Autocomplete: how to get automatically value on focus if no values selected - javascript

From the comment in this question, I've seen how to set an autocomplete field to empty if no element from the list has been selected.
What I am trying to implement is that when a user does not select any element from the autocomplete list and switches to the next field, one of the following should happen:
If there was at least on element displayed in the autocomplete list, take automatically the first element of that list. In the screenshot below, Mannheim should be automatically selected if the user goes to another field without selecting any element.
If no element was displayed, make the field empty again.
If tried the suggestions from here and here, but without success.
This is my code:
var cities = //function that provides a list of cities depending on the input string (edited to clarify)
$('.autocomplete-city').autocomplete({
source: function (request, response) {
response($.map(cities( request.term ), function (value, key) {
return {
label: value.label,
value: value.value
}
}));
},
// manage what happens if user does not click any option from autocomplete
change: function(event, ui){
if (ui.item == null){
if ( list_from_autocomplete == null ){ // I tried here several possibilities but none seem to work
$(this).val('');
$(this).focus();
} else {
$(this).val( first_item_in_list ); // Despite the existing questions, I could not make it work...
}
}
},
minLength: 2,
autoFocus: true,
});
How could this be done?

You could search all the cities that contains the user input and if you get only one result, put it in the autocomplete.
1) So, in the change event you could check if user selected an item:
change: function(event, ui){
if(ui.item){
//user select an item
}
else{
//here let's try to set the autocomplete
}
2) Search the cities that contains the user's input:
var result = cities.filter(function( obj ) {
return obj.label.indexOf(searched);
});
3) Finally, if you get just one result, set the autocomplete with that value:
if(result.length==1){
$(this).val(result[0].label);
}
Please see following snippet:
var cities = [
{"label":"Alessandria","id":"AL"},
{"label":"Milano","id":"MI"},
{"label":"Pisa","id":"PI"},
{"label":"Pistoia","id":"PT"}
];
$(".autocomplete-city").autocomplete({
source: cities,
select: function(event, ui){
if(ui.item){
console.log('select', ui.item.label);
return ui.item.label;
}
else{
console.log('select with null value');
}
},
change: function(event, ui){
var searched = this.value;
console.log("Searched: " + searched);
if(ui.item){
console.log('change', ui.item.id);
}
else{
console.log('change with null value');
var result = cities.filter(function( obj ) {
return obj.label.toLowerCase().indexOf(searched.toLowerCase()) !== -1;
});
if(result.length>0){
$(this).val(result[0].label);
}
else{
//clear the autocomplete
$(this).val("");
}
}
}
});
<link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<input class="autocomplete-city"/>
In the above example there are following cities: Alessandria, Milano, Pisa, Pistoia.
If you digit in textbox "Mil" or "Ale" and just press the tab, the autocomplete will be filled with the single result starting with "Mil" or "Ale".
Instead, when you digit "Pis" the autocomplete will be cleared.
I hope it was clear, bye.
Updated:
In order to get the first result when user leaves the autocomplete without selecting any city, you could check result.length>0 and set the first value from result in to the autocomplete:
var result = cities.filter(function( obj ) {
return obj.label.toLowerCase().indexOf(searched.toLowerCase()) !== -1;
});
if(result.length>0){
$(this).val(result[0].label);
}
else{
//clear the autocomplete
$(this).val("");
}

Related

Materialize CSS on chip delete

