This is in JQuery, using the JQuery-UI version of autocomplete
I’m in a bit of an edge case. I’m working inside a form that must be indefinitely cloneable, so I can’t use id tags for unique identification, and I can’t just search down from the top to find something that looks like the DOM elements I’m working with – I have to use relative functions (.closest, .find, and so forth). Inside this form, I have a setup with a country field, a state field, and a location field, and the location field is supposed to be an autocomplete, fed from a link, where it hands the current value of the country and state fields on the link going up for server-side filtering. I’d like it to go something like this:
function locPrep(locNode) {
$locNode.autocomplete({
source: function (request, response) {
$locDiv = $(this).closest("div.locWrapper");
$stateNode = $locDiv.find("input.state");
$countryNode = $locDiv.find("input.country");
$.post("/FormHost/AutocompleteLocList",
{state:$stateNode.val(), country:$countryNode.val(), term:request.term },
function (data) {
response(data);
}
);
}
});
}
…except that that doesn’t work because the $(this) for the source function isn’t locNode, and I can’t just declare it outside and use it inside because locPrep gets called repeatedly, once for each autofill in the form. If I try that, the fact that Jquery makes everything global causes all of the autofills in the form to reference the country and state fields for the last one. I tried using javascript vars to get around the scoping issues and it broke strangely. Can anyone help?
Edit: thanks to Dmitriy Naumov’s kind assistance, I was able to hammer together a functioning solution (though I’m still not entirely sure why it works, given some of the things that I tried that did not). I’m including the functioning code in the hopes that it may help someone else later. (I’ve certainly gained quite a lot from the answered questions of others.)
First, I went through and changed every instance where I called the function from “locPrep(foo);” to “new locPrep(foo);” I also changed it to take locDiv rather than locNode. Then, I changed the code to the following (though this is, as that was, a somewhat simplified version).
function locPrep(locDiv) {
$locNode = $(locDiv).find("input.locationAutofill")
$locNode.autocomplete({
source: function (request, response) {
var stateVar = $(locDiv).find("input.state").val();
var countryVar = $(locDiv).find("input.country").val();
$.post("/FormHost/AutocompleteLocList",
{state:stateVar, country:countryVar, term:request.term },
function (data) {
response(data);
}
);
}
});
}
I’m not entirely sure which bits of this were necessary, but as a group they manhandle the code around to using tight enough scoping to solve the issue.
Save $(this) to a variable and pass it as a parameter (locNode) to your function (during initialization). Also, instead of $(this) you can pass a link to the container element, so each of your initialized autocompletes will know its parent.
Update: The following may not be 100% correct in terms of autocomplete initialization, but its a solid illustration how to create 2 unique instances of locPrep in
<div id="myDiv1">and<div id="myDiv2">Update2: how to pass this
init:
new will make sure that value of currentThis is unique in each instance of locPrep