Does :on => blur works?

Hi.
I’m using observe_fields and the behaviour I need is onBlur. The code (I
think the code is correct) is as follows:

<%= start_form_tag :id => ‘AjaxForm’ %>
<%= text_field_tag :text1 %>
<%= text_field_tag :text2 %>
<%= observe_field :text1,
:url => {:action => ‘test’},
:update => ‘ajaxWrapper’,
:with => ‘text1’,
:on => ‘blur’ %>
<%= end_form_tag %>

The problem is that it behaves like onChange.

Is there anyone that achieved to use :on => ‘blur’ (or ‘focus’, ‘click’,
…) ?

I’ll really appreciate an answer.
Thanks

according to docs, you can specify :on => blur

http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper.html#M000535

sorry, didn’t fully read your question.

the only difference between onblur and onchange is that onblur fires
every time you move away from the text field, whereas onchange (on a
textfield) fires when you move away from the text field (just like
blur) but only when the value of the field is changed, ie, it won’t
fire if you move away and the value stayed the same.

so yes, blur will behave just like change for a text field.

Dear Chris, thanks for your answer.
I’ve read the documentation about it and I know it’s supposed to work.
The thing is I can’t make it work.

So, the question is if anyone have had the same problem and could figure
it out, please lend me a hand.

Thanks

Fernando,

What html is actually being generated?

well, what behavior is it showing and what behavior are you expecting?

you say you want onblur, but you are seeing onchange.

so this means the event only fires when you change the field then move
focus away and what you want is for the event to fire whenever you
move focus away, whether the field value changes or not?

please clarify.

Chris

David wrote:

Fernando,

What html is actually being generated?

The html is as follows.

I hope you (or anyone) can give me an aswer. Thanks beforehand.

<input id="text2" name="text2" type="text" />

Hi,

am playing with the blur option myself, and am confused.

Notice that it only has two arguments. The third argument added by
the build_observer helper is not passed along to the prototype.js
function. The actual event is made wholly dependent on:
switch (element.type.toLowerCase()) {
which is just a fancy way of saying ‘change’ when that’s ‘click’ for
checkboxes and radio buttons.

Regardless of the rails code analysis, the fact is that if I
put :on=>‘blur’ into my observer, then I get the blur parameter in the
javascript.

Trouble is it doesn’t seem to work!!

When I look at the various references for Prototype (and I am NOT
javascript clever) then I can see no reference to
Form.Element.EventObserver supporting a blur event. It appears to
inherit from Abstract.EventObserver which, it says, only supports
onclick and onchange. Perhaps this is the point that Rob was trying
to make.

Anyway it seems very odd to me that Prototype does not support an on
blur event, and even stranger that Rails implementation suggests that
it does. Maybe someone with understanding of Prototype could clarify,
and hopefully explain how to get to it nicely from Rails. The
alternative I guess, is to use a different JS library, as suggested in
another post, but then it is a case of building our own helpers. Or,
I wonder how difficult it would be to create an on blur event trigger
directly from a Rails helper?

I really do want to do on blur detection on one of my forms. Can
anyone help.

Thanks
Tony

On Jun 24, 2007, at 2:57 PM, Fernando P. wrote:

Ajax.Updater(‘ajaxWrapper’, ‘/pruebas/test’, {asynchronous:true,
evalScripts:true, parameters:‘text1=’ + value})}, ‘blur’)
//]]>

This code is from Rails 1.2.2, but you should be able to track this
down in your version if different.

The problem is that the documentation is simply wrong. Let’s look at
the code:

vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb:287:
def observe_field(field_id, options = {})
if options[:frequency] && options[:frequency] > 0
build_observer(‘Form.Element.Observer’, field_id, options)
else
build_observer(‘Form.Element.EventObserver’, field_id,
options)
end
end

line 662:
def build_observer(klass, name, options = {})
if options[:with] && !options[:with].include?(“=”)
options[:with] = “‘#{options[:with]}=’ + value”
else
options[:with] ||= ‘value’ if options[:update]
end

     callback = options[:function] || remote_function(options)
     javascript  = "new #{klass}('#{name}', "
     javascript << "#{options[:frequency]}, " if options[:frequency]
     javascript << "function(element, value) {"
     javascript << "#{callback}}"
     javascript << ", '#{options[:on]}'" if options[:on]
     javascript << ")"
     javascript_tag(javascript)
   end

public/javascripts/prototype.js:2124:
Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;

 this.lastValue = this.getValue();
 if (this.element.tagName.toLowerCase() == 'form')
   this.registerFormCallbacks();
 else
   this.registerCallback(this.element);

},

onElementEvent: function() {
var value = this.getValue();
if (this.lastValue != value) {
this.callback(this.element, value);
this.lastValue = value;
}
},

registerFormCallbacks: function() {
Form.getElements(this.element).each(this.registerCallback.bind
(this));
},

registerCallback: function(element) {
if (element.type) {
switch (element.type.toLowerCase()) {
case ‘checkbox’:
case ‘radio’:
Event.observe(element, ‘click’, this.onElementEvent.bind
(this));
break;
default:
Event.observe(element, ‘change’, this.onElementEvent.bind
(this));
break;
}
}
}
}

Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = Object.extend(new
Abstract.EventObserver(), {
getValue: function() {
return Form.Element.getValue(this.element);
}
});

So a Form.Element.EventObserver has an initialization function from
Abstract.EventObserver which looks like this (seen above also):
Abstract.EventObserver.prototype = {
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;

Notice that it only has two arguments. The third argument added by
the build_observer helper is not passed along to the prototype.js
function. The actual event is made wholly dependent on:
switch (element.type.toLowerCase()) {
which is just a fancy way of saying ‘change’ when that’s ‘click’ for
checkboxes and radio buttons.

Now, could the initialize function be changed in
Abstract.EventObserver to use the third argument as the event to
observe if provided and still fall back to using the element type?
Sure. But the moral of this story is that the code itself is the
most reliable place to find out how something works – don’t assume
that the documentation is always correct.

Of course, these very changes may have already been made in the most
recent versions of prototype and Rails, but I’ll leave that
investigation to the diligent reader. :wink:

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

Actually, :on => blur does not work.
As Tony says, the parameter is passed to the javascript but doesn’t work
anyway.
And, as Rob said before, the documentation and the code itself it’s
simply wrong.

What I needed was on blur and my time was limited so what I did was to
change prototype.js. Now I got my own version of prototype that does on
blur detection but does ONLY on blur detection. So, if you want the same
I did, I can give you more details but if you want to get on blur,
focus, hover, etc., you’ll have to wait for an official and corrected
version of prototype.

Greetings

And thanks Rob for your answer. It really helped me.