I have been trying to get the tag of a deleted chip from the div in the Materialize chips class, but nothing is working.
Here is what I have already tried.
$('.chips').on('chip.delete', function(e, chip){
console.log(chip);
console.log(e);
console.log(chip.tag);
});
None of the above is working.
With just only console.log(chip), I get undefined error in JavaScript console, but the function is firing when I delete the chip. I am just not able to get the value of tag of deleted chip. I want to store the tag in a variable.
I am creating chips dynamically on Materialize date select:
$('#pm_date').change(function () {
var chipvalue = $(this).val();
if (chipvalue !== "") {
// checking if tag already exits
if ($("#date_chip_select:contains(" + chipvalue + ")").length > 0) {
alert('Date already selected');
} else {
var appendstring = "<div class='chip' id='date_chip_child_" + chip_id + "'>" + chipvalue + "<i class='material-icons close'>close</i></div>";
}
}
});
Here is the fiddle: https://jsfiddle.net/hq22mne4/1/
chips.js, which is part of materialize, doesn't seem to expose any methods for adding or removing chips programmatically. It seems to exclusively listen for an enter keydown event and then internally add the chip.
So, I stitched together a workaround that does just that. I set potential chip's value within your onchange event:
$("#datechips").find('input').val($(this).val());
And create the chip when date picker is closed:
$('.datepicker').pickadate({
selectMonths: true,
selectYears: 15,
onClose: function() {
// add chip via filling the input and simulating enter
$("#datechips").find('input').trigger({ type : 'keydown', which : 13 });
},
});
It may not be ideal, but you should be able to tailor this going forward.
https://jsfiddle.net/j3ej8240/
I've also had a lot of trouble working this out. This is how I capture the add and delete chip events without using jQuery:
function chipDeleted(e, data) {
console.log("Chip was deleted with text: " + data.childNodes[0].textContent);
}
function chipAdded(e, data) {
console.log("Chip was added with text: " + data.childNodes[0].textContent);
}
//
document.addEventListener("DOMContentLoaded", function (e) {
console.log("DOM fully loaded and parsed");
var firstTag = "Initial Tag";
var elems = document.querySelectorAll('.chips');
var instances = M.Chips.init(elems, {
data:[{
tag: firstTag
}],
autocompleteOptions: {
limit: Infinity,
minLength: 1
},
placeholder: "No search...",
onChipDelete: function (e, data) { chipDeleted(e, data) },
onChipAdd: function (e, data) { chipAdded(e, data) }
});
});
And my HTML part is like this:
<body>
<div class="chips search-history"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
</body>

appendTo custom element not updating with autocomplete

I have a search box and am using Jquery autocomplete to get the search results which I want to return to a custom element.
At the moment it appends every time the search changes which leads to duplicates.
I was wondering if there is an option which will delete the contents of the custom element when the search term changes.
var $searchFriends = $("#searchFriends");
$searchFriends.autocomplete({
source: "search/findFriends",
minLength: 3,
appendTo: "#searchResults",
select: function(event, ui) {
$('#searchFriends').val(ui.item.value);
return false;
}
})
.data("uiAutocomplete")._renderItem = function( ul, item){
return $("<li class='friendResult' id='"+item.id+"'>")
.append("<a>"+item.value+"</a>")
.appendTo('#searchResults')
};
I currently have a work around which is working fine (below) but there must be another way.
$searchFriends.on('change textInput input', function (){
$('#searchResults').empty();
});
You can use html() to replace the html in an element (instead of using append() to append it).
var $searchFriends = $("#searchFriends");
$searchFriends.autocomplete({
source: "search/findFriends",
minLength: 3,
appendTo: "#searchResults",
select: function(event, ui) {
$('#searchFriends').val(ui.item.value);
return false;
}
})
.data("uiAutocomplete")._renderItem = function( ul, item){
var content = $("<li class='friendResult' id='"+item.id+"'>").append("<a>"+item.value+"</a>");
$('#searchResults').html(content);
};

Ajax / Jquery Autocomplete with JSON data does not show background style

I want to render Ajax / Jquery Autocomplete in my Spring App but unable to show background style I get result as shown
my Autocomplete code is
<script type="text/javascript">$(document).ready(function() {
//attach autocomplete
$("#tagQuery").autocomplete({
minLength: 1,
delay: 500,
//define callback to format results
source: function (request, response) {
$.getJSON("/getTags", request, function(result) {
response($.map(result, function(item) {
return {
// following property gets displayed in drop down
label: item.tagTitle,
// following property gets entered in the textbox
value: item.tagTitle,
// following property is added for our own use
tag_url: "http://" + window.location.host + "/" + item.tagId + "/" + item.tagTitle
}
}));
});
},
//define select handler
select : function(event, ui) {
if (ui.item) {
event.preventDefault();
$("#selected_tags span").append(''+ ui.item.label +'');
//$("#tagQuery").value = $("#tagQuery").defaultValue
var defValue = $("#tagQuery").prop('defaultValue');
$("#tagQuery").val(defValue);
$("#tagQuery").blur();
return false;
}
}
});
});
UPDATE
Adding line
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" />
solved issue of ui it now looks good
but when I select any value it is not placed in input text and how can I add comma separated multiple results in input box.
please any help is a day saving...

Auto select the top autocomplete result into hidden input

