[Fabio M Costa] New changed event

Have you ever had problems with the ‘change’ event? I did, in particular on text-inputs.

I’ll list the crazy behaviors i don’t like about it:

  • If you change the value of a text input and submit the actual form by pressing enter, on Opera the change event won’t fire!;
  • If you apply keydown, keypress or keyup and any of them returns false (this is used on meioMask and most of the plugins that filters the input from the user), the change event won’t fire!;
  • If you focused on a text input and some script you made changes the value from this input, when you blur it the change even’t won’t fire!;
  • On IE, if you choose one of the native auto-complete options that is shown when you focus without typing anything, change event won’t fire!

That’s why i created this new glossy ‘changed’ event, which is the change event but fixing all these problems i listed. It uses the power of the Mootools custom events to create this new event that can be used like any other event.

I’ve created a page to show it working.

/**
 * @author Fábio Miranda Costa <fabiomcosta [at] gmail [dot] com>
 * 09-07-2009
 * http://www.meiocodigo.com
 * Changed Event for Mootools 1.2.x
 */</p>

<p>(function(){</p>

<pre><code>var $ = document.id || $;
var STORAGE_VALUE = 'changed-event-value-storage';
var lastFocused = null;
var focusFunc = function(){
    lastFocused = this;
    this.store(STORAGE_VALUE, this.get('value'));
};
var submitFunc = function(e){
    if(check.call(lastFocused)){
        lastFocused.fireEvent('changed');
    }
};
var check = function(e){
    var storedValue = this.retrieve(STORAGE_VALUE);
    // this happens when you focus the input before adding the changed event on the input
    if(storedValue === null) return false;
    return this.value !== storedValue;
};

Element.Events.changed = {
    base: 'blur',
    onAdd: function(){
        var evts = this.retrieve('events');
        if(!(evts &amp;&amp; evts.focus &amp;&amp; evts.focus.keys.contains(focusFunc))){
            this.addEvent('focus', focusFunc);
            var formEl = $(this.form), fevts = formEl.retrieve('events');
            if(!(fevts &amp;&amp; fevts.submit &amp;&amp; fevts.submit.keys.contains(submitFunc))){
                formEl.addEvent('submit', submitFunc);
            }
        }
    },
    condition: function(e){
        e.type = 'changed';
        return check.call(this, e);
    },
    onRemove: function(){
        var evts = this.retrieve('events');
        if(!evts.changed.keys.length){
            this.removeEvent('focus', focusFunc);
            if(lastFocused == this) lastFocused = null;
            if(!submitInputs.length){
                $(this.form).removeEvent('submit', submitFunc);
            }
        }
    }
};
</code></pre>

<p>})();

I’m sorry about the entities errors on the code, its this f…. s…. blog system that simply can’t do it right. If anybody know how to solve this, please let me know.

It won’t hurt if i remember that it should only be used on text inputs (it wont work as expected on radiobuttons and checkboxes) and you should apply the event before you focus the element (its kind of obvious but as i said, it won’t hurt).

Did i tell you that Mootools rocks? ;)