/** * @author Ryan Johnson * @copyright 2008 PersonalGrid Corporation * @package LivePipe UI * @license MIT * @url http://livepipe.net/control/tabs * @require prototype.js, livepipe.js */ /*global window, document, Prototype, $, $A, $H, $break, Class, Element, Event, Control */ if(typeof(Prototype) == "undefined") { throw "Control.Tabs requires Prototype to be loaded."; } if(typeof(Object.Event) == "undefined") { throw "Control.Tabs requires Object.Event to be loaded."; } Control.Tabs = Class.create({ initialize: function(tab_list_container,options){ if(!$(tab_list_container)) { throw "Control.Tabs could not find the element: " + tab_list_container; } this.activeContainer = false; this.activeLink = false; this.containers = $H({}); this.links = []; this.options = { beforeChange: Prototype.emptyFunction, afterChange: Prototype.emptyFunction, hover: false, tracked: true, linkSelector: 'li a', linkAttribute: 'href', setClassOnContainer: false, activeClassName: 'active', disabledClassName: 'disabled', defaultTab: 'first', autoLinkExternal: true, targetRegExp: /#(.+)$/, showFunction: Element.show, hideFunction: Element.hide }; Object.extend(this.options,options || {}); if (this.options.tracked) { Control.Tabs.instances.push(this); } var filterLinks; switch (this.options.linkAttribute) { case 'href': case 'src': filterLinks = function(link){ return (/^#/).test(link.getAttribute(this.options.linkAttribute).replace( window.location.href.split('#')[0],'')); }; break; default: if (typeof(this.options.linkAttribute) == 'function') { filterLinks = this.options.linkAttribute; } else { filterLinks = function(link) { return link.hasAttribute(this.options.linkAttribute); }; } } (typeof(this.options.linkSelector) == 'string' ? $(tab_list_container).select(this.options.linkSelector) : this.options.linkSelector($(tab_list_container)) ).findAll(filterLinks.bind(this)).each(function(link){ this.addTab(link); }.bind(this)); this.containers.values().each(Element.hide); if(this.options.defaultTab == 'first') { this.setActiveTab(this.links.first()); } else if(this.options.defaultTab == 'last') { this.setActiveTab(this.links.last()); } else { this.setActiveTab(this.options.defaultTab); } var targets = this.options.targetRegExp.exec(window.location); if(targets && targets[1]){ targets[1].split(',').each(function(target){ this.setActiveTab(this.links.find(function(link){ return link.key == target; })); }.bind(this)); } if(this.options.autoLinkExternal){ $A(document.getElementsByTagName('a')).each(function(a){ if(!this.links.include(a)){ var clean_href = a.href.replace(window.location.href.split('#')[0],''); if(clean_href.substring(0,1) == '#'){ if(this.containers.keys().include(clean_href.substring(1))){ $(a).observe('click',function(event,clean_href){ this.setActiveTab(clean_href.substring(1)); }.bindAsEventListener(this,clean_href)); } } } }.bind(this)); } }, addTab: function(link){ this.links.push(link); switch (this.options.linkAttribute) { case 'href': case 'src': link.key = link.getAttribute(this.options.linkAttribute).replace( window.location.href.split('#')[0],'').split('#').last().replace(/#/,''); break; default: if (typeof(this.options.linkAttribute) == 'function') { link.key = this.options.linkAttribute(link); } else { link.key = link.getAttribute(this.options.linkAttribute); } } var container = this.options.tabs_container ? this.options.tabs_container.down('#'+link.key) : $(link.key); if(!container) { throw "Control.Tabs: #" + link.key + " was not found on the page."; } this.containers.set(link.key,container); link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){ if(window.event) { Event.stop(window.event); } this.setActiveTab(link); return false; }.bind(this,link); }, getTab: function (link) { if(!link && typeof(link) == 'undefined') { return null; } if(typeof(link) == 'string'){ return this.getTab(this.links.find(function(_link){ return _link.key == link; })); }else if(typeof(link) == 'number'){ return this.getTab(this.links[link]); }else { return this.containers.get(link.key); } }, setActiveTab: function(link){ if(!link && typeof(link) == 'undefined') { return; } if(typeof(link) == 'string'){ this.setActiveTab(this.links.find(function(_link){ return _link.key == link; })); }else if(typeof(link) == 'number'){ this.setActiveTab(this.links[link]); }else if(!(this.options.setClassOnContainer ? $(link.parentNode) : link).hasClassName(this.options.disabledClassName)){ if(link == this.activeLink) { return; } if(this.notify('beforeChange',this.activeContainer,this.containers.get(link.key)) === false) { return; } if(this.activeContainer) { this.options.hideFunction(this.activeContainer); } this.links.each(function(item){ (this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName); }.bind(this)); (this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName); this.activeContainer = this.containers.get(link.key); this.activeLink = link; this.options.showFunction(this.containers.get(link.key)); this.notify('afterChange',this.containers.get(link.key)); } }, disableTab: function (link) { if(!link && typeof(link) == 'undefined') { return; } if(typeof(link) == 'string'){ this.disableTab(this.links.find(function(_link){ return _link.key == link; })); }else if(typeof(link) == 'number'){ this.disableTab(this.links[link]); }else{ if ({'INPUT':true,'BUTTON':true,'SELECT':true,'TEXTAREA':true}[link.nodeName]) { link.disabled = true; } (this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.disabledClassName); } }, enableTab: function (link) { if(!link && typeof(link) == 'undefined') { return; } if(typeof(link) == 'string'){ this.enableTab(this.links.find(function(_link){ return _link.key == link; })); }else if(typeof(link) == 'number'){ this.enableTab(this.links[link]); }else{ if ({'INPUT':true,'BUTTON':true,'SELECT':true,'TEXTAREA':true}[link.nodeName]) { link.disabled = false; } (this.options.setClassOnContainer ? $(link.parentNode) : link).removeClassName(this.options.disabledClassName); } }, next: function(){ this.links.each(function(link,i){ if(this.activeLink == link && this.links[i + 1]){ this.setActiveTab(this.links[i + 1]); throw $break; } }.bind(this)); }, previous: function(){ this.links.each(function(link,i){ if(this.activeLink == link && this.links[i - 1]){ this.setActiveTab(this.links[i - 1]); throw $break; } }.bind(this)); }, first: function(){ this.setActiveTab(this.links.first()); }, last: function(){ this.setActiveTab(this.links.last()); } }); Object.extend(Control.Tabs,{ instances: [], findByTabId: function(id){ return Control.Tabs.instances.find(function(tab){ return tab.links.find(function(link){ return link.key == id; }); }); } }); Object.Event.extend(Control.Tabs);