rangerer.at

YUI inheritance

At work we are using the gallery-node-accordion module from the YUI gallery to group content into sections. While the module is quite useful to transform already existing content into an accordion structure, it falls short on ways to hook into the accordion lifecycle. A typical task might be to load ads when opening a section or scroll to the head of the section once the accordion animation is complete. Normally you could accomplish those hooks by firing events for those specific moments in the accordion lifecycle and let users subscribe to those events to add business logic. Unfortunately caridy (the developer of gallery-node-accordion) did only leave todo comments instead of actually firing those events.

The proper solution would have been to fork caridys work from github, add those events, post a pull request for caridy and point our application to use my version of gallery-node-accordion. I decided to take the easy option and create a class that would inherit from Y.Plugin.NodeAccordion and overwrite the methods that I want to fire events for.

Y.namespace('Plugin').PeopleAccordion = Y.Base.create('PeopleAccordion', Y.Plugin.NodeAccordion, [], {
    initializer: function(config) { ... },
    _openItem: function(item) { ... }
}, { NS: 'accordion' });

It took me quite a while to get the above code working and have a functioning Y.Plugin.PeopleAccordion class that I could use. The main reason was that although NodeAccordion does already supply the static NS attribute it needs to be supplied by PeopleAccordion as well.

When using Y.Base.create the initializer function is augmented with the one from NodeAccordion and therefore you can simply add your code and both functions will be called. So the only thing left to do was firing an event in _openItem and forward the call to NodeAccordion._openItem. After playing around for another few hours I came to the conclusion that there is no way to call the parents _openItem method from the PeopleAccordion instance. I was able to get a prototype of NodeAccordion and call (or apply) the _openItem method, but as that method needs to operate on the instances attributes it was no good.

I was at a dead end and had to resort to replacing the click event handlers in PeopleAccordion with my own.

node.plug(Y.Plugin.Accordion, { ... });
node.accordion._eventHandler.detach();
node.accordion._eventHandler = this.delegate('click', function(e) {
    // custom code
    node.accordion.toggleItem( e.target );
    e.target.blur();
    e.halt();
}, '.yui3-accordion-item-trigger');