/* idTabs v3.0 ~ Sean Catchpole - Copyright 2009 MIT/GPL */
;(function($){ if(!$) return;
//TODO: add support for .live (probably shouldn't do this)
//TODO: add support for liveQuery
//TODO: add support for rebinding, unbinding
//TODO: needs testing with different browsers
//TODO: needs testing with older versions of jQuery
//TODO: Changes for 3.0
/* return removed (it was depreciated)
 * passing arguments changed (id,s)
 * refresh of code speed and accuracy
 * items now object instead of id's
 * multiple tabs can now point to same id
 * removed autoloading jQuery
 * added item classes support
 * properly unbinds
 * extend idTabs
 */

/* Options (in any order):

 start (number|string)
    Index number of default tab. ex: $(...).idTabs(0)
    String of id of default tab. ex: $(...).idTabs("#tab1")
    default: class "selected" or index 0
    Passing -1 or null will force it to not select a default tab

 change (boolean)
    True - Url will change. ex: $(...).idTabs(true)
    False - Url will not change. ex: $(...).idTabs(false)
    default: false

 click (function)
    Function will be called when a tab is clicked. ex: $(...).idTabs(foo)
    If the function returns false, idTabs will not take any action,
    otherwise idTabs will show/hide the content (as usual).
    The function is passed two variables:
      The id of the element to be shown
      and the settings object which has the following additional items:
        area     - the original area $(area).idTabs();
        tabarea  - the current tab area used to find tabs
        tabs     - a jQuery list of tabs
        items    - a jQuery list of the elements the tabs point to
        tab(id)  - a helper function to find a tab with id
        item(id) - a helper function to find an item with id

 selected (string)
    Class to use for selected. ex: $(...).idTabs(".current")
    default: ".selected"

 event (string)
    Event to trigger idTabs on. ex: $(...).idTabs("!mouseover")
    default: "!click"
    To bind multiple events, call idTabs multiple times
      ex: $(...).idTabs("!click").idTabs("!focus")

*/

// Helper functions
var idTabs, //shortcut
href = function(e){ return $(e).attr("href"); },
type = function(o){
  var s = Object.prototype.toString.call(o); //reliable
  return s.substr(8,s.length-9); //only need the name
};

$.fn.idTabs = function(){
  // Loop through arguments matching options
  var data,a,i=0,s={},args=arguments;
  while(i<args.length) {
    a=args[i++];
    switch(type(a)){
      case "Object"   : $.extend(s,a); break;
      case "Boolean"  : s.change = a;  break;
      case "Number"   : s.start = a;   break;
      case "Function" : s.click = a;   break;
      case "String"   :
        if(a.indexOf('.')==0) s.selected = a;
        else if(a.indexOf('!')==0) s.event = a;
        else if(a) s.start = a;
      default: break;
    }
  }

  s.area = this; //save context
  data = "idTabs"+ +new Date; //instance expando
  return this.each(function(){ $.idTabs(this,s,data); }); //chainable
};

idTabs = $.idTabs = function(tabarea,options,data){
  // Settings
  var test,list,meta = $.metadata?$(tabarea).metadata():{}, //metadata
  s = {tab:idTabs.tab,item:idTabs.item}; //helpers
  s = $.extend(s,idTabs.settings,meta,options||{}); //settings
  s.tabarea = tabarea; //save context
  s.data = data||"idTabs"+ +new Date; //save expando

  // Play nice
  $.each({selected:'.',event:'!',start:'#'},function(n,c){
    if(type(s[n])=="String" && s[n].indexOf(c)==0)
      s[n] = s[n].substr(1); }); //removes type characters
  if(s.start===null) s.start=-1; //no tab selected

  // Find tabs
  s.tabs = $([]); //save tabs
  s.items = $([]); //save elements
  $("a[href^=#]",tabarea).each(function(){
    s.tabs.push(this);
    s.items = s.items.add(s.item(href(this)));
  });

  // Bind idTabs
  list = $("a[href^=#]",tabarea).trigger("idTabs."+s.event).data(s.data,s);
  list.bind(s.event,{s:s},idTabs.find).bind("idTabs."+s.event,{s:s},idTabs.unbind);
  list.each(function(){ $(href(this)).hide(); });

  // Select default tab
  test=$();
     type(s.start) == "Number" && (s.start<0 || (test=list.eq(s.start)).length)
  || type(s.start) == "String" && (test=list.filter("[href=#"+s.start+"]")).length
  || (test=list.filter('.'+s.selected).removeClass(s.selected)).length
  || s.start===undefined && (test=list.eq(0)).length;
  if(test.length) test.trigger(s.event);

  return s; //return current settings (be creative)
};

// Find tabs
idTabs.find = function(e){
  var self=this, ret=false, s=e.data.s;
  // Find first tab within each tabset
  $("a[href="+href(this)+"]:first",s.area).each(function(){
    var t = $(this).data(s.data); //tab's settings
    if(t) ret=idTabs.showtab.call(t.tabarea==s.tabarea?self:this,t)||ret;
  });
  return ret;
};

// Show tab
idTabs.showtab = function(s){
  if(!s||$(this).is('.'+s.selected)) return s&&s.change; //return if already selected
  var id = href(this); //find id
  if(s.click && s.click.call(this,id,s)==false) return s.change; //call custom func
  return idTabs.show.call(this,id,s); //call default func
};

// Show item
idTabs.show = function(id,s){
  s.tabs.removeClass(s.selected); //clear tabs
  s.tab(id).addClass(s.selected); //select tab(s)
  s.items.hide(); //hide all items
  s.item(id).show(); //show item(s)
  return s.change; //option for changing url
};

// Unbind idTabs
idTabs.unbind = function(e){
  var s = e.data.s;
  $(this).removeData(s.data)
  .unbind(s.event+".idTabs");
  return false;
};

// Extend idTabs
idTabs.extend = function(){
  var args = arguments;
  return function(){
    [].push.apply(args,arguments);
    this.idTabs.apply(this,args);
  };
};

// Matching tabs
idTabs.tab = function(id){
  return $("a[href="+id+"]",this.tabarea);
};

// Matching items
idTabs.item = function(id){
  var item = $(id);
  return item.length?item:$('.'+id.substr(1));
};

// Defaults
idTabs.settings = {
  start:undefined,
  change:false,
  click:null,
  selected:".selected",
  event:"!click"
};

// Version
idTabs.version = "3.0";

// Auto-run
$(function(){ $(".idTabs").idTabs(); });

})(jQuery);
