I'd like to use jQuery's auto complete in a Drupal project to automatically find nodes (pieces of content) with a given title. I can't quite find any examples of option usage that match what I am trying to do, which is the following:
URL needs to conform to the pattern: /api/node/title/{whatever the user typed}
When results are returned as JSON, the title needs to be used in the auto complete list
When a result is clicked, a styled paragraph containing the title will appear over the text box, but it will actually contain the node id (nid) of the node selected.
Here is what I have so far:
jQuery(this).autocomplete({
source: '/api/node/title/'+jQuery(this).val(),
minLength: 2
}).data( "autocomplete")._renderItem = function(ul, item) {
return jQuery('<li />')
.data("item.autocomplete", item)
.appendTo(ul);
};
I haven't even gotten to worrying about what to do once an element is selected - the URL is going out as /api/node/title?term={blank}, and even though I am getting JSON results back, nothing is appearing. Any suggestions, or examples of similar usage? The examples on the jQuery UI website for autocomplete weren't especially helpful.
EDIT: Here is an example of the expected response.
{
"nid":"2",
"vid":"2",
"type":"lorem",
"language":"und",
"title":"Grid Computing",
"uid":"0",
"status":"1",
"created":"1320092886",
"changed":"1320273538",
"comment":"1",
"promote":"1",
"sticky":"0",
"tnid":"0",
"translate":"0"
}
for 1), you can use a callback for the source
$('input').autocomplete({
source: autoDrupal,
minLength: 2});
function autoDrupal(requestObject, responseCallback) {
var url = '/api/node/title/' + requestObject.term;
$.get(url, function(data) {
// check my fiddle to transform drupal response in autocomplete result ;)
responseCallback(data);
});
};
for 2) I don't get what you mean by "title" but it can surely be handled in the response of $.get
for 3) a event handler can do the trick (once I understand your dreaded "title"). something like that:
$('ul.ui-autocomplete').delegate('li', 'click', function () {
$('#stuff').css('color', 'red');
})
check and play with this fiddle ;)
Related
I am using jquery-ui autocomplete plugin.
Here is how I've instantiated the autocomplete plugin.
//autofill
$( "#TextArea" ).autocomplete({
source: "search.php?option="+ option.toLowerCase(),
minLength: 3
});
On dropdown change, i am trying to change the option :
$('#Options').on('change', function() {
option = this.value.toLowerCase();
var teaxtarea = $('#TextArea');
//this is supposed to change the source string when the option value changes.
teaxtarea.autocomplete( "option", "source", "search.php?option="+ option);
}
});
I got the code to update the source string from the question below.
Jquery: Possible to dynamically change source of Autocomplete widget?
However, this solution doesn't seem to work for me.
I still get the first selected option even if i change the option in the dropdown.
Any help is greatly appreciated.
Suggest the following:
$("#TextArea").autocomplete({
source: function(req, resp){
var option = $('#Options option:selected').val().toLowerCase();
$.ajax({
cache: false,
url: "search.php",
data: {
option: option,
term: req.term
},
dataType: "json",
success: function(data){
resp(data);
}
});
},
minLength: 3
});
I think one issue is that if #Options is a <select> element, you need to find the selected child element:
$("#Options option:selected")
This ensures that you have the proper object and then you can call .val() upon it. If you need more help here, please update your post with an MCVE: https://stackoverflow.com/help/mcve
That may resolve the issue for you. If not, continue on.
Second, to ensure you are not caching, we can perform a more manual source capture.
When a string is used, the Autocomplete plugin expects that string to point to a URL resource that will return JSON data. It can be on the same host or on a different one (must support CORS). The Autocomplete plugin does not filter the results, instead a query string is added with a term field, which the server-side script should use for filtering the results.
So we replicate the same functionality with some added settings. So each time source is checked, the options will be checked and the term will be sent. We'll get the data back in JSON and send back to Autocomplete to be displayed.
Hope that helps.
I have severall select2 in my page.
I have a specific ajax engine and can't change it for many reasons.
i would like to fill each select2 dropdown when the end-user type in the field, and use home made javascript to fill the "options" in the select2.
I've tried many different things found on the net, and can't find a working syntax for that.
For instance :
jQuery("customer").select2({
query: function (options) {
alert('ok');
// my ajax call would be here
xajax_getCustomers(stringFilled);
}
});
i've tried with "ajax:" and several other things, i can't find how to trigger a javascript function when something filled.
Important : i should be able to get the string filled, in order to pass it to my ajax call
Thanks for your help
You have got this event:
$(selector).on("select2-highlight", function(e) {
console.log("highlighted val=" + e.val + " choice=" + e.choice.text);
})
It's valid for a search event, so when select2-highlight event is fired means that user is searching for a string that you can manage with the e.val and e.choice.text values.
Unfortunatelly there's no strict search event, but you can bind the hided input text of the plugin with a on('keyup');
Something like this:
$('input.select2-search__field').on('keyup', function() {
alert($(this).val()); // it alerts with the string that the user is searching
});
Im running into a problem where i have an ajax driven page that is drawn when a user selects something from a simple drop down:
<select id = "selectdepartment">
<option id = "default">Select an option...</option>
....
</select>
and the remainder of the page is drawn using the jquery .change() :
$('#selectdepartment').change(function(){
});
Which then runs some ajax to php script. everything works great, the problem is when i submit a form that was drawn with ajax (using $_SERVER['PHP_SELF'];), the data gets submited, the page reloads, and the page is cleared but the select box is still left where it was. The user has to move to a different option then back to the one the selected originally to re-fire the .change(). that sucks.
I could fix this by passing a php variable in all of my forms, then checking to see the variable set on every page load and if it is draw the page parts then, but this would lead to pretty messy code and it's less than desirable.
There has to be a way to do this with the jquery library, though my knowledge of the javascript language in general is not what i would like it to be. If anyone has any helpful hints please share, dont do it for me though, i wont learn that way :)
edit: code with .trigger
$('#selectdepartment').change(function(){
var department = $('#selectdepartment').val();
var day = $('#data').data('day');
var month = $('#data').data('month');
var year = $('#data').data('year');
//alert (department);
if(department === "Select an option..."){
$('.hiddenuntildepartmentisselected').css({"display":"none"});
}
else{
$('.hiddenuntildepartmentisselected').css({"display":"block"});
}
showpoints(department);
drawpointstable(department, day, month, year);
displaytheuseresforselecteddepartment(department, '');
$('#sendthedepartment').val(''+department+'');
$('#hiddendepartmentidforaddinganewpoint').val(''+department+'');
}).trigger('change');//end run functions
You can use the .trigger() function to immediately trigger the change event handler when the page has loaded:
$('#selectdepartment').change(function() {
// code here
}).trigger('change');
Or if you need to call it elsewhere via JavaScript/jQuery:
$('#selectdepartment').trigger('change'); // or just .change() as a shorthand
Updated
Your button for the form could make use of the onClick attribute, which would invoke a method to parse the form fields and post the data to your php script via .ajax().
In the success event method you then check any flags you need to and modify the element as you desire if needed.
Basic example:
Inside of .ajax():
...
url: 'xxx.xxx.xxx',
async: true,
type: 'POST',
dataType: 'html',
data: JSON.stringify( form_fields ),
beforeSend: function()
{
// Pre send stuff, like starting a loading gif
},
success: function( data, textStatus, xhr )
{
// Be sure you load the page with the content first
$( '#containing-div' ).html( data );
// Do your check here, and modify your element if needed here
if( flagtocheck === 'xxx' )
{
// Modify the element in question...
}
// I call a custom method termed `.ctrls()` here that makes any
// adjustments to the DOM once its loaded/updated.
},
error: function( xhr, textStatus, errorThrown )
{
}
Of course, you'll want to set flagtocheck appropriately in your case.
Hope that helps!
Note regarding edit
This post was edited to be a little more descriptive and more easily understood. Since the person asking the question is already using the .ajax() method, the success event method is the ideal place for doing what the person asking the question is requesting. It is 1 less method invocation to directly modify the element there than using it to call .trigger() or .change() which then also directly modifies the element.
I am using jQuery to get a list of suppliers for a part number.
I then want to load some extra data about the supplier/part number combination once the edit form appears. The problem is that the dataurl method (which I am calling in the beforeInitData method) to get the suppliers does not complete before the beforeShowForm method executes. Therefore I do not have a supplier to look up when the form first loads. Is there a way to run the function after the dataUrl method completes to get the extra data?
I have tried JQGrid editoptions dataurl not using ajax get? and got it going but I know there will be conflicts because the ajaxSelectOptions method gets called for every request and sometimes my requests will be coming from different places with different requirements.
Here is the code that I am using for my grid:
jQuery("#receiptPartsTable").jqGrid('editGridRow',"new",
{
height:400,
width:800,
reloadAfterSubmit:false,
recreateForm: true,
beforeInitData: function(form)
{
var selectedPart = rowData.part;
var selectedPartQty = rowData.qty;
//Getting list of suppliers
$("#receiptPartsTable").jqGrid('setColProp', 'supplier', { editoptions:{dataUrl:'getSuppliersForPart.php?part=' + rowData.part} });
},
beforeShowForm: function(form)
{
var selectedPart = rowData.part;
var selectedPartQty = rowData.qty;
$('#part').val(selectedPart);
$('#qty').val(selectedPartQty);
//$('#supplier').val() is not set yet;
var supplier = $('#supplier').val();
//This method is getting called before there is a supplier
getPartDetails(rowData.part, supplier);
//Set up onChange listener. After selecting a supplier, get the part details
$('#supplier').change(function() {
var supplier = $('#supplier').val();
getPartDetails(selectedPart, supplier);
});
}
You posted no definition of jqGrid which you use. The context in which you execute the above code is also not quite clear. Do you get rowData before from the currently selected row? Where you define it?
Nevertheless I think that you went in the correct direction and that you found already the correct way to solve the problem. The usage of complete callback of ajaxSelectOptions is probably the only way which you can use. You wrote about some "conflicts", but not posted more details.
I would recommend you to examine properties of this inside of complete callback. jqGrid set context option (see the line) of the $.ajax call (exactly like in the answer which you already found yourself). So you can use this.elem, this.options and this.vl inside of complete callback. this.vl is the value from the cell in case if editing of existing row. Typically it's the name of the option which will be selected. this.options has tree important properties which you can use: this.options.dataUrl, this.options.id, this.options.name. In case of form editing are the values this.options.id and this.options.name the same. In case of inline editing this.options.id will have rowid and _ ad the prefix. It gives you the possibility to execute different code inside of complete callback for different selects where you use dataUrl.
One more remark. In the most cases you can remove call of setColProp from the beforeInitData and use the approach suggested in the answer and the another one:
ajaxSelectOptions: {
data: {
id: function () {
return $("#receiptPartsTable").getGridParam('selrow');
},
part: function () {
return rowData.part;
}
},
complete: function (jqXHR, textStatus) {
var columName = this.options.name, response = jqXHR.responseText;
...
}
}
You can use just editoptions: {dataUrl: "getSuppliersForPart.php"} The URL will be appended with part and id parameters (see the above code). Instead of id you could use getRowData to get content from other columns based of rowid of currently selected row for example.
I have a jQuery UI Autocomplete control that fires an Ajax request when minLength = 3. The problem is as follows:
Say I enter "fic" as the initial search term - this is fine. The request fires and results are returned. I decide that I don't want to select any of the results and then re-enter the same search again (fic). This time no Ajax request fires!
My code is shown below:
// ... do request
$("#reportSearch").autocomplete({
delay: 50,
minLength: 3,
source: function(q, add){
$.ajaxSetup ({ cache: false});
$.ajax({
type: "GET",
url: K_URL_REQUEST
So basically the "source" callback is not fired in the second scenario I described above. It appeared that the reason for this was that the autocomplete control was holding onto the previous search term and because it matched - was not triggering a search:
// Taken from jquery-ui-1.8.4.custom.min.js
if (a.term != a.element.val()) { // *** THE MATCH IS HERE
//console.log("a.term != a.element.val(): "+a.term+", "+a.element.val());
a.selectedItem = null;
a.search(null, c) // *** SEARCH IS TRIGGERED HERE
}
In order to get it to fire each time, I simply reset the search term to null after a search returned. This way it worked as expected.
The thing is I don't understand this behaviour. I would've thought each search should be distinct. There is no caching (or shouldn't be anyway).
So although I've fixed my problem I keep feeling that I have missed something here.
Any ideas anyone? Thanks in advance!
Instead changing the jquery.ui, you can try erasing the value of the property "previous", doing something like this:
$(this).data().autocomplete.previous = null;
I have found a solution to this problem (for info, I am using jQuery UI 1.8.4)
The Autocomplete implementation in the jquery-ui-1.8.4.custom.js has a method defined as _change. By commenting out the if statement, the control always sends the request.
...,
_change: function(event) {
//if (this.previous !== this.element.val()) {
this._trigger("change", event, { item: this.selectedItem });
//}
},
...
i've managed to solve this problem by comment out this if-statement in the source of the jquery ui autocomplete.
// keypress is triggered before the input value is changed
clearTimeout( self.searching );
self.searching = setTimeout(function() {
// only search if the value has changed
//if ( self.term != self.element.val() ) {
self.selectedItem = null;
self.search( null, event );
//}
}, self.options.delay );
Since JQuery UI 1.8+ you can use the widget factory to extend the default behavior of all your autocomplete widgets.
Simply include a javascript file with this content after jqueryUI
// Extend jquery UI autocomplete
$.widget( "ui.autocomplete", $.ui.autocomplete, {
_close: function( event ) {
var ret = this._super();
// Resets previously used search term
this.term = null;
return ret;
}
});
Great tips here - this is something I've been struggling with for a while.
For me, the only solution that consistently works is a combination of Duncan's and Stefaan's answers above.