Search code examples
javascripthtmlfirefoxmootools

Firefox form inputs/divs inside label behaviour


I am submitting a form via javascript as callback of a label click. It works on all browsers except Firefox, and I am currently testing on FF24.

This is the label structure:

<label>
    <input type="radio" name="itsname" value="1">
    <div>
        <img />
    </div>
    <div></div>
    <div><br></div>
    <div>
        <div>
            <div></div>
            <div>
                <span></span>
            </div>
        </div>
        <div>
            <div></div>
            <div>
                <span></span>
            </div>
        </div>
    </div>
</label>

And this is the (pseudo)code for submitting the parent form:

label.addEvent('click', function () {
    if(Browser.firefox) this.getChildren('input')[0].set('checked', true)
    this.getParents('form')[0].submit()
})

As you can see, the code is already fixed for FF, so I am not really looking for a solution but just for a more or less detailed explanation on why the additional code is mandatory for making the script work in FF. I already know the radio input gets checked "too late" otherwise.


Solution

  • this is probably a race condition whereby the form .submit() hijacks the default label behavior and prevents it from bubbling to the input and changing its value.

    http://jsfiddle.net/dimitar/mjLya/

    var html = document.getElement('input[type=hidden]');
    document.getElements('label input[type=radio] ! label').addEvent('click', function(){
        html.set('value', 'submitted with ' + this.getElement('input[type=radio]').get('checked'));
        this.getParent('form').submit();
    });
    

    in FF 23, it echoes back 'submitted with false'. Actually, same on Chrome 29.

    The following change, adding a 10ms delay before submit, seems to allow the label click event to bubble to the input and set the value:

    var html = document.getElement('input[type=hidden]');
    document.getElements('label input[type=radio] ! label').addEvent('click', function(){
        // you can do this:
        // this.getElement('input[type=radio]').set('checked', true);
        html.set('value', 'submitted with ' + this.getElement('input[type=radio]').get('checked'));
        var f = this.getParent('form');
        f.submit.delay(10, f);
    });