Javascript/Prototype adding two event handlers to a single field when I just want one
I'm using prototype to attach event handlers to a number of form fields. The form fields are named "ContactAddress", "ContactCity", "ContactState", "ContactZip" as well as another set that begins with "ContactProfile". Now, the event needs to be able to tell the difference between when I'm updating a "Contact" field and a "ContactProfile" field so I have a data structure and code that works like t开发者_开发百科his:
var geos = {
'Contact' : [
'Address', 'City', 'State', 'Zip'
],
'ContactProfile' : [
'Address', 'City', 'State', 'Zip'
]
};
// Called on page load
function watchGeo() {
for(prefix in geos) {
geos[prefix].each(function(item) {
$(prefix + item).observe('change', function() {ajaxgeolocate(prefix, item);});
})
}
}
// Doesn't actually geolocate anything yet, just tells me that the event works and what params got passed.
function ajaxgeolocate(prefix, suffix) {
alert(prefix + " " + suffix);
}
Upon loading the page, when I change one of the ContactProfile fields, it gives me an alert box that says "ContactProfile Address" (for example) like it should. However, if I change one of the Contact fields, it gives me an alert box that also says "ContactProfile Address". Curious, I inspected the field and found out that two event handlers had been added to all Contact fields, instead of just one. ContactProfile fields all have one event, as they should.
What's going on here?
It happens here:
function watchGeo() {
for(prefix in geos) {
geos[prefix].each(function(item) {
//alert($(prefix + item))
$(prefix + item).observe('change', function() {ajaxgeolocate(prefix, item);});
})
}
}
The variable 'prefix' is a member of 'watchGeo' and is included in the closure function passed to .each(). However when you get to the 2nd prefix, the first one is overwritten in all previous closures passed to .each().
Further more, it's even worse, 'prefix' becomes a global variable since you never declare it inside the function scope.
Try:
function appendGeoWatcher(prefix, item) {
$(prefix + item).observe('change', function() {ajaxgeolocate(prefix, item);});
}
function watchGeo() {
for(var prefix in geos) { // var prefix, keeps it local.
geos[prefix].each(function(item) {
appendGeoWatcher(prefix, item)
});
}
}
精彩评论