I want to propose an autocomplete list (jquery ui 1.8) with some words in bold font.
The JSON source looks like :
{"especes":[{"fk_sp":number,"nom_espece":name,"nom_valide":0 or 1}].
My script is like that :
$(function(){
$('#id').autocomplete({
source: function(request, response) {
$.getJSON("fichier.php", {
term: request.term
}, function(data) {
var array = data.error ? [] : $.map(data.especes, function(m) {
return {
label: m.nom_espece,
value: m.fk_sp,
valid: m.nom_valide
};
});
response(array);
});
},
select: function (event, ui) {
$("#espece").val(ui.item.label);
$("#fk_sp").val(ui.item.value);
}
}).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( item.valid == '1' ? "<b>" + item.label + "</b>" : item.label)
.appendTo( ul );
};
});
If I use :
.data( "ui-autocomplete" ) => I have the good selectable list without the bold lines,
.data( "ui-Autocomplete" ) ou .data( "uiAutocomplete" ) => nothing works,
and if I juste write ._renderItem without .data( "ui-autocomplete" ) => I have a pretty list with the good names in bold, but I can't select any name of the list !
I don't find where is my error (I suppose it is somwhere with the "select :" part).
Related
I have the following code. It generates no js errors. Can't get the autocomplete to display any results:
$(function() {
$.ajax({
url: "data.xml",
dataType: "xml",
cache: false,
success: function (xmlResponse) {
var data_results = $("Entry", xmlResponse).map(function () {
return {
var1: $.trim($("Partno", this).text()),
var2: $.trim($("Description", this).text()),
var3: $.trim($("SapCode", this).text()),
var4: $("Title", this).text(),
var5: $.trim($("File", this).text()),
var6: $.trim($("ItemID", this).text())
};
}).get();
$("#searchresults").autocomplete({
source: data_results,
minLength: 3,
select: function (event, ui) {
...
}
}).data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" ).data("item.autocomplete", item)
.append( "<a>" + item.var1 + "<br>" + item.var2 + "</a>")
.appendTo( ul );
};
}
});
Any ideas what I might be missing? Thanks in advance.
It seems that .data('autocomplete') is now .data('ui-autocomplete').
Source: http://jqueryui.com/upgrade-guide/1.10/#removed-data-fallbacks-for-widget-names
By default, autocomplete expects your source array to contain objects with either a label property, a value property, or both.
With that in mind you have two options:
Add a label or value property to your source objects when you process the array from your AJAX call:
var data_results = $("Entry", xmlResponse).map(function () {
return {
var1: $.trim($("Partno", this).text()),
var2: $.trim($("Description", this).text()),
var3: $.trim($("SapCode", this).text()),
var4: $("Title", this).text(),
var5: $.trim($("File", this).text()),
var6: $.trim($("ItemID", this).text()),
value: $.trim($("Description", this).text())
};
}).get();
The value you assign will be used on focus, select, and to search on.
Change the source function to perform custom filtering logic:
$("#searchresults").autocomplete({
source: function (request, response) {
var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
response($.grep(data, function (value) {
return matcher.test(value.var1) ||
matcher.test(value.var2);
/* etc., continue with whatever parts of the object you want */
}));
},
minLength: 3,
select: function (event, ui) {
event.preventDefault();
this.value = ui.var1 + ui.var2;
},
focus: function (event, ui) {
event.preventDefault();
this.value = ui.var1 + ui.var2;
}
}).data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" ).data("item.autocomplete", item)
.append( "<a>" + item.var1 + "<br>" + item.var2 + "</a>")
.appendTo( ul );
};
Note that with this strategy you have to implement custom select and focus logic.
I tried to use jQuery combobox (fiddle) in my Mozilla Firefox addon. But AMO editors rejected my Addon after reviewing stating that my javascript does unsafe HTML insertion with unsanitized data. Parts of the code stated as unsafe all belong to the code on official jQuery Ui page for combobox. I am also writing the code below. Removing this piece of code throws error if I try to create a combobox.
It makes me wonder why combobox isn't already included in jQuery and why do I have to put this snippet inside my code? Am I doing anything wrong here. Alternatively Can someone suggest me how can I make this code taken from official jquery page safe and sanitized?
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "";
var input = this.input = $( "<input>" )
.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
// remove invalid value, as it didn't match anything
$( this ).val( "" );
select.val( "" );
input.data( "autocomplete" ).term = "";
return false;
}
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
this.button = $( "<button type='button'> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-button-icon" )
.click(function() {
// close if already visible
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
// work around a bug (likely same cause as #5265)
$( this ).blur();
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
input.focus();
});
},
destroy: function() {
this.input.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
})( jQuery );
I have got the autocomplete to work but with errors. How would i format the response code correctly?
Response Code:
{
label: "Label 1",
value: "27"
},
{
label: "Label 2",
value: "18"
},
{
label: "Dave",
value: "25"
},
{
label: "Jacqui Potatoes",
value: "17"
}
Javascript:
$("#account_search .ac_input").autocomplete({
minLength: 0,
source: base_url + "accounts/ac_results/account_name",
dataType: "json",
type: "POST",
}).data( "autocomplete" )._renderItem = function( ul, item ) {
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "<br>" + item.desc + "</a>" )
.appendTo( ul );
return $( "<li></li>" );
};
I think the .data() function is the problem although it is working somehow. I would like to access both the label and value
You've got an error in the _renderItem function (you should call .data on the newly created <li></li>):
.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "<br>" + item.value + "</a>" )
.appendTo( ul );
};
I also replaced item.desc which did not exist on your JSON response with item.value.
As a sidenote, you may not need to override that function at all. You only need to use it if you want to change the way each item looks in the suggestion list.
Also, make sure to remove that extra comma in the options object. Additionally, the options dataType and type are not valid options anyway:
$("#account_search .ac_input").autocomplete({
minLength: 0,
source: base_url + "accounts/ac_results/account_name"
});
Example (local data source): http://jsfiddle.net/nG8Q4/
I'm trying to use this example http://jqueryui.com/demos/autocomplete/#combobox . But it shows blank option by default. instead of "Select one...". How to fix that problem?
And one more question: I don't use "show underlying menu" buton as in show in example. Is there any unused pc of code for that button in JS code?
it shows blank option by default. instead of "Select one...". How to fix that problem?
The reason this is occurring is this piece of code in the _create function:
value = selected.val() ? selected.text() : "";
Just change the false portion of the ternary to say "Select One":
value = selected.val() ? selected.text() : "Select one...";
Here's the modified widget for reference:
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "Select One...";
var input = this.input = $( "<input>" )
.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
$( this ).val( "" );
select.val( "" );
input.data( "autocomplete" ).term = "";
return false;
}
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
this.button = $( "<button type='button'> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-button-icon" )
.click(function() {
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
$( this ).blur();
input.autocomplete( "search", "" );
input.focus();
});
},
destroy: function() {
this.input.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
I don't use "show underlying menu" buton as in show in example. Is there any unused pc of code for that button in JS code?
Yes, you're safe to remove that button. In fact, all you need is a select element to initialize the widget on.
Here's an example of the combobox without a button and with "Select one..." as the default text: http://jsfiddle.net/andrewwhitaker/MgjRy/
I have the following code:
// Autocomplete search
$("#shop_search").autocomplete({
source: '<%= spotify_search_path(:json) %>',
minLength: 1,
select: function(event, ui) {
append_place(ui.item.name, ui.item.id, ui.item.shop_type, ui.item.address_geo, ui.item.contact, ui.item.email, ui.item.web);
$("#shop_search").val('');
}
}).data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + "<span class='autocomplete_link'>" + item.name + "</span>" + "<br />" + "<span class='autocomplete_address'>" + item.address_geo + "</span>" + "</a>" )
.appendTo( ul );
$(".ui-autocomplete-loading").ajaxStart(function(){
$(this).show();
});
$(".ui-autocomplete-loading").ajaxStop(function(){
$(this).hide();
});
};
Currently it only shows the drop down autocomplete when there is search result. I want it to show "No matches found" when nothing could be found. What should I add into the code?
Thanks.
If you use a jQuery ajax call for the source, you can append "No results found" to the results if there aren't any. Then on the select method, you can simply check to see if the item is the "no results found" item that you added and if so, do nothing. Here I identified that by checking to see if the id was equal to zero.
$("#shop_search").autocomplete({
source: function (request, response) {
$.ajax({
url: "<%= spotify_search_path(:json) %>",
data: {
term: request.term
},
success: function (data) {
if (data.length == 0) {
data.push({
id: 0,
label: "No results found"
});
}
response(data);
}
});
},
select: function (event, ui) {
if (ui.item.id != 0) {
append_place(ui.item.name, ui.item.id, ui.item.shop_type, ui.item.address_geo, ui.item.contact, ui.item.email, ui.item.web);
$("#shop_search").val('');
}
}
});
You'll need to do some work on your template to get the "no results found" to display properly, but this should get you on the right track.
You can just check if item is null or 0.
If item is 0 or null append "No matches found" else append the item. That's basically the whole logic.
May be this helps
source: function( request, response ) {
$.getJSON( url, {
term: extractLast( request.term )
}, response )
.error(function() {
console.log("no results");
});
},
$( "#jsonNameSearch" ).autocomplete({
// This is the source of the autocomplete, in the success method if the
// length of the response is zero then highlight the field indicating no match.
source: function( request, response ) {
$.getJSON( 'jsonAutocomplete.ajax?dataType=drivers', {
term: request.term
}, response )
.success(function(data) {
(data.length == 0) ? $( "#jsonNameSearch" ).addClass('nomatch') : $( "#jsonNameSearch" ).removeClass('nomatch');
});
},
select: function( event, ui ) {
if (ui.item) self.location.replace('driverModify.htm?id='+ui.item.id);
}
});