I have tried following code picked from plunker to reduce ajax request to database. JSON format is also generated fine as per example in text file.
But when i'am trying to populate autocomplete options it's showing only one character of beginning. But when i use json output directly with items variable then it works fine.
Plunker
Plunker Link
JSON example in Keywords.txt file
["Mis","Operation","Operation Manager","Php","Sales","Telecalling","Analytics","Ceo","Commercials"];
Code
$(function()
{
var items = 'Keywords.txt';
function split( val )
{
return val.split( /,\s*/ );
}
function extractLast( term )
{
return split( term ).pop();
}
$( "#keyword" )
.autocomplete(
{
minLength: 1,
source: function( request, response )
{
response( $.ui.autocomplete.filter(items, extractLast( request.term ) ) );
},
focus: function()
{
return false;
},
select: function( event, ui )
{
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
});
I think that your problem is that you have a string, try to parse the response:
$.get('Keywords.txt').then(function(keywords){
items = JSON.parse(keywords);
});
Related
I have an autocomplete function that filters through local json to return results to a textbox, however on selecting a location, the autocomplete does not fill the text box. I have tried to include a select method as per the docs but it breaks my functionality. Where should I include the select in my codebase?
Autocomplete function:
$('#autocomplete').autocomplete({
minLength: 1,
source: function(request, response) {
var data = $.grep(suggestion, function(value) {
return value.city.substring(0, request.term.length).toLowerCase() == request.term.toLowerCase(); // Here the suggestion array is filtered based on what the user has typed. User input will be captured in the request.term
});
response(data); // this will return the filtered data which will be attached with the input box.
}
}).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "ui-autocomplete-item", item )
.append( "<a>" + item.city + "," + item.country + "</a>" )
.appendTo( ul ); // here we are creating and appending appending element based on the response object we got after filtering
};
});
Data
var suggestion =
[
{"id":"1","name":"Goroka","city":"Goroka","country":"Papua New Guinea","iata":"GKA","icao":"AYGA","latitude":"-6.081689","longitude":"145.391881","altitude":"5282","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"2","name":"Madang","city":"Madang","country":"Papua New Guinea","iata":"MAG","icao":"AYMD","latitude":"-5.207083","longitude":"145.7887","altitude":"20","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"3","name":"Mount Hagen","city":"Mount Hagen","country":"Papua New Guinea","iata":"HGU","icao":"AYMH","latitude":"-5.826789","longitude":"144.295861","altitude":"5388","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"4","name":"Nadzab","city":"Nadzab","country":"Papua New Guinea","iata":"LAE","icao":"AYNZ","latitude":"-6.569828","longitude":"146.726242","altitude":"239","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"5","name":"Port Moresby Jacksons Intl","city":"Port Moresby","country":"Papua New Guinea","iata":"POM","icao":"AYPY","latitude":"-9.443383","longitude":"147.22005","altitude":"146","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
]
The select can be placed before or after the source in your case, as long as it stays in the autocomplete object as a property. You can follow this example:
$('#autocomplete').autocomplete({
minLength: 1,
source: function (request, response) { ... },
select: function (event, ui) {
event.preventDefault();
// [...] your code here
return false;
}
}).data( "ui-autocomplete" )._renderItem = function( ul, item ) { ... };
I have an autocomplete function that was working with a local json source. Given that it's 16k lines of code, I want to move this to an external json file. However I can't seem to get it working with the external source file. Can anyone point me in the right direction? At the moment this code does not work, but also does not return any errors to the console.
Autocomplete script
$(function() {
$.ajax({
url: "javascripts/airports.json",
dataType: "json",
success: function(request, response) {
var data = $.grep(suggestion, function(value) {
return value.city.substring(0, request.term.length).toLowerCase() == request.term.toLowerCase();
});
$('#autocomplete').autocomplete({
minLength: 1,
source: data,
focus: function(event, ui) {
$('#autocomplete').val(ui.item.city,ui.item.country);
return false;
},
select: function(event, ui) {
$('#autocomplete').val(ui.item.name);
return false;
}
}).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "ui-autocomplete-item", item )
.append( "<a>" + item.city + "," + item.country + "</a>" )
.appendTo( ul );
};
}
});
});
External data structure
var suggestion =
[
{"id":"1","name":"Goroka","city":"Goroka","country":"Papua New Guinea","iata":"GKA","icao":"AYGA","latitude":"-6.081689","longitude":"145.391881","altitude":"5282","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"2","name":"Madang","city":"Madang","country":"Papua New Guinea","iata":"MAG","icao":"AYMD","latitude":"-5.207083","longitude":"145.7887","altitude":"20","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"3","name":"Mount Hagen","city":"Mount Hagen","country":"Papua New Guinea","iata":"HGU","icao":"AYMH","latitude":"-5.826789","longitude":"144.295861","altitude":"5388","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"4","name":"Nadzab","city":"Nadzab","country":"Papua New Guinea","iata":"LAE","icao":"AYNZ","latitude":"-6.569828","longitude":"146.726242","altitude":"239","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
,
{"id":"5","name":"Port Moresby Jacksons Intl","city":"Port Moresby","country":"Papua New Guinea","iata":"POM","icao":"AYPY","latitude":"-9.443383","longitude":"147.22005","altitude":"146","timezone":"10","dst":"U","tz":"Pacific/Port_Moresby"}
]
Your response should be a JSON object (array) where each item is an object with id, label and value keys.
The items in your json files doesn't have the label and value keys, so the autocomplete can't really show them.
Best solution - change the content of the file/response to follow the id/label/value structure.
If you can't do this - you can use the _renderItem function to create your own items in the autocomplete based on the content of the json file:
$('#autocomplete').autocomplete({
...
_renderItem: function( ul, item ) {
return $( "<li>" )
.append( item.name )
.appendTo( ul );
}
...
});
I'm using the jQuery combobox widget which works fine, but is causing some issues when added dynamically.
What should happen
Visitor uses the combobox to filter/select valid users to add to a
list.
The list has no max number of users that can be added.
There's a [+] toggle button at the end of each user field that allows the Visitor to add another user to the list.
Clicking the button makes an ajax call to add more users to the list, allowing there to be no limit to the max number of users.
Initially, 10 user fields are loaded on screen, and then when they click the [+] button towards the end, the ajax call adds another 10 to the list.
What's Happening
When the form with the list of users is submitted, the users from the initial 10 fields appear fine, but any fields added as part of the ajax call are returned as empty.
Here's the code:
combobox:
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var input,
that = this,
wasOpen = false,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "",
wrapper = this.wrapper = $( "<span>" )
.addClass( "ui-combobox" )
.insertAfter( select );
function removeIfInvalid( element ) {
var value = $( element ).val(),
matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( value ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
}
}
input = $( "<input>" )
.appendTo( wrapper )
.val( value )
.addClass( "ui-state-default ui-combobox-input " )
.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;
that._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
removeIfInvalid( this );
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
$( "<a>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
// .tooltip()
.appendTo( wrapper )
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-combobox-toggle" )
.mousedown(function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.click(function() {
input.focus();
// close if already visible
if ( wasOpen ) {
return;
}
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
});
// input.tooltip({
// // tooltipClass: "tool_toplft"
// });
},
_destroy: function() {
this.wrapper.remove();
this.element.show();
}
});
})( jQuery );
ajax code:
$('body').on('click','.add_usr', function(){
if($('.box.noshow').length == 3){
$(this).fadeOut(800);
var count = parseInt($(this).attr('data-ctr')) +1;
$.post('/base/process.php', {action: 'team_add_usr_select', 'count': count}, function(data){
$('.box:last').after(data.output);
});
}
$('.box.noshow').first().fadeIn(800).removeClass('noshow');
$('.box').children('select').removeAttr('disabled');
$('.box.noshow').each(function(){
$(this).children('select').attr('disabled', 'disabled');
});
$('.add_usr').css('display','none');
$('.box:visible').last().children('.add_usr').css('display','inline-block');
if($('.box:visible').length > 1){
$('.del_usr').css('display', 'inline-block');
}
return false;
});
Again, the combobox is working correctly, but when I submit the form, the fields are present but blank.
UPDATE
data outputs an object with the details for me, including the original form information.Here's an example of the output:
form: Object
form: "team_add"
id_leader: "1"
id_team: ""
team_name: "test"
usr: Object
1: "1"
2: "13"
3: "521"
4: "533"
5: "2"
6: "3"
7: "816"
This example was sent with 12 users added. The new fields are added to the form after entry #7 is filled and clicked. Also, I've noticed in this instance it stopped showing additional fields. Previously when testing, it would list 8: "". Now I'm more confused.
i use jqueryui for search in my site just like facebook
jquery code:
//search main
function split( val ) {
return val.split( );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#mainsearch" ).bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "ui-autocomplete" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
source: function( request, response ) {
$.getJSON( "/block/search.php", {
term: extractLast( request.term )
}, response );
},
search: function() {
var term = extractLast( this.value );
if ( term.length < 2 ) {
return false;
}
},
focus: function() {
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
window.location.replace(ui.item.url);
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
php code:
while($f = mysqli_fetch_array($s,MYSQLI_ASSOC)){
if($userid != $f['id']){
$name = $f['name'].' '.$f['family'];
$url = $siteurl.$f['username'].'/';
array_push($results, array('id' => $f['id'],'value' => $name,'url' => $url));
}
}
echo json_encode($results);
but if i insert image tag like:
<img src='something'>
its just show < img > text not an image when its show result
there is anyway to solve it?
thank you
From the jQuery-ui docs: "If you want the label to be treated as html you can use Scott González' html extension".
ok i solve this problem with code blow:
function split( val ) {
function extractLast( term ) {
return split( term ).pop();
}
$( "#mainsearch" ).autocomplete({
source: function( request, response ) {
$.getJSON( "/block/search.php", {
term: extractLast( request.term )
}, response );
},
search: function() {
var term = extractLast( this.value );
if ( term.length < 2 ) {
return false;
}
},
focus: function() {
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
window.location.replace(ui.item.url);
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
})
.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li style='clear:both'>" )
.append( ""+item.value+"")
.appendTo( ul );
};return val.split( );
}
and php code:
while($f = mysqli_fetch_array($s,MYSQLI_ASSOC)){
if($userid != $f['id']){
$name = $f['name'].' '.$f['family'];$img = getimagesizes($f['image'],50);
$url = $siteurl.$f['username'].'/';
array_push($results, array('id' => $f['id'],'img' => $img,'value' => $name,'url' => $url));
}
}
echo json_encode($results);
.data must convert to html and show your result
as you can see in my qustion example in jqueryui is completely diffrent with this
but with this you can put html in your auto complete :)
I have an issue where I have added two feature classes and it means that I sometimes get results which are duplicated in the autosuggest. I wondered if there is a way I can some how check for duplicates and fetch an alternative instead of showing the same result twice.
This is my code here (working): http://jsfiddle.net/spadez/nHgMX/4/
$(function() {
jQuery.ajaxSettings.traditional = true;
function log( message ) {
$( "<div>" ).text( message ).prependTo( "#log" );
$( "#log" ).scrollTop( 0 );
}
$( "#city" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "http://ws.geonames.org/searchJSON",
dataType: "jsonp",
data: {
featureClass: ["A","P"],
style: "full",
maxRows: 7,
name_startsWith: request.term,
country: "UK"
},
success: function( data ) {
response( $.map( data.geonames, function( item ) {
return {
label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
value: item.name
}
}));
}
});
},
minLength: 1,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.label :
"Nothing selected, input was " + this.value);
},
open: function() {
$( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
},
close: function() {
$( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
}
});
});
Any help or information would be much appreciated
Hard to tell exactly what you're asking. But to remove duplicates from an array of objects, you can use underscore's _.uniq()
$.map( _.uniq(data.geonames, false, function(o){return o.adminName1})
Here's a jsfiddle that doesn't show duplicates. But again, it's hard to tell what a duplicate really is from your structure, but this code should move you in the right direction
You don't have use underscore, it's really easy to implement uniq on your own, just look at azcn2503's answer
I modified the code slightly so that it does the following:
Puts all the autocomplete entries in to an object, with the autocomplete value as the key
Converts this object back in to an array and returns it
By doing this, any duplicate keys simply overwrite the previous one.
The success function now looks like this:
success: function( data ) {
var x = $.map( data.geonames, function( item ) {
return {
label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
value: item.name
}
});
// Create an object to easily filter out duplicates (key of same name will simply be reused)
var x2 = {};
for(var i in x) {
x2[x[i].value] = x[i];
}
// Create a new array that simply converts the object in to a de-duplicated array
var x3 = [];
for(var i in x2) {
x3.push(x2[i]);
}
// Return the array
response(x3);
}
I have tested it and it seems to be working, although your issue with the duplicates appearing in the first place is not something I can replicate.
Updated fiddle: http://jsfiddle.net/nHgMX/8/
If your ajax call is returning an array with the response value, you can run it through a plugin to remove duplicate entries. Here's a plugin that I found on another SO thread somewhere a while back.
function ArrayNoDupes(array) {
var temp = {};
for (var i = 0; i < array.length; i++)
temp[array[i].value] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
}
I may be mistaken, but you would implement it into your existing code by changing the following line:
source: function( ArrayNoDupes(request), response )
EDIT: Updated function per Juan Mendes' comment