Search code examples
javascriptprototypejsdom-eventsprototype-chosen

Update prototype chosen.js dynamically


I'm a new to Prototype and I can't really understand the minimalist documentation provided here http://harvesthq.github.com/chosen/

It says that to update chosen.js dynamically, we should use this snippet

Event.fire($("form_field"), "liszt:updated");

What I don't understand is, which element need to be targeted on that Event.fire. Here in my case, I have a dynamic form with two select element. On which the second select element is enabled only after user choose the option on first select element. Like on this illustration:

color enabled only after user choose size

So I just tried it out on my code. Here it is:

// let say I want to make all .chzn-select element replaced by chosen.js
var el = $$(".chzn-select");

// this is the code to make all .chzn-select replaced by chosen.js
document.observe('dom:loaded', function(evt) {
     var select, selects, _i, _len, _results;
     if (Prototype.Browser.IE && (Prototype.BrowserFeatures['Version'] === 6 || Prototype.BrowserFeatures['Version'] === 7)) { return; }
     selects = el;  _results = [];
     for (_i = 0, _len = selects.length; _i < _len; _i++) {
        select = selects[_i];
        _results.push(new Chosen(select));
     }
}); 

// this is what I used to observe the change event of the .chzn-select element
el.invoke('observe', 'change', function() {
    // I have successfully updated all the .chzn-select element after the change of some other .chnz-select
    myOwnObjet.myOwnFunction(el);

    // now this is where I get confused, I want to update all the generated chosen.js selector
    Event.fire(el, "liszt:updated");
});

on that example, that Event.fire seems to be not working at all... So what I am doing wrong here? how exactly I could update that chosen.js version of color select to updated after user choose the size select?


Solution

  • In your invocation of the observe event on all the .chzn-select elements, you use el as the current element, it will not reflect the actual element in the array.

    Try this:

    el.invoke('observe', 'change', function(ev) {
        var nev = Event.element(ev);
        myOwnObject.myOwnFunction(nev);
    
        Event.fire(nev, 'liszt:updated');
    });
    

    UPDATE

    Ok, after thoroughly investigating, I found the problem, event.simulate was not being included, i completely fixed the code, check out this fiddle.

    Here is the code used in the fiddle:

    var selects;
    document.observe('dom:loaded', function(evt) {
        selects = $$('select.chzn-select').inject($H(), function(hsh, sl) {
            hsh.set(sl.id, new Chosen(sl));
            return hsh;
        });
    
        selects.each(function(pair) {
            Event.observe($(pair.key), 'change', function(ev) {
                myOwnFunction($(pair.key), pair.value);
            });
        });
    });
    
    function myOwnFunction(select, chzn) {
        if (select.id === 'sl-color') {
            var size = $('sl-size');
            size.disabled = false;
    
            Event.fire(size, 'liszt:updated');             
        }
    }
    ​