Lazy initialization of jquery UI autocomplete - javascript

I'd like to lazy initialize the source options of a jQueryUI autocomplete. I'm aware of the possibility to pass a function to the source option, but I want to delay the initialization until the user really starts using the autocomplete.
I tried waiting for the search event and then set the source option, but this has no effect.
var availableTags = [
"ActionScript",
"AppleScript",
"Scheme"
];
$("#searchFirstTransactionStateInfo_searchPartnerId").autocomplete({
source : [],
minLength: 0,
search: function( event, ui ) {
$(event.target).source = availableTags;
}
});
How can I delay setting the source option until the user starts using the UI element?
Note: I used a fixed array for simplicity. Finally I want to call an AJAX function.

Well, if you use a function as the source parameter, and let that function perform a get request (ajax ofcourse), it will actually only start making requests when you've typed something. As an example, open up your network tab and start typing in this UI example:
http://jqueryui.com/autocomplete/#multiple-remote
$(function() {
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#birds" )
.autocomplete({
source: function( request, response ) {
$.getJSON( "search.php", {
term: extractLast( request.term )
}, response );
},
search: function() {
// custom minLength
var term = extractLast( this.value );
if ( term.length < 2 ) {
return false;
}
},
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;
}
});
});

Related

jQuery autocomplete search and select programmatically

I have a data from my controller and when the page loads I want the autocomplete input to search for that data and select it.
I am able to search the data using:
$( "#autocomplete" ).autocomplete( "search", '<?=$ID?>' );
above code works and showing the correct value of autocomplete. Now I cant select the value so that the autocomplete input triggers change. I wanted the input to trigger change because I will auto populate some input.
The way I select the value pro grammatically is :
select: function( event, ui ) {}
Now i found this:
search: function( event, ui ) {},
Is is possible to combine the two?
How to select searched data from auto complete programmatically ?
Update:
This is how my autcomplete works:
$( ".updatedautocomplete" ).autocomplete({
source:function(request,response){
var $this = $(this);
$.post("url",{
term:request.term
}).done(function(data, status){
response($.map( data, function( item ) {
return {
data
}
return false; // Prevent the widget from inserting the value.
}));
});
},
select: function( event, ui ) {
$( this ).attr( 'data-value' , ui.item.id );
$( this ).attr( 'data-asd' , ui.item.sad );
$( this ).val( ui.item.label );
$( "#modal" ).val( ui.item.qwe.trim() );
$( "#modal" ).val( ui.item.asd.trim() );
$( "#modal" ).val( ui.item.zxc.trim() );
$( "#modal" ).val( ui.item.ert.trim() );
$( "#modal" ).val( ui.item.dfg.trim() );
return false;
}
});
The reason why I wanted select event is to populate some input as shown in the source
You simply do jQuery.val() on the input element, like so.
Edit
Since you seem to want to trigger the selection after an asynchronous data retrieval, you probably want the response event and perform the selection there.
response (event, ui)
Triggered after a search completes, before the menu is shown. Useful for local manipulation of suggestion data, where a custom source option callback is not required. This event is always triggered when a search completes, even if the menu will not be shown because there are no results or the Autocomplete is disabled
$(".updatedautocomplete").autocomplete({
source: function(request, response) {
var $this = $(this);
//$.post("url", {
// term: request.term
//})
//.done(function (data, status) {
// response($.map(data, function (item) {
// return {
// data
// }
// return false; // Prevent the widget from inserting the value.
// }));
//
//});
// Simulates some data returned from server
response([
{ label: "Javascript", value: "js" },
{ label: "CSharp", value: "cs" },
{ label: "PHP", value: "php" }
]);
},
response: function(event, ui) {
// Make your preferred selection here
var item = ui.content[0].label;
$(this).val(item).trigger('change');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<input class="updatedautocomplete" />
search and select are the events which get triggered when the search is taking place. You don't execute them.
Additionally, I believe the method search (not the event one) is meant rather for "suggesting" users that a value/tag exists in the list and that they need to select it themselves. So, yes, if you need a value programmatically selected (without user interaction) you might need to do it by .val() and optionally .trigger().

Need to do multiple search at a time with starting character which is search in autocomplete

I am use https://jqueryui.com/autocomplete/#multiple for autocomplete functionality in my site. Its work fine, Now I want to search record with first character that added to text box only.
Here is my code:
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css"><input type="text" id="multi"><script>$(document).ready(function() {var avail = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
];
$("#single").autocomplete({
source:avail
});
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#multi" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
avail, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
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;
}
});});</script>
As per comments:
To make the typeahead.js multipel search demo searching "starting from first character", change matching code line from this:
~item.toLowerCase().indexOf(tquery.toLowerCase())
to this:
item.toLowerCase().indexOf(tquery.toLowerCase()) == 0
Demo fiddle: http://jsfiddle.net/BwDmM/1100/
Additional note: more explanation about how the original matching code works (tilda bitwise operator) can be found here: http://www.joezimjs.com/javascript/great-mystery-of-the-tilde/

