select2-4.0.3 displaying values as keys in JSON data - json

i have this JSON data coming from server. which is valid JSON per JASONlint
issue is when i enter 3 digits (anything bogus) I get the drop down, and it shows "keys" as values!!! I do not know why it is in reverse order??? if i use .each in place of .map it correctly lists values as values (in console log), but then shows nothing in dropdown (some error in select2 js is reported).
JSON: (firebug)
{"4":"2013","3":"2014","1":"2016","6":"winter","7":"birthday","2":"2015","5":"summer","8":"vacation"
}
this is my JS:
$("#selectTags").select2({
tags: true,
multiple: true,
allowClear: true,
//closeOnSelect: false,
tokenSeparators: ',', // [' ',','],
minimumInputLength: 3,
ajax: {
url: "/cgi-bin/json-data.pl",
dataType: 'json',
delay: 100,
data: function (params) {
var queryParameters = {
term: params.term
}
return queryParameters;
},
processResults: function (data) {
return {
results: $.map(data, function (key,value) {
console.log('key='+key);
return {
id: key,
text: value
}
})
};
}
}
});

the problem is with map, you have mixed up arguments, the first is value, the second is key.
see http://api.jquery.com/jQuery.map/#jQuery-map-object-callback
processResults: function (data) {
return {
results: $.map(data, function (value, key) {
console.log('key='+key);
return {
id: key,
text: value
}
})
};
}

Related

autocomplete to populate all values on input focus

I have autocomplete textbox whose values are populated using ajax call which returns json data. This works fine with following code lines.
$("#searchTitle").autocomplete({
source: function (request, response) {
$.ajax({
url: "/umbraco/Surface/MyApp/StartSearch",
type: "POST", dataType: "json",
data: { term: request.term },
success: function (data) {
debugger
response($.map(data, function (item) {
debugger
return { label: item.Cat_Name };
}));
}
});
},
messages: { noResults: "", results: "" },
minLength: 0
});
But this function gets called when user type something. Now, I want that when input is focused, all the values from response should be shown in autocomplete. How can I trigger the same?
You can achieve by using search event of autocomplete on focus of input.
For example
$( "#searchTitle" ).focus(function() {
// make sure you put space between double quote
$( "#searchTitle" ).autocomplete("search", " " );
});

Adding StateCode dash StateName to the autocomplete using MVC4.5 and a JsonResult

