The main content of this article is taken from Caridy Patino’s article published in 2008. The original article uses YUI2. I have updated the example to use YUI3.1.1.

In common application scenarios, tabs are used to save and efficiently utilize page space. If we have a Tab, and each Tab is presented with a different function, I will choose to put the JS code that handles user events on the page when there are fewer functions. For example, in the case of YUI:

Build the page DOM:

Build the page DOM that meets the requirements (of course we could also use YUI to create the DOM dynamically, but that would lose the search-engine friendliness).

<div id=”demo”>

<ul>

<li><a href=”#foo”>foo</a></li>

<li><a href=”#bar”>bar</a></li>

<li><a href=”#baz”>baz</a></li>

</ul>

<div>

<div id=”foo”>

foo content

<p><a href=”javascript:void(0);” id=”fooLink”>Click Me</a></p>

</div>

<div id=”bar”>

bar content

<p><a href=”javascript:void(0);” id=”barLink”>Click Me</a></p>

</div>

<div id=”baz”>

baz content

<p><a href=”javascript:void(0);” id=”bazLink”>Click Me</a></p>

</div>

</div>

</div>

Javascript code:

//Create YUI Instance YUI({base:’.. /lib/yui/build/’,combine:true}).use(‘tabview’, function(Y){ var tabview = new Y.TabView({ srcNode:”#demo” });

    tabview.render();

    //public message function

function message(e){

var node = e.currentTarget;

alert(node.get(“id”) + ” Clicked “);

}

    // attach event handler

Y.one(“#fooLink”).on(“click”, message);

Y.one(“#barLink”).on(“click”, message);

Y.one(“#bazLink”).on(“click”, message);

});

In this way, we create a TabView and assign a processing event to each connection in the TabView (of course, the example uses one instead). This is fine when there are few elements and events in Tab content, but it becomes a problem when the content increases and is loaded dynamically through Ajax.

The Problem

But this approach can introduce certain dependencies and complexity within our code, Because the actions for a certain TAB’s content will be defined at the page level, which means that if you want change the content of tab, You probably need to change something at the application level as well — the functionality of the TAB’s content is not encapsulated with that content.

Because this approach defines events in response to TAB content changes at the page level, it adds dependency and complexity to the program. If you want to change the TAB’s content, you have to change a lot of things in the program — meaning that the TAB’s content and its functionality are not well encapsulated.

Using Ajax to load content dynamically can be done through YUI’s plug-in mechanism if you want to trigger actions after returning content, or bind events to elements in the returned content. It is not possible to embed

In my experiments, I found that this problem did not exist in YUI3.1.1, and the scripts included in the returned content executed normally. This is a great feature, which means that we can encapsulate the content and logical processing together, thus making our code structure clearer. Here is the tested code, mostly source code on YUI Tabview.

        TabIO = function(config) {

TabIO.superclass.constructor.apply(this, arguments);

};

Y.extend(TabIO, Y.Plugin.WidgetIO, { initializer: function() { var tab = this.get(‘host’); tab.on(‘selectedChange’, this.afterSelectedChange); tab.on(‘contentUpdate’, this.contentUpdate); tab.get(‘panelNode’).on(‘contentUpdate’, this.contentUpdate); }, contentUpdate:function(e){ alert(“test”); }, afterSelectedChange: function(e) { // this === tab if (e.newVal) { // tab has been selected this.io.refresh(); }},

            setContent: function(content) {

var tab = this.get(‘host’);

tab.set(‘content’, content);

},

            _toggleLoadingClass: function(add) {

this.get(‘host’).get(‘panelNode’)

.toggleClass(this.get(‘host’).getClassName(‘loading’), add);

}

        }, {

NAME: ‘tabIO’,

NS: ‘io’

});

        var tabview = new Y.TabView({

srcNode:”#demo”

});

Y.each(feeds, function(src, label) {

tabview.add({

label: label,

plugins: [{

fn: TabIO,

cfg: {

uri: src

}

}]

});

});

        tabview.render();

        //public message function

function message(e){

var node = e.currentTarget;

alert(node.get(“id”) + ” Clicked “);

}

        // attach event handler

Y.one(“#fooLink”).on(“click”, message);

Y.one(“#barLink”).on(“click”, message);

Y.one(“#bazLink”).on(“click”, message);

});

</script>

 

Even better, if the return result contains a reference to an external script, the referenced script will also be executed. Here is the server-side code.

<? php

$html = ”; if( isset($_GET[‘query’]) ){ switch($_GET[‘query’]){ case “chrome”: $html .= “Chrome

“; $html .= “Chrome

“; $html .= “Chrome

“; $html .= time(); break; case “firefox”: $html .= “Firefox

“; $html .= “Firefox

“; $html .= “Firefox

“; $html .= time(); break; case “safari”: $html .= “Safari

“; $html .= “Safari

“; $html .= “Safari

“; $html .= time(); break; case “explorer”: $html .= “Explorer

“; $html .= “Explorer

“; $html .= “Explorer

“; $html .= time(); break; } $html .= “

Delegate Event

“; $html .= ““; $html .= ““; echo $html; }

 

In YUI 3.1, using node.set(‘ content ‘) alone will not parse the script in the content. In this case, There are two very useful tools that you can use: “Dispatcher” and Node. delegate.

The former is a member of the Bubbling Library, while the latter is a very useful tool provided by YUI.

I’ll leave it there for today, and I’ll talk more about what happens when you don’t have a Tab.

References:

1, Useing the TabView Control with My Dispatcher Plugin

2, YUI Tabview

3, Progressive Enhancemeng

4, YUI Plugin