jquery autocomplete special char trigger

i have the following problem:
i must make a special autocomplete with jquery triggered by char "#"
the problem is that if i begin the textbox with # it works but if i enter # after i write some chars it doesn't work.
how it must work:
-i write some text an i want to add someone from "utilizatoriJson",
-to add someone from "utilizatoriJson" i must press the # key and an autocomplete dropdown must apear,
-after i select someone from dropdown or i type a full label from dropdown it must put space and let me continue my message
how can i do this ?
code that i wrote :
var utilizatoriJson = <%=utilizatoriJson%>;
$( '#textarea_mesaj_colaborare').autocomplete({
source: utilizatoriJson
}) .autocomplete( "instance" )._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
}
$( '#textarea_mesaj_colaborare').autocomplete("disable");
$('#textarea_mesaj_colaborare').keyup(function(){
if ($('#textarea_mesaj_colaborare').val()[$('#textarea_mesaj_colaborare').val().length-1]==='#'){
var inceput = $('#textarea_mesaj_colaborare').val().length;
$( '#textarea_mesaj_colaborare').autocomplete("enable");
}
});
As already mentioned, you would require multiple words approach here.
The link to original source has already been provided above. So, I would like show what I understood from your doubt.
But first let me know if you want to have autocompletion like after '#' all label that start with 'a' should give results that only start with 'a' and not those which contain 'a'.
Since I suppose this would be of much better use, I have code for that part.
Working Demo: http://jsfiddle.net/AJmJt/2/
$(function() {
//Since you told that labels start with '#'
var utilizatoriJson = [
{'label': "#ActionScript",'id':'1'},
{'label': "#Java",'id':'2'},
{'label': "#C++",'id':'3'},
{'label': "#Javascript",'id':'4'},
{'label': "#Python",'id':'5'},
{'label': "#BASIC",'id':'6'},
{'label': "#ColdFusion",'id':'7'},
{'label': "#Haskell",'id':'8'},
{'label': "#Lisp",'id':'9'},
{'label': "#Scala",'id':'10'}
];
function split( val ) {
return val.split( / \s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 1,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
var lastword = extractLast(request.term);
// Regexp for filtering those labels that start with '#'
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( lastword ), "i" );
// Get all labels
var labels = utilizatoriJson.map( function( item ) { return item.label; });
var results = $.grep( labels, function( item ) {
return matcher.test( item );
});
response( $.ui.autocomplete.filter( results, lastword ) );
},
focus: function() {
// prevent value inserted on focus
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;
}
});
});
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.0/jquery-ui.js"></script>
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags" size="50">
</div>
If you don't want something like I said, then there is no need for RegExp matching, but there you need to see if word starts with '#' or not.
Code for this behavior working: http://jsfiddle.net/rPfY8/1/
$(function() {
var utilizatoriJson = [
{'label': "#ActionScript",'id':'1'},
{'label': "#Java",'id':'2'},
{'label': "#C++",'id':'3'},
{'label': "#Javascript",'id':'4'},
{'label': "#Python",'id':'5'},
{'label': "#BASIC",'id':'6'},
{'label': "#ColdFusion",'id':'7'},
{'label': "#Haskell",'id':'8'},
{'label': "#Lisp",'id':'9'},
{'label': "#Scala",'id':'10'}
];
function split( val ) {
return val.split( / \s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 1,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
var lastword = extractLast(request.term);
if(lastword[0] != '#')
return false;
// Get all labels
var labels = utilizatoriJson.map(function(item){return item.label;});
response( $.ui.autocomplete.filter(
labels, lastword ) );
},
focus: function() {
// prevent value inserted on focus
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;
}
});
});
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.0/jquery-ui.js"></script>
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags" size="50">
</div>
You don't want to disable/re-enable the autocomplete as that prevents the control from doing anything. You can do this the way you propose, but there's another approach. Take a look at the example here: http://jqueryui.com/autocomplete/#multiple
This should do what you're looking for, you can update the filter to only do a "starts with" search
Here's a JSFIDDLE example of what I mean: http://jsfiddle.net/UhL5d/
And the corresponding Javascript:
$(function () {
var availableTags = [
{value: 1, label: "#ActionScript" },
{value: 2, label: "#AppleScript" },
{value: 3, label: "#Asp" },
{value: 4, label: "#BASIC" },
{value: 5, label: "#C" } ];
function split(val) {
return val.split(/\s/);
}
function extractLast(term) {
return split(term).pop();
}
$("#textarea_mesaj_colaborare").autocomplete({
source: function (request, response) {
// delegate back to autocomplete, but extract the last term
response($.ui.autocomplete.filter(
availableTags, extractLast(request.term)));
},
focus: function () {
// prevent value inserted on focus
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.label);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(" ");
return false;
}
});
});

