I\'m programming in Javascript.
I need to dynamically generate the event handlers for the onclick
event.
Here above the code:
for (v
Three options:
The usual way is to have a builder function for the handlers:
for (var i = 1; i < CurrValue; i++) {
getId('btnReadRFIDTag_' + i).onclick = buildHandler(i);
}
function buildHandler(index) {
return function() {
ReadRFIDTag(getId('txtCode_' + index));
};
}
The function built by the buildHandler
closes over the index
argument from that call to buildHandler
, rather than over i
, and so it sees the right value.
Function#bind
If you can rely on ES5 (or you include an ES5 shim, as this is a shimmable feature), you can do it with Function#bind
:
// Using Function#bind (option 1)
for (var i = 1; i < CurrValue; i++) {
var elm = getId('btnReadRFIDTag_' + i);
elm.onclick = function(index) {
ReadRFIDTag(getId('txtCode_' + index));
}.bind(elm, i);
}
Used like that, it creates unnecessary extra functions, so you could also use it like this:
// Using Function#bind (option 2)
for (var i = 1; i < CurrValue; i++) {
var elm = getId('btnReadRFIDTag_' + i);
elm.onclick = myHandler.bind(elm, i);
}
function myHandler(index) {
ReadRFIDTag(getId('txtCode_' + index));
}
Instead of putting a handler on each button, if they're all in a container (and ultimately, of course, they are, even if it's just document.body
), you can put the handler on that container and then use event.target
to find out which button was clicked. I wouldn't do that with old-style onclick
, but you can with addEventListener
or attachEvent
:
var container = /* ...get the container... */;
if (container.addEventListener) {
container.addEventListener('click', clickHandler, false);
}
else if (container.attachEvent) {
container.attachEvent('onclick', function(e) {
return clickHandler.call(this, e || window.event);
});
}
else {
// I wouldn't bother supporting something that doesn't have either
}
function clickHandler(e) {
var btn = e.target;
while (btn && btn !== this && btn.id.substring(0, 15) !== "btnReadRFIDTag_") {
btn = btn.parentNode;
}
if (btn && btn !== this) {
ReadRFIDTag(getId('txtCode_' + btn.id.substring(15)));
}
}
The way that works is by hooking the click
event on the container, and then when the click bubbles up (down?) to it, it looks at where the click originated and sees if that (or an ancestor of it) is one of the buttons we care about. If it is, we act on it.