Detecting status change in a checkbox

W

waleed

I'm not really good with javascript, basically what I'm trying to do
is that I want to be able to handle when the status of a checkbox is
changed (i.e. checked or unchecked), I see everybody is using onclick
but I wonder if this is the correct approach, what if a user changes
the status of the checkbox using the keyboard, will onclick be
triggered? I know I might sound a little picky here but I believe
those people who created DHTML must've thought about this, right?

Sorry if I posted the question in the wrong group, I couldn't find a
good group for DHTML, I assume many people post questions about DHTML
here as javascript and DHTML are very related, anyway a post in the
wrong group is still better than all this spam I see everywhere here!
 
W

waleed

Never mind guys, I just realized that onclick is also triggered when
the user checks/unchecks the checkbox using the keyboard ...
 
S

Steve Swift

waleed said:
I'm not really good with javascript, basically what I'm trying to do
is that I want to be able to handle when the status of a checkbox is
changed (i.e. checked or unchecked), I see everybody is using onclick
but I wonder if this is the correct approach, what if a user changes
the status of the checkbox using the keyboard, will onclick be
triggered?

I think that onChange is what you want. I was tinkering with some
onChange code for RADIO buttons recently, and discovered that onChange
seems to trigger for radio buttons only when they change from unchecked
to checked. There is some sense in this, otherwise you'd often get two
events each time a button was changed (the other one coming from the
button which got unchecked).
 
D

dhtml

Steve said:
I think that onChange is what you want. I was tinkering with some
onChange code for RADIO buttons recently, and discovered that onChange
seems to trigger for radio buttons only when they change from unchecked
to checked. There is some sense in this, otherwise you'd often get two
events each time a button was changed (the other one coming from the
button which got unchecked).

onchange is "specified" to fire after the element loses focus and it has
a new value.[1][2]

However, when the control is checkbox or radio, the |checked| state is
usually what determines the "onchange" firing.

But that's only part of the picture.

When a radio or checkbox |checked| property is set in script, onchange
won't fire. Even when calling focus() before and blur() after.

The only way to get onchange to fire is for the user to change it, or to
dispatch a change event on the target programmatically, using
initMouseEvent[3][2]. initMouseEvent has the unusual design of 15
parameter variables. I still haven't memorized the order.

Mozilla has a checkboxstatechange event[4] for XUL that seems to have
leaked into HTML. Probably not the most reliable thing to use in
production apps, and has been filed as a bug[5].

I can't explain the reasoning behind the HTML and DOM specs ignoring
"change" for radio and checkbox. I can, however, demonstrate that the
facts are provable in a very simple demonstration:-

========================================================
<!DOCTYPE html>
<html>
<head>
<title>checkbox onchange firing for programmatic changes</title>
</head>
<body>
<form action="">
<input type="checkbox" name="a" id="a1">
<input type="checkbox" name="a" id="a2">
<input type="checkbox" name="a" id="a3">
</form>
<pre id='monitor'> </pre>
<script type="text/javascript">
document.onchange = function(e) {
text.data += '\n' + e.type + ": " +
e.target.type + "#" + e.target.id;
};

var inputs = document.body.getElementsByTagName('input'),
i = 0,
text = document.getElementById('monitor').firstChild;

var timer = setInterval(function() {
if(!inputs) {
i = 0;
clearTimeout(timer);
}
var checkbox = inputs;
checkbox.focus();
text.data += "\ncheckbox " + checkbox.id + " focused";
text.data += "\ncheckbox " + checkbox.id + " changed";
checkbox.checked = true;
//checkbox.value = i;
checkbox.blur();
text.data += "\ncheckbox " + checkbox.id + " blurred\n";
i++;
}, 600);


</script>
</body>
</html>

========================================================

Running the example in three browsers (op, ff, saf), the result of
changing the |checked| property via script will not cause a change event
to fire. The output looks like:

| checkbox a1 focused
| checkbox a1 changed
| checkbox a1 blurred
|
| checkbox a2 focused
| checkbox a2 changed
| checkbox a2 blurred
|
| checkbox a3 focused
| checkbox a3 changed
| checkbox a3 blurred
|
| checkbox a1 focused
| checkbox a1 changed
| checkbox a1 blurred


However, change will fire when you, as a user, click the checkbox by
clicking it with your mouse or activating it with the spacebar when it's
focused.

| change: checkbox#a1
| change: checkbox#a2
| change: checkbox#a3

Radio buttons don't fire change when checked programmatically either.
They only fire change on user action.

SO, to answer the OP's question, I think you can use a combination of
polling the event, plus capturing the change event on the object itself.
If supporting IE is concerned, don't use bubbling. Change doesn't bubble
in IE[6].

Garrett

[1] HTML 4.01
http://www.w3.org/TR/REC-html40/interact/scripts.html#h-18.2.3
[2] DOM Events
http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-htmlevents-h3
[3] initMouseEvent
http://developer.mozilla.org/en/DOM/event.initMouseEvent
[4] checkboxstatechange, XUL Planet
http://www.xulplanet.com/references/elemref/ref_EventHandlers.html
[5] Mozilla Bug 335020 "No nice way to watch for checkbox toggle"
https://bugzilla.mozilla.org/show_bug.cgi?id=335020
[6] MSDN: onchange Event
http://msdn.microsoft.com/en-us/library/ms536912(VS.85).aspx
 
B

Bart Lateur

dhtml said:
The only way to get onchange to fire is for the user to change it, or to
dispatch a change event on the target programmatically, using
initMouseEvent[3][2]. initMouseEvent has the unusual design of 15
parameter variables. I still haven't memorized the order.

You can also call the onclick and/or onchange event handlers manually,
while you're changing the checked status.

function check(el, bool) {
el.checked = bool;
if(el.onclick) el.onclick.call(el);
if(el.onchange) el.onchange.call(el);
}

You can pass extra parameters for the event methods to call(), typically
it should representing the event that triggered the callback, but most
onclick/onchange handlers don't even look at it. So, in such a case, you
don't need it.

Here's a complete sample:

<form>
<label><input type="checkbox" name="test"
onclick="this.parentNode.style.backgroundColor = this.checked ? 'red' :
'green'"> check, or not</label><br>
<label><input type="radio" name="remote" onclick="check(this.form.test,
true)"> on</label>
<label><input type="radio" name="remote" onclick="check(this.form.test,
false)"> off</label>
</form>
<script type="text/javascript">
function check(el, bool) {
el.checked = bool;
if(el.onclick) el.onclick.call(el);
if(el.onchange) el.onchange.call(el);
}
</script>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top