/*

pdx.prototype.gadgets.tabbars: a simple tab bar manager
  v1.0, 2011/03/13, initial release
  v1.1, 2011/03/14, options.stripBetweenWhitespace='full' support

  CC BY-SA 2011. Andras Kemeny (http://www.pdx.hu/)
    http://creativecommons.org/licenses/by-sa/3.0/legalcode
  NO WARRANTIES! however, it's tested on IE7/8, Firefox 3.5.x, Opera 10+,
    Chrome & Safari, and it works.
  REQUIRES prototype.js to work.
    http://www.prototypejs.org/

general info:

accepts tab bar controllers in either format (for graceful degradation):
  <ul 
   [role="tabbar"] 
   idprefix="<common_id_prefix>" 
   controls="<tabbar_control_id>" 
   [defaulttab="<default>"]>
    <li><a href="#<tabname1>">tab 1 label</a></li>
    <li><a href="#<tabname2>">tab 2 label</a></li>
    ...
  </ul>
OR
  <div
   [role="tabbar"] 
   idprefix="<common_id_prefix>" 
   controls="<tabbar_control_id>" 
   [defaulttab="<default>"]>
    <a href="#<tabname1>">tab 1 label</a>
    <a href="#<tabname2>">tab 2 label</a>
    ...
  </ul>

the content fragments controlled by the tabbar must be block elements, and must
have the following syntax:
  <a name="<tabname>"></a>
(this is for making sure that a degraded version remains navigable, but not a
must-have)
  <h2 class="onlyprint">tab label</h2>
(this one is for printing or for dumb browsers, it should be hidden in media=
screen)
  <div id="<common_id_prefix><tabname>" controller="<tabbar_control_id>">
   ...tab contents...
  </div>

[role="tabbar"] is optional, however, it's the default CSS selector pattern, if
you want to use anything else, make sure to overwrite tabbars.options.selecta
before the DOM tree finishes loading as tabbars initializes by dom:loaded.

usage:

1. prepare the structures above. if you don't need any tab bars on your page,
   tabbars.init() will return with no modifications to the DOM tree.
2. enjoy! tabbars auto-initializes at dom:loaded stage, so you don't have to do
   anything.
3. if you want to change the defaults, see comment at the end of this file.

tabbars.options(: default):

  selecta: '[role=tabbar]'
    the CSS selector pattern that identifies tabbar controllers.
  selectedClass: 'selected'
    the classname tabbars adds to the selected tab.
  stripBetweenWhitespace: true
    try and strip the whitespace between tabs. if set to false, it leaves the
    non-element parts alone. if set to 'full', it removes any and all text and
    comment nodes regardless of their content.

*/

var tabbars = {
 options: {
  selecta: '[role=tabbar]',
  selectedClass: 'selected',
  stripBetweenWhitespace: 'full'
 },
  _initialized: false,
 init: function() {
	if (tabbars._initialized===true) return(true);
	tabbars._initialized = true;
 	$$(tabbars.options.selecta).each(function(ulist) {
 		var cts = ulist.getAttribute('controls');
 		var def = (ulist.hasAttribute('defaulttab')===true) ? ulist.getAttribute('defaulttab') : null;
 		var defitem = null;
 		var idpref = ulist.getAttribute('idprefix');
 		$$('[controlled='+cts+']').each(function(el) { el.style.display = 'none'; });
 		var chi = ulist.childElements();
 		if (chi.length>0) for(var i=0;i<chi.length;i++) {
 			if (chi[i].tagName.toLowerCase()=='li') {
 				var tabto = tabbars._afterHash(chi[i].firstDescendant().getAttribute('href'));
 				chi[i].innerHTML = chi[i].firstDescendant().innerHTML;
 			}
 			else if (chi[i].tagName.toLowerCase()=='a') {
 				var tabto = tabbars._afterHash(chi[i].getAttribute('href'));
 				chi[i].removeAttribute('href');
 			}
 			if ((def===null)&&(i==0)) def = tabto;
			chi[i].setAttribute('activates',tabto);
			chi[i].observe('click',tabbars.itemClicked);
			if (tabto==def) defitem = chi[i];
 			
 		}
 		if (defitem!==null) tabbars.itemClick2(defitem);
 		if (tabbars.options.stripBetweenWhitespace===true) {
 			ulist.cleanWhitespace();
 		}
 		else if (tabbars.options.stripBetweenWhitespace=='full') {
 			var textnodes = [];
 			var chi = ulist.childNodes;
 			if (chi.length>0) for(var i=0;i<chi.length;i++) {
 				if ((parseInt(chi[i].nodeType)==3)||(parseInt(chi[i].nodeType)==8))
 					textnodes.push(chi[i]);
 			}
 			if (textnodes.length>0) for(var i=0;i<textnodes.length;i++) ulist.removeChild(textnodes[i]);
 		}
 	});
 },
 _afterHash: function(linka) {
 	linka = linka.substr(linka.lastIndexOf('#')+1);
 	return(linka);
 },
 itemClicked: function(ev) {
 	var el = ev.element();
 	tabbars.itemClick2(el);
 	ev.stop();
 },
 itemClick2: function(el) {
 	var cho = el.getAttribute('activates');
 	tabbars.currsel = cho;
 	var par = $(el.parentNode);
	var cts = par.getAttribute('controls');
	var idpref = par.getAttribute('idprefix');
	$$('[controller='+cts+']').each(function(el) { el.style.display = 'none'; });
	$$('[controller='+cts+'][id='+idpref+cho+']').each(function(el) { el.style.display = 'block'; });
	par.select('[activates]').each(function(litem) {
		if (litem.getAttribute('activates')==tabbars.currsel) {
			if (litem.hasClassName(tabbars.options.selectedClass)===false) litem.addClassName(tabbars.options.selectedClass);
		} else {
			if (litem.hasClassName(tabbars.options.selectedClass)===true) litem.removeClassName(tabbars.options.selectedClass);
		}
	});
 }
}

/* by default, tabbars.init() gets executed at dom:loaded stage to avoid un-
   necessary fuss. however, if you want to initialize at another stage, put
   in a javascript snippet BEFORE the </body> tag:
     document.stopObserving('dom:loaded',tabbars.init);
   also, if you want to change the defaults (in tabbars.options), make sure
   you do it before the DOM tree loads, also before the </body> tag. */
document.observe('dom:loaded',tabbars.init);