autocomplete with multiple values and automatic replace

I'm using autocomplete with multiple remote values.
Every search gives me only one word (words in input text are separated by space)
I removed return false; from focus function and now when I focus on autocomplete results it automaticly change the input text and when i return focus to input text it show the original text i wrote.
This is behaviour that i want, but the problem is when I search second word.
Then when the autocomplete search i focused it overwrites the first word in input text.
I want the first word stay the same and only second (3, 4 ..) word changes. And when I return to input text I get the original text I wrote before I focus the search result.
My code:
$(function() {
function split( val ) {
return val.split( / \s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
source: function( request, response ) {
$.getJSON( "http://test.dev/search.php", {
term: extractLast( request.term ),
complete: request.term,
}, response );
},
search: function() {
// custom minLength
var term = extractLast( this.value );
if ( term.length < 2 ) {
return false;
}
},
focus: function(event, ui) {
},
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;
}
});
});

Javascript Autocomplete email's domain using jQuery UI

I need help, I am stuck with trying to make the following case scenario work:
You have email input field, you type: foo#y - it should pop up autocomplete box, offering yahoo.com (for example).
If you take this suggestion, the end value should become: foo#yahoo.com
I have wrote this code (modified off another jquery UI sample):
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 3,
source: function( request, response ) {
var mail_regex = /^([\w.]+)#([\w.]+)$/;
var match = mail_regex.exec(request.term);
if (match)
var matcher = new RegExp( "^" + match[2], "i" );
response( $.grep( availableTags, function( item ){
return matcher.test( item );
}) );
},
focus: function() {
// prevent value inserted on focus
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;
}
});
Full working interactive sample:
http://jsfiddle.net/rRF2s/3/
However, it REPLACES the foo# with just yahoo.com - I can not for the life of me figure out how to override this behaviour...
Any Javascript/jQuery masters - help please! how to accomplish this goal?
I tried doing: return match[1]+matcher.test( item ), but that does not work.
The select function is assigning the resultant value with this.value =. However it is replacing the input value completely rather than appending it with the drop down value.
Without a great deal of testing the following, simplified function seems to work as required:
select: function( event, ui ) {
this.value = this.value.substring(0, this.value.indexOf('#') + 1) + ui.item.value;
return false;
}
This is taking the first part of the already entered value, for example foo# for the input foo#ya and then adding on the value of the selected item from the drop down.
You may want to trigger the dropdown when someone enters the # symbol (seems more intuitive to me) and if so, this function may also need modifying to correctly extract the user entered value.
Here is the complete code:
$(function() {
var availableTags = [
"Yahoo.com",
"Gmail.com"
];
function extractLast( val ) {
if (val.indexOf("#")!=-1){
var tmp=val.split("#");
console.log(tmp[tmp.length-1]);
return tmp[tmp.length-1];
}
console.log("returning empty");
return "";
}
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 1,
source: function( request, response ) {
var mail = extractLast(request.term);
if(mail.length<1){return;}
var matcher = new RegExp( "^" + mail, "i" );
response( $.grep( availableTags, function( item ){
return matcher.test( item );
}));
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = this.value.split(", ");
// remove the current input
var ml=terms[terms.length-1].split("#")[0];
terms.pop();
// add the selected item
terms.push( ml+"#"+ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
});

Categories