I am processing nested getJSON data in the below code, where > 1 record is returned and sorted by autocomplete.
{
"ok": [
{
"myName": "Back Office",
"myModule": "back01",
"myDesc": "Developing a the platform"
},
......
]
}
When the final data (lets say 6 matching records) are passed to .autocomplete( "instance" ) each call to update return $( "<li>" ) seems to overwrite the previous returned JSON data, meaning only the last record is displayed instead of the 6 that are valid Is the JSON.
I note that when debugging the .autocomplete routine is looping through the correct number of times to match the number of records, it is just that each loop seems to overwrite the <li> with a fresh object rather than append to the previous record.
Why is the overwrite happening?
thanks
Art!
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$( function() {
$( "#my_module_in" ).autocomplete({
minLength: 1,
source: function( request ,response){
$.getJSON("https://api.myapi.com/getStuff", function (data) {
$.each(data, function (okKey, val00) {
if ( okKey === 'ok') {
$.each(val00, function (key201, val201) {
response($.map(data, function (item) {
return {
label: val201.myName,
value: val201.myModule+"_"+val201.myDesc,
}
}))
})
}else{
console.log("error:noJson");
}
})
});
},
focus: function( event, ui ) {
console.log(ui.item.label);
return false;
},
select: function( event, ui ) {
$( "#my_module_in" ).val( ui.item.label);
$( "#my_module" ).val( ui.item.value);
$( "#my_module_description" ).html( ui.item.value );
return false;
}
})
.autocomplete( "instance" )._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<div>" + item.label + "<br>" + item.value + "</div>" )
.appendTo( ul );
};
});
</script>
</head>
<body>
<div id="my_module_label">Op_Group</div>
<input id="my_module_in">
<input type="hidden" id="my_module">
<p id="my_module_description"></p>
You need an empty array containing the results found in the $.each ($.map()) operation. Then, in the $.map() function, for every item push the current object in the empty array.
Finally, call the response callback function with the array that you filled.
var result = [];
$.each(val00, function(key201, val201) {
$.map(data, function(item) {
result.push({
label: val201.myName,
value: val201.myModule + "_" + val201.myDesc
});
});
});
response(result);
Something like this:
$(function() {
$("#my_module_in").autocomplete({
minLength: 1,
source: function(request, response) {
$.getJSON("https://gist.githubusercontent.com/dannyjhonston/51e9ea30dddd09d9f82a8e78b8a51de2/raw/9ad8b1b40377a6807548b444491846dd13025902/getStuff.json", function(data) {
$.each(data, function(okKey, val00) {
if (okKey === 'ok') {
var result = [];
$.each(val00, function(key201, val201) {
$.map(data, function(item) {
result.push({
label: val201.myName,
value: val201.myModule + "_" + val201.myDesc
});
});
});
response(result);
} else {
console.log("error:noJson");
}
});
});
},
focus: function(event, ui) {
console.log(ui.item.label);
return false;
},
select: function(event, ui) {
$("#my_module_in").val(ui.item.label);
$("#my_module").val(ui.item.value);
$("#my_module_description").html(ui.item.value);
return false;
}
})
.autocomplete("instance")._renderItem = function(ul, item) {
return $("<li>").append("<div>" + item.label + "<br />" + item.value + "</div>").appendTo(ul);
};
});
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<div id="my_module_label">Op_Group</div>
<input id="my_module_in" type="text">
<input type="hidden" id="my_module">
<p id="my_module_description"></p>
Related
I have been using the jQuery ‘Autocomplete Widget’ for a number of years now. This has always been done but passing a value with ‘term’ to the PHP SQL code like this;
$( "#cs1" ).autocomplete({
autoFocus: true,
minLength: 3,
source: "gethint.php",
select: function( event, ui ) {
// This if undes the readonly on the Fname input field below
if ( ui.item.label == 'NONHAM' ) {$('#Fname').prop('readonly', false);}
$( "#cs1" ).val( ui.item.label );
$( "#hints" ).val( ui.item.value );
$( "#Fname" ).val( ui.item.desc );
var nc = $( "#thenetcallsign" ).html();
//return false;
}
})
.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<a>" + item.label + " ---> " + item.desc + "</a>" )
.appendTo( ul );
};
});
But now I have to add another condition to the SQL code to return a more detailed value. The value for this additional condition is;
var nc = $( "#thenetcallsign" ).html();
The problem is I don’t know how to add this to ‘term’ or a separate variable and pass it to gethint.php using the ‘Autocomplete’ widget.
Once I get the extra value to the PHP program I know what to do.
Would somebody please explain or show me how to do this?
You might have to stringify it but pass the extraParams
extraParams: { type: "CoolCode" },
var nc = $("#thenetcallsign").html();
$("#cs1").autocomplete({
autoFocus: true,
minLength: 3,
source: "gethint.php",
extraParams: {
nc: nc
},
select: function(event, ui) {
// This if undes the readonly on the Fname input field below
if (ui.item.label == 'NONHAM') {
$('#Fname').prop('readonly', false);
}
$("#cs1").val(ui.item.label);
$("#hints").val(ui.item.value);
$("#Fname").val(ui.item.desc);
var nc = $("#thenetcallsign").html();
//return false;
}
})
.data("ui-autocomplete")._renderItem = function(ul, item) {
return $("<li>")
.append("<a>" + item.label + " ---> " + item.desc + "</a>")
.appendTo(ul);
};
});
source could be a function in order to get more flexibility
$( "#cs1" ).autocomplete({
/* ... */
source: function(request, response) {
$.getJSON( "gethint.php", {
term: request.term ,
nc: $( "#thenetcallsign" ).html()
}, response );
},
/* ... */
});
http://jsfiddle.net/Share_Knowledge/dgtqptr7/
I am trying to use autocomplete functionality of jquery ui into my project But i have no idea why THE SECOND $('.search').autocomplete() is
not working.
maybe i have to use $.noConflict()
if yes how i can use it $.noConflict()
would any body tell me how to use it to solve this problem out
any help please i would be thankful
using firebug i get these errors
POST http://localhost/autoservice/public_html/tickets/load_spareparts/11/instance
First
i don't what is the word instance coming from..???
here is the order of the js files
-js/jquery-ui.min.js
-jquery.autocomplete.js
jQuery(document).ready(function($) {
$.ajaxSetup( { type: "post" } );
// THIS IS WORKING PERFECTLY
$("#item").autocomplete(url+'/item_search', {
minChars:0,
selectFirst: false,
width: 749,
multiple: false,
matchContains: true,
formatItem: formatItem,
formatResult: formatResult
});
// THIS SHOW THE ERROR WHICH MENTIONED UP THERE
// IT'S NOT WORKING
$('#search').autocomplete({
minLength: 0,
source: path3+'/get_spareparts',
focus: function( event, ui) {
$('#search').val( ui.item.item_id );
return false;
},
select: function(event, ui) {
output = '';
output += '<tr>';
output += '<td>'+ui.item.item_id+'</td>';
output += '<input type="hidden" value="'+ui.item.id+'" name="item_id"></td>';
output += '<td>'+ui.item.item_name+'</td>';
output += '<td>'+ui.item.price+'</td>';
output += '<td><input type="text" name="qty" value="" size="1" class="qty"></td>';
output += '<td>'+ui.item.desc+'</td>';
output += '<td>Delete</td>';
output += '</tr>';
$('.inject').append(output);
$(this).val('');
deleteItem(); // DELETE ITEM
return false;
}
}) .autocomplete( "instance" )._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<a>" + item.desc + "<br>" + item.item_id + "</a>" )
.appendTo( ul );
};
function deleteItem () {
$('.spareTrash').on('click', function(event) {
event.preventDefault();
$(this).parent().parent().fadeOut(900, function(){ $(this).remove();});
});
}
}); // END READY JQUERY
I have created jQuery UI autocomplete which is working very good. But my requirement is that what I display as list should also select same in text box. But it is not selecting
For example list like XXX (XYZ) but when I select it only select XXX not XXX (XYZ)
what I am missing !!
function getDeptStations() {
$("#txDestination").autocomplete({
source: function (request, response) {
var term = request.term;
var Query = "";
if (lang === "en")
Query = "City_Name_EN";
else if (lang === "fr")
Query = "City_Name_FR";
if (lang === "de")
Query = "City_Name_DE";
if (lang === "ar")
Query = "City_Name_AR";
var requestUri = "/_api/lists/getbytitle('Stations')/items?$select=City_Code," + Query + "&$filter=startswith(" + Query + ",'" + term + "')";
$.ajax({
url: requestUri,
type: "GET",
async: false,
headers: {
"ACCEPT": "application/json;odata=verbose"
}
}).done(function (data) {
if (data.d.results) {
response($.map(eval(data.d.results), function (item) {
return {
label: item[Query] + " (" + item.City_Code + ")",
value: item[Query],
id: item[Query]
}
}));
}
else {
}
});
},
response: function (event, ui) {
if (!ui.content.length) {
var noResult = { value: "", label: "No cities matching your request" };
ui.content.push(noResult);
}
},
select: function (event, ui) {
$("#txDestination").val(ui.item.label);
cityID = ui.item.id;
},
minLength: 1
});
}
Almost there, just return a false from select event.
select: function (event, ui) {
$("#txDestination").val(ui.item.label);
cityID = ui.item.id;
return false;
},
or Simply
select: function (event, ui) {
alert(ui.item.id);
return false;
},
This will guide jquery autocomplete to know that select has set a value.
Update: This is not in the documentation, I figured out by digging into source code, took me some time. But indeed it deserves to be in the doc or in options.
in this case you have to options
the obvious one set value:item[Query] + " (" + item.City_Code + ")" but I am assuming this is not the option.
Handle the selection by yourself first check the api doc and you will see event like below. with event.target you can access your input with ui you can access you selected item.
$( ".selector" ).autocomplete({
select: function( event, ui ) {}
});
I understand its been answered already. but I hope this will help someone in future and saves so much time and pain.
After getting the results in autocomplete you can use below code for keeping the value in the autocomplete textbox field. (you can replace 'CRM.$' with '$' or 'jQuery' depending on your jQuery version)
select: function (event, ui) {
var label = ui.item.label;
var value = ui.item.value;
//assigning the value to hidden field for saving the id
CRM.$( 'input[name=product_select_id]' ).val(value);
//keeping the selected label in the autocomplete field
CRM.$('input[id^=custom_78]').val(label);
return false;
},
complete code is below: This one I did for a textbox to make it Autocomplete in CiviCRM. Hope it helps someone
CRM.$( 'input[id^=custom_78]' ).autocomplete({
autoFill: true,
select: function (event, ui) {
var label = ui.item.label;
var value = ui.item.value;
// Update subject field to add book year and book product
var book_year_value = CRM.$('select[id^=custom_77] option:selected').text().replace('Book Year ','');
//book_year_value.replace('Book Year ','');
var subject_value = book_year_value + '/' + ui.item.label;
CRM.$('#subject').val(subject_value);
CRM.$( 'input[name=product_select_id]' ).val(ui.item.value);
CRM.$('input[id^=custom_78]').val(ui.item.label);
return false;
},
source: function(request, response) {
CRM.$.ajax({
url: productUrl,
data: {
'subCategory' : cj('select[id^=custom_77]').val(),
's': request.term,
},
beforeSend: function( xhr ) {
xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
},
success: function(result){
result = jQuery.parseJSON( result);
//console.log(result);
response(CRM.$.map(result, function (val,key) {
//console.log(key);
//console.log(val);
return {
label: val,
value: key
};
}));
}
})
.done(function( data ) {
if ( console && console.log ) {
// console.log( "Sample of dataas:", data.slice( 0, 100 ) );
}
});
}
});
PHP code on how I'm returning data to this jquery ajax call in autocomplete:
/**
* This class contains all product related functions that are called using AJAX (jQuery)
*/
class CRM_Civicrmactivitiesproductlink_Page_AJAX {
static function getProductList() {
$name = CRM_Utils_Array::value( 's', $_GET );
$name = CRM_Utils_Type::escape( $name, 'String' );
$limit = '10';
$strSearch = "description LIKE '%$name%'";
$subCategory = CRM_Utils_Array::value( 'subCategory', $_GET );
$subCategory = CRM_Utils_Type::escape( $subCategory, 'String' );
if (!empty($subCategory))
{
$strSearch .= " AND sub_category = ".$subCategory;
}
$query = "SELECT id , description as data FROM abc_books WHERE $strSearch";
$resultArray = array();
$dao = CRM_Core_DAO::executeQuery( $query );
while ( $dao->fetch( ) ) {
$resultArray[$dao->id] = $dao->data;//creating the array to send id as key and data as value
}
echo json_encode($resultArray);
CRM_Utils_System::civiExit();
}
}
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
I am having great difficulty in successfully parsing a JSON file to use within JQuery UI autocomplete
Please see my dev page: http://www.zyredesign.com/autocomplete
The JSON isn't organised as well as I would have hoped as the items keys are ID's eg:
{"140":"Abarth",
"375":"Acura"
}
Etc....
Here is my javascript attempt:
$(document).ready(function() {
$('#cars').autocomplete({
source: function()
{
$.getJSON('json.json', function(data)
{
cars_array = new Array();
$.each(data, function(k, v) {
cars_array.push(v);
})
alert( cars_array);
return cars_array;
})
},
minLength: 3,
focus: function( event, ui ) {},
select: function( event, ui ) {
$('#suggestions').html(ui);
return false;
}
});
});
/*
function get_json()
{
var items = new Array();
$.getJSON('json.json', function(data) {
var items = [];
alert( eval ("(" + data + ")") );
// $.each(data, function(key, val) {
//items.push('<li id="' + key + '">' + val + '</li>');
// });
$('<ul/>', {
'class': 'my-new-list',
html: items.join('')
}).appendTo('body');
});
return items;
}
*/
Any help would be greatly appreciated, thanks!
The function you've supplied for the source: attribute doesn't return a value. The $.get() function does, but that won't reach the source attribute.
source: function()
{
$.getJSON('json.json', function(data)
{
cars_array = new Array();
$.each(data, function(k, v) {
cars_array.push(v);
})
return cars_array;
})
//You need to return something here
}
Also, it may be an issue that you're using an asynchronous call to the json file in a synchronous pattern. In other words, consider this:
$.getJSON('json.json', function(data)
{
cars_array = new Array();
$.each(data, function(k, v) {
cars_array.push(v);
})
//Now you definitely have the cars so you can do the autocomplete
$('#cars').autocomplete({
source:cars_array,
minLength: 3,
focus: function( event, ui ) {},
select: function( event, ui ) {
$('#suggestions').html(ui);
return false;
}
});