I'm trying to achieve two things using jQuery UI Autocomplete v1.8.14.
1) Use a space delimited word search for all matches (independent of order): (eg search "some heart", matches "win the heart of someone")
2) Highlight all of the matches: (eg search "some heart", matches "win the heart of some one")
This 开发者_如何学编程question has been asked multiple times, but I have been unable to find simple, reproducible code showing correct implementation.
I've started a JS Fiddle: http://jsfiddle.net/KywMH/2/. If possible please answer in the form of reproducible code.
Thank you.
Here's one way: See it in action at jsFiddle.
var availableTags = [
"win the day",
"win the heart of",
"win the heart of someone"
];
var autoCompNodeId = 'tags';
$( "#" + autoCompNodeId ).autocomplete ( {
source: function (requestObj, responseFunc) {
var matchArry = availableTags.slice (); //-- Copy the array
var srchTerms = $.trim (requestObj.term).split (/\s+/);
//--- For each search term, remove non-matches.
$.each (srchTerms, function (J, term) {
var regX = new RegExp (term, "i");
matchArry = $.map (matchArry, function (item) {
return regX.test (item) ? item : null;
} );
} );
//--- Return the match results.
responseFunc (matchArry);
},
open: function (event, ui) {
/*--- This function provides no hooks to the results list, so we have to trust the
selector, for now.
*/
var resultsList = $("ul.ui-autocomplete > li.ui-menu-item > a");
var srchTerm = $.trim ( $("#" + autoCompNodeId).val () ).split (/\s+/).join ('|');
//--- Loop through the results list and highlight the terms.
resultsList.each ( function () {
var jThis = $(this);
var regX = new RegExp ('(' + srchTerm + ')', "ig");
var oldTxt = jThis.text ();
jThis.html (oldTxt.replace (regX, '<span class="srchHilite">$1</span>') );
} );
}
} );
Because the old highlight function is no longer available, we use the open
event to highlight the search terms. Pay special attention not to highlight inside tags.
The solution below solves these two problems by
1) Modifying the autocomplete source function
2) Modifying .data('autocomplete')._renderItem
A working JS Fiddle can be found here: http://jsfiddle.net/W8MKt/7/
Any critique of the code or the solution would be appreciated.
Thank you.
<div class="ui-widget">
<label for="tags">Multi-word search: </label>
<input id="tags">
</div>
$(function() {
var availableTags = [
"win the day",
"win the heart of",
"win the heart of someone"
];
$( "#tags" ).autocomplete({
source: function(request, response) {
var aryResponse = [];
var arySplitRequest = request.term.split(" ");
for( i = 0; i < availableTags.length; i++ ) {
var intCount = 0;
for( j = 0; j < arySplitRequest.length; j++ ) {
regexp = new RegExp(arySplitRequest[j]);
var test = availableTags[i].match(regexp);
if( test ) {
intCount++;
} else if( !test ) {
intCount = arySplitRequest.length + 1;
}
if ( intCount == arySplitRequest.length ) {
aryResponse.push( availableTags[i] );
}
};
}
response(aryResponse);
}
}).data('autocomplete')._renderItem = function( ul, item ) {
var srchTerm = $.trim(this.term).split(/\s+/).join ('|');
var strNewLabel = item.label;
regexp = new RegExp ('(' + srchTerm + ')', "ig");
var strNewLabel = strNewLabel.replace(regexp,"<span style='font-weight:bold;color:Blue;'>$1</span>");
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + strNewLabel + "</a>" )
.appendTo( ul );
};
});
I've found that using the built in autocomplete filter to reduce your search space does the trick as well (and is much simpler):
source: function( request, response ) {
var searchspace = availableTags;
// split by space or however you want to split up your search phrase into terms
var searchwords = request.term.split(" ");
$.each(searchwords, function() {
searchspace = $.ui.autocomplete.filter(searchspace, this);
});
// in case you don't want to return the whole thing, if your searchspace is large
var mySlice = searchspace.slice(0, 10);
response(mySlice);
},
}
精彩评论