I'm trying to do a search by id, but the autocomplete by name.
So I put an hidden input, that is updated on select.
The problem is that if the user presses Esc or some how initiates a search without selecting, the search fails (doesn't return the desired value), because the hidden value isn't updated. I'm trying to force the autocomplete to choose the top result as long as no other result is selected.
My code is:
$('#search_box').focus(function () {
$(hidden).val("");
});
$('#search_box').autocomplete({
source: "autocomplete_empl.asp",
minLength: 2,
autoFocus: true,
select: function (event, ui) {
$('#hidden').val((ui.item ? ui.item.id : 0));
}
});
Thanks!
P.S
The returned list comes in json form.
I would check if autocomplete val() is empty.
If it is empty do nothing( or you need to select the first value?)
$('#search_box').focus(function () {
$(hidden).val("");
});
$('#search_box').autocomplete({
source: "autocomplete_empl.asp",
minLength: 2,
autoFocus: true,
select: function (event, ui) {
if($('#search_box').val() !== ""){
$('#hidden').val((ui.item ? ui.item.id : 0));
}
}
});
If you need to select the first option just trigger the search event with the data you need
select: function (event, ui) {
if($('#search_box').val() !== ""){
$('#hidden').val((ui.item ? ui.item.id : 0));
}
else{
$('#search_box').autocomplete('search', 'DataYouNeed');
}
}
Here is the link on the API page, which explains it a bit
http://api.jqueryui.com/autocomplete/#method-search

Force a user to select from JQuery UI Autocomplete and populate a hidden field after selecting

I have a large HTML form that contains many fields that need an autocomplete for accounts. I tag these fields with the class AccountLookup and jQuery does the dirty work for the autocomplete:
$(".AccountLookup").autocomplete({
source: function (request, response) {
$.ajax({
url: "Lookup.asmx/GetAccounts",
data: "{ 'Search': '" + request.term + "' }",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data.d, function (item) {
return {
value: item.Value
}
}))
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
},
minLength: 3
});
Now, when a user selects something from the autocomplete I need it to populate a hidden field just BEFORE the tagged input field; probably using something like:
$(this).prev().val(item.Key);
How do I incorporate this functionality? Also, how do I force a user to select from the auto complete? (All the values are pre-defined, the user cannot add new ones.)
EDIT:
As far as I understand from inspecting the DOM, the select option is currently filling in the hidden form field.
select: function (event, ui) {
$(this).prev().val(ui.item.key);
}
I know this is an old post--- but I ran into it in trying to solve a similar problem (forcing the user to select an item from the list)...
$("#ac").autocomplete({
source: function (req, resp) {
//add code here...
},
select: function (e, ui) {
$(this).next().val(ui.item.id);
},
change: function (ev, ui) {
if (!ui.item)
$(this).val("");
}
});
$(".AccountLookup").autocomplete({
/*...*/
}).result(function(event, item) {
$(this).prev().val(item.Key);
});
You could also use a jQuery validate to ensure that the field is populated.
for force selection, you can use "change" event of Autocomplete
var availableTags = [
"ActionScript",
"AppleScript"
];
$("#tags").autocomplete({
source: availableTags,
change: function (event, ui) {
if(!ui.item){
//http://api.jqueryui.com/autocomplete/#event-change -
// The item selected from the menu, if any. Otherwise the property is null
//so clear the item for force selection
$("#tags").val("");
}
}
});
For the selection action, try using the formatItem option. You can format each result to have an onclick event that will populate the other textbox.
For the forcing to select from autocomplete, you need to use the mustMatch option.
http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions
I ran into this same problem quite awhile ago and some post helped me along with it. I have since modified the code as I found that there were cases I wanted one or more fields to fill in from the information returned. In the select option of the autocomplete I added a function.
select: function (e, ui) {ReSetField({'txtID':'id','txtPrice':'price' [,etc...]}, ui) }
The function "ResetFields" then takes in a JSON list of element names paired with fieldnames and uses the fieldnames to match the elements in the ui object. The value can then be pulled from the ui item and put into the html element.
function ReSetField(_flds, _vals) {
//Set up the flds to be reset with values passed in.
try {
if (_flds != undefined) {
if ($.type(_flds) == 'string') {
_flds = JSON.parse(_flds);
};
var _fld = null;
var _val = '';
$.each(_flds, function (index) {
if (index.length > 0) {
_fld = '#' + index; //Set the forms field name to set
_val = _flds[index]; //Pick up the field name to set the fields value
$fld = $(_fld);
$fld.val(_vals.item[_val]); //Set the fields value to the returned value
}
}
})
};
}
catch (e) {
alert('Cannot set field ' + _fld + '.');
}
}
By sticking the "fieldlist" into the HTML element as an attribute like "fieldlist" and using a class like "comboBox" I can then use a single function to find all ComboBox elements and set up the autocomplete on a form reducing the amount of code required to handle 2 or more lookups on a form.

Categories