logo       
Bookmark and Share

Re: prototype EventObserver on radio option elements: msg#00009

lang.ruby.rails.spinoffs

Subject: Re: prototype EventObserver on radio option elements


Running with the idea of defining a single EventObserver for a whole group of radio elements, I came up with something like this. I'm sure this is a much more elegent way of integrating it with the existing EventObserver. My Javascript isn't that strong. I had to remove the "initialize" function from the Abstract.EventObserver and therefore mess with the existing hierarchy.

<form id="myFormId">
<label><input type="radio" name="myradio" value="a" id="myradio.a">Value A</label>
<label><input type="radio" name="myradio" value="b" id="myradio.b">Value B</label>
</form>
<script type="text/javascript">
Form.Element.RadioEventObserver = Class.create();
Form.Element.RadioEventObserver.prototype = (new Abstract.EventObserver()).extend({
initialize: function(form, name, callback) {
this.elements = Form.getElements(form, 'radio', name);
this.callback = callback;
this.lastValue = this.getValue();
for (var i = 0; i < this.elements.length; i++) {
this.registerCallback(this.elements[i]);
}

},
getValue: function() {
for (var i = 0; i < this.elements.length; i++) {
var value = Form.Element.getValue(this.elements[i]);
if (value) {
return value;
}
}
},

onElementEvent: function() {
var value = this.getValue();
if (this.lastValue != value) {
for (var i = 0; i < this.elements.length; i++) {
if (Form.Element.getValue(this.elements[i])) {
this.callback(this.elements[i], value);
}
}
this.lastValue = value;
}
}
});

new Form.Element.RadioEventObserver(
'myFormId', 'myradio',
function(element, value) {
alert("radio " + element.id + ", " + element.name + ", last value: " + this.lastValue + ", value: " + value);
}
);

Improvements and suggestions appreciated,

Thanks,

Tim



Tim Morrow wrote:


Hi all,

I just started using prototype 1.3.1. I've successfully used Form.Element.EventObserver on a select list and recently tried to add it to radio options. However, I think there is a flaw in how it works with radio options.

Radio options are a little unusual in that there are multiple distinct elements, tied together by a common name, where changing one element causes a change to another element. That is, selecting a radio option causes it to become "checked" and _unchecks_ a different element. The behavior is not on a single element.

It entirely possible that I missed some simple solution already hiding within the prototype library. Please enlighten me if that is so.

I started by adding an EventObserver to each radio element in the same group of radio options. However, the event (which is tied to onclick) was only fired once per element. It seems that the EventObserver records the "lastValue" and only fires if it hasn't changed. For a radio element, it only changes once: when you first click on it (and it becomes checked) its value changes from "undefined" to the value of the radio option. Clicking on a different radio element unchecks the first element, but the EventObserver never sees this and this never resets "lastValue". Which means the events never fire again. Its easy to reproduce:

<label><input type="radio" name="myradio" value="a" id="myradio.a">Value A</label>
<label><input type="radio" name="myradio" value="b" id="myradio.b">Value B</label>
<script type="text/javascript">
new Form.Element.EventObserver(
'myradio.a',
function(element, value) {
alert(element.id + ", " + element.name + ", last value: " + this.lastValue + ", value: " + value);
}
);
new Form.Element.EventObserver(
'myradio.b',
function(element, value) {
alert(element.id + ", " + element.name + ", last value: " + this.lastValue + ", value: " + value);
}
);

A simple workaround you can put in your own code is to reset the "lastValue" of all EventObservers on related radio options. But this requires you to assign each EventObserver to a variable and know about all the others.

Another workaround is to modify prototype to make the Radio option events fire on "onchange", then eliminate the code that checks to see if the value has changed (of course only for elements of input type radio). The onchange will only fire when that radio option changes. This is fairly straightforward.

Finally, it seems a little unwieldy to have to define multiple EventObservers for a single group of radio options. Perhaps the best solution would be to somehow define an EventObserver with a single callback for the entire set of radio elements that have the same name, fired on the onchange event of any radio option. This would simply client code greatly.

Anyone have any thoughts on this?

Thanks,

Tim


_______________________________________________
Rails-spinoffs mailing list
Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@xxxxxxxxxxxxxxxx
http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs


<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | Mail Home | sitemap | FAQ | advertise