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@public.gmane.org
> http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs