/**
 *  Tabs v1
 *  PB/Graphico February 2009;
 *  Show/hide multiple panels via a set of tabs, each one linked to a unique panel;
 *
 *  Supported browsers Firefox 3(Mac & PC), IE 6 &7 , Opera 9.5(PC), Safari 3(Mac).
 *
 *  Example use;
 *  var options = {
 *      id: '[id of default panel],
 *  }
 *  $('#panels').tabs(options);
 *
 *  Requires the panels to be built with the following html, utilising document anchors;
 *  <div id="[unique id]" class="section">
 *      <div class="nav">
 *          <ul>
 *              <li>
 *                 <a href="#[id 1]">[desc]</a>
 *              </li>
 *              <li>
 *                 <a href="#[id 2]">[desc]</a>
 *              </li>
 *              more nav elems....
 *          </ul>
 *      </div>
 *      <div id="[id 1]">
 *          content....
 *      </div>
 *      <div id="[id 2]">
 *          content....
 *      </div>
 *      more divs....
 *  </div>
 *
 *  Supported options;
 *  id: String, id of the panel to show by default;
 *
 * fires the following custom events;
 * tabsupdate:      fired immediately before a new panel is made visible;
 * tabscomplete:    fired a new panel is made visible;
 */
(function(jq) {
    jq.fn.tabs = function(options) {
        jq.extend(jq.fn.tabs.defaults, options);
        var tab = new Tab(this);
        return jq('.nav a', this).bind('click', function(){
            jq(document).trigger('tabsupdate', {tab:this});
            tab.update(this);
            return false;
        });
    };
    jq.fn.tabs.defaults = {
        id: null
    };
    /**
     * constructor;
     * @param   obj:{jQuery}  ref to tabs container;
     */
    function Tab(obj) {
        this.container = obj;
        this.reset();
        this.setDefault(jq.fn.tabs.defaults.id);
    };
    /**
     * Tab public methods/props;
     */    
    Tab.prototype = {
        /**
         * updates shows the selected panel and updates the link state;
         * @param   elem:{HTMLAnchorElement}  ref to clicked tab;
         */
        update: function(elem){
            var id = this.getId(elem.href);
            this.reset();
            jq(elem).parent().filter('li').addClass('active');
            jq('.panel', this.container).filter(function(){
                return this.id == id;   
            }).show();
            jq(document).trigger('tabscomplete', {panel:id, tab:elem});
            return true;
        },
        /**
         * reset (hide) all panels;
         */
        reset: function(){
            jq('.nav li', this.container).filter(function(){
                return this.className.indexOf('active') !== -1;    
            }).removeClass('active'); 
            return jq('.panel', this.container).hide(); 
        },
        /**
         * splits the document anchor from the supplied url;
         * @param   url:{String}  contains document anchor;
         * @returns String;
         */
        getId: function(url){
            return url.split('#')[1];
        },
        /**
         * show the default panel;
         * @param   id:{String}  ref to visible panel id;
         */
        setDefault: function(id){
            var self = this;
            var link = jq('.nav a', this.container).filter(function(){
                return self.getId.call(self, this.href) == id;
            }).get(0);
            return this.update(link);
        }
    };
})(jQuery);