I am trying to get the state code to be followed by a dash and the state name using an ajax autocomplete syntax. I'm using jQuery and jQueryUI and the jQueryUI autocomplete function to attempt this.
I am using this json result:
[{"code":"AK","name":"Alaska"},{"code":"AL","name":"Alabama"},
{"code":"AR","name":"Arkansas"},{"code":"AZ","name":"Arizona"},
{"code":"CA","name":"California"}, ... ]
And I'm using this jQuery ajax call with an embedded
$.ajax({
url: '/Cats/State/List',
type: 'POST',
dataType: 'json',
success: function (data) {
$('#Cat_stateCode').autocomplete(
{
source: data.code + '-' + data.name,
minLength: 2
});
}
});
The mvc controller JSON Result looks like this:
public JsonResult List()
{
return Json(db.States.ToList(), JsonRequestBehavior.AllowGet);
}
How do I get the auto complete to show:
CA - California
CO - Colarado
If I type out C? Or does Autocomplete only work with simple json like {"AK", "AL", "AR" ... }?
Figured it out:
$("#Cat_stateCode").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Cat/States/List",
dataType: "json",
data: {
style: "full",
maxRows: 12,
req_state_part: request.term
},
success: function (data) {
response($.map(data, function (item) {
return {
label: item.code + ' - ' + item.name,
value: item.code
}
}));
// alert("data.code:" + data);
},
error: function (e) {
alert("e.error:" + e.error);
}
});
},
minLength: 1,
select: function (event, ui) {
//alert("ui item:" + ui.item ? "Selected: " + ui.item.label : "Nothing selected, input was " + this.value); //todo: remove after dev
},
open: function () {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
In my mvc CatStateController I have this:
public JsonResult List(String stateAbbreviation)
{
String StateNameORStateCodeContains = Request.Params["req_state_part"];
return Json(db.States.Where(state => state.name.Contains(StateNameORStateCodeContains) || state.code.Contains(StateNameORStateCodeContains)).ToList(), JsonRequestBehavior.AllowGet);
}
So it looks like it doesn't sent the term over, it only send over some params you make up in the data element. Since you can make up pretty much anything its up to the developers imagination. One thing I was trying to do was create a closure b/c I have a lot of different animals with different states. And I need to create this same autocomplete function for each of them. So I need to ask another question how do you remove the auto complete so I can call that same function from many different ids, or do I just separate them out with a comma like so:
$("#Cat_stateCode,#Dog_stateCode,#Penguin_stateCode...").autocomplete({ ... ???
And I believe the answer to the second part is in here. I think its insinuating just add some class or attribute to the applicable input tags and then just perform an each over them and them lastly apply the autocomplete to the $(this).autocomplete immediately after each each iteration occurs.
Found a better way with just set the input tag to have a class="cssClassName". Had to use the TextBoxFor:
#Html.TextBoxFor(model => model.Cat.stateCode, new { #class = "StateCodeAutoComplete" })

Bootstrap typeahead ajax result format - Example

I am using Bootstrap typeahead with an ajax function, and want to know what is the correct Json result format, to return an Id and a descripcion.
I need the Id to bind the typeahead selected element with a mvc3 model.
This is the code:
[Html]
<input id="myTypeahead" class='ajax-typeahead' type="text" data-link="myUrl" data-provide="typeahead" />
[Javascript]
$('#myTypeahead').typeahead({
source: function (query, process) {
return $.ajax({
url: $('#myTypeahead').data('link'),
type: 'post',
data: { query: query },
dataType: 'json',
success: function (jsonResult) {
return typeof jsonResult == 'undefined' ? false : process(jsonResult);
}
});
}
});
This works properly when I return a simple list of strings, for example:
{item1, item2, item3}
But I want to return a list with Id, for example:
{
{Id: 1, value: item1},
{Id: 2, value: item2},
{Id: 3, value: item3}
}
How to process this result in the ajax "success: function()"?
That is very easy with jquery Autocomplete, because I can return a Json Object list.
[jquery Autocomplete process data example]
...
success: function (data) {
response($.map(data, function (item) {
return { label: item.Id, value: item.Value, id: item.Id, data: item };
})
...
But that doesn't work with boostrap Typeahead.
Can anyone help me?
Thanks.
I try for two days and finally I could it working.
Bootstrap Typeahead doesn't support an array of objects as a result by default, only an array of string. Because "matcher", "sorter", "updater" and "highlighter" functions expect strings as parameter.
Instead, "Bootstrap" supports customizable "matcher", "sorter", "updater" and "highlighter" functions. So we can rewrite those functions in Typeahead options.
II used Json format, and bound the Id to a hidden html input.
The code:
$('#myTypeahead').typeahead({
source: function (query, process) {
return $.ajax({
url: $('#myTypeahead').data('link'),
type: 'post',
data: { query: query },
dataType: 'json',
success: function (result) {
var resultList = result.map(function (item) {
var aItem = { id: item.Id, name: item.Name };
return JSON.stringify(aItem);
});
return process(resultList);
}
});
},
matcher: function (obj) {
var item = JSON.parse(obj);
return ~item.name.toLowerCase().indexOf(this.query.toLowerCase())
},
sorter: function (items) {
var beginswith = [], caseSensitive = [], caseInsensitive = [], item;
while (aItem = items.shift()) {
var item = JSON.parse(aItem);
if (!item.name.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(JSON.stringify(item));
else if (~item.name.indexOf(this.query)) caseSensitive.push(JSON.stringify(item));
else caseInsensitive.push(JSON.stringify(item));
}
return beginswith.concat(caseSensitive, caseInsensitive)
},
highlighter: function (obj) {
var item = JSON.parse(obj);
var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
return item.name.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
return '<strong>' + match + '</strong>'
})
},
updater: function (obj) {
var item = JSON.parse(obj);
$('#IdControl').attr('value', item.id);
return item.name;
}
});
Note: I saw #EralpB`s comment "Is this still the best way to accomplish this task?"
Yes, #Gonzalo solution works, but it seems strange (like crutch,especially after using jQuery-Autocomplete) - it should work "from box".Better is to use this - Bootstrap-3-Typeahead. It supports an array of objects as result: format - [{id: .. ,name:...},...,{id: .. ,name:...}]. Example for OP`s issue:
....
source: function (query, process) {
return $.ajax({
......
success: function (result) {
var resultList = [];
$.map(result,function (Id,value) {
var aItem = { id: Id, name: value};
resultList.push(aItem);
});
return process(resultList);
}
});
},

autocomplete jquery.get json doesn't complete

I'm having trouble with autocomplete, usign JSON data.
I'm getting the right response from the callback, but the autocomplete doesn't work properly. For example, when I type "Lon" I get this response:
[{\"value\":\"Dijon, (DIJ)\",\"code\":\"DIJ\"},{\"value\":\"Longview, (GGG)\",\"code\":\"GGG\"},{\"value\":\"Long Island, (HAP)\",\"code\":\"HAP\"},{\"value\":\"Islip, (ISP)\",\"code\":\"ISP\"},{\"value\":\"Long Banga, (LBP)\",\"code\":\"LBP\"},{\"value\":\"Londrina, (LDB)\",\"code\":\"LDB\"},{\"value\":\"Londonderry, (LDY)\",\"code\":\"LDY\"},{\"value\":\"Long Beach, (LGB)\",\"code\":\"LGB\"},{\"value\":\"Long Lellang, (LGL)\",\"code\":\"LGL\"},{\"value\":\"Long Akah, (LKH)\",\"code\":\"LKH\"},{\"value\":\"Londra, (All airports - LON)\",\"code\":\"LON\"},{\"value\":\" - Londra, Gatwick Arpt (LGW)\",\"code\":\"LGW\"},{\"value\":\" - Londra, London City Arpt (LCY)\",\"code\":\"LCY\"},{\"value\":\" - Londra, Stansted Arpt (STN)\",\"code\":\"STN\"},{\"value\":\" - Londra, London Biggin Hill Arpt (BQH)\",\"code\":\"BQH\"},{\"value\":\" - Londra, Heathrow (LHR)\",\"code\":\"LHR\"}]
But my autocomplete just adds Longview and Long Island.
The tricky thing is that after I keep typing "Lond", the autocomplete works perfect, I delete the "d", the autocomplete works perfect, it completes all the data from above.
Where do I go wrong...?
Here's my code:
$("#destination2").keyup(function(){
var term = $("#destination2").val();
//var query_type = $("#form_type").val();
jQuery.get('http://online.bileteavion.com.ro/q_travel_online_api/misc/hotels.autocomplete.php?query_type=flight&term='+term, function(data) {
data = eval('['+data.responseText.split('[')[1].split(']')[0]+']');
var source = $.map(data, function(item) {
return {
label: item.value,
value: item.value,
id: item.id,
iata: item.iata
}
});
$("#destination2").autocomplete({
source: source,
minLength: 3,
search: function(event, ui) {
$('#loading-spinner').show();
},
change: function(event, ui) {
//console.log(ui.item);
if( !ui.item ) {
$(this).val("");
$("input[name='cityId']").val("");
$("input[name='destinationIataCode']").val("");
$("input[name='destination']").val("");
}
},
open: function() {
$('#loading-spinner').hide();
},
select: function(event, ui) {
$("input[name='cityId']").val(ui.item.id);
$("input[name='destinationIataCode']").val(ui.item.iata);
$("input[name='destination']").val(ui.item.value);
$(this).blur();
}
});
}
);
});
jquery.autocomplete is not a function to call every single time you want to display the autocomplete dialog.
You should call jquery.autocomplete only once during initializion, to equip your input field with a full mechanism which allows autocompleting - and which will take care of the "keyup" event.
To achieve what you need, you should use a callback with the source option.
Here is how :
Instead of :
$("#destination2").keyup(function(){
...
jquery.get(<url>, function(data){
var source = ...
$("#destination2").autocomplete({
source: source
minLength: ...
search: ...
open: ...
select: ...
})
})
})
You should write :
$("#destination2").autocomplete({
source: function(request, response){
//request is an obj containing infos on what is typed
//response is a callback, which should be called if you want to display hints
jQuery.get(url + request.term, function(data){
var source = ...
response(source);
})
}
minLength: ...
search: ...
open: ...
select: ...
})
You should check the Remote JSONP datasource from the docs.
I use this in my site. Works quite well.
$("#id").autocomplete({
source: function (request, response) {
$.ajax({
url: 'http://online.bileteavion.com.ro/q_travel_online_api/misc/hotels.autocomplete.php',
dataType: "json",
data: {
//values to pass to server. in your case: query_type & term
term: request.term,
query_type: 'flight'
},
success: function (data) {
response($.map(eval(data), function (item) {
return {
//map values as you previously did
label: item.value,
value: item.value,
id: item.id,
iata: item.iata
}
})
);
}
})
},
minLength: 3,
search: function(event, ui) {
$('#loading-spinner').show();
},
change: function(event, ui) {
//console.log(ui.item);
if( !ui.item ) {
$(this).val("");
$("input[name='cityId']").val("");
$("input[name='destinationIataCode']").val("");
$("input[name='destination']").val("");
}
},
open: function() {
$('#loading-spinner').hide();
},
select: function(event, ui) {
$("input[name='cityId']").val(ui.item.id);
$("input[name='destinationIataCode']").val(ui.item.iata);
$("input[name='destination']").val(ui.item.value);
$(this).blur();
}
});

jQuery UI - Autocomplete with extra params - returned data

All,
I've moved on to using the ui autocomplete rather than the plugin, took me a while to figure out extra params based on an example I found here, but that part works.
I'm having problems with dealing with the return data. In the code below I can alert out the title being returned, but I get a drop down of 'UNDEFINED' in the browser.
Thanks in advance.
$('#DocTitle').autocomplete({
source: function(request, response) {
$.ajax({
url: "index.pl",
dataType: "json",
data: {
Title: request.term,
maxRows: 10
},
success: function(data) {
response($.map(data, function(item) {
alert(item.TITLE);
return {
TITLE: item.TITLE
}
}))
}
})
}
});
I am using jquery UI autocomplete as follows and it is working quite fine for me. You may try on the similar lines.
$('input[type=text][name=City]').autocomplete({
source: function(request, response) {
$.getJSON($('input#CitySuggestionsLink').val(), {
term: request.term,
stateId: $('select#StateName option:selected').attr('value')
}, response);
},
search: function() {
// custom minLength
var term = this.value;
if (term.length < 1) {
return false;
}
},
delay: 200,
focus: function() {
// prevent value inserted on focus
return false;
},
select: function(event, ui) {
return false;
}
});