[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/jquery_ui/jquery.ui.old/ui/ -> ui.tabs.js (source)

   1  /*

   2   * jQuery UI Tabs 1.6

   3   *

   4   * Copyright (c) 2008 AUTHORS.txt (http://ui.jquery.com/about)

   5   * Dual licensed under the MIT (MIT-LICENSE.txt)

   6   * and GPL (GPL-LICENSE.txt) licenses.

   7   *

   8   * http://docs.jquery.com/UI/Tabs

   9   *

  10   * Depends:

  11   *    ui.core.js

  12   */
  13  (function($) {
  14  
  15  $.widget("ui.tabs", {
  16  
  17      _init: function() {
  18          // create tabs

  19          this._tabify(true);
  20      },
  21  
  22      destroy: function() {
  23          var o = this.options;
  24          this.element.unbind('.tabs')
  25              .removeClass(o.navClass).removeData('tabs');
  26          this.$tabs.each(function() {
  27              var href = $.data(this, 'href.tabs');
  28              if (href)
  29                  this.href = href;
  30              var $this = $(this).unbind('.tabs');
  31              $.each(['href', 'load', 'cache'], function(i, prefix) {
  32                  $this.removeData(prefix + '.tabs');
  33              });
  34          });
  35          this.$lis.add(this.$panels).each(function() {
  36              if ($.data(this, 'destroy.tabs'))
  37                  $(this).remove();
  38              else
  39                  $(this).removeClass([o.selectedClass, o.deselectableClass,
  40                      o.disabledClass, o.panelClass, o.hideClass].join(' '));
  41          });
  42          if (o.cookie)
  43              this._cookie(null, o.cookie);
  44      },
  45  
  46      _setData: function(key, value) {
  47          if ((/^selected/).test(key))
  48              this.select(value);
  49          else {
  50              this.options[key] = value;
  51              this._tabify();
  52          }
  53      },
  54  
  55      length: function() {
  56          return this.$tabs.length;
  57      },
  58  
  59      _tabId: function(a) {
  60          return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
  61              || this.options.idPrefix + $.data(a);
  62      },
  63  
  64      _sanitizeSelector: function(hash) {
  65          return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"

  66      },
  67  
  68      _cookie: function() {
  69          var cookie = this.cookie || (this.cookie = 'ui-tabs-' + $.data(this.element[0]));
  70          return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
  71      },
  72  
  73      _tabify: function(init) {
  74  
  75          this.$lis = $('li:has(a[href])', this.element);
  76          this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
  77          this.$panels = $([]);
  78  
  79          var self = this, o = this.options;
  80  
  81          this.$tabs.each(function(i, a) {
  82              // inline tab

  83              if (a.hash && a.hash.replace('#', '')) // Safari 2 reports '#' for an empty hash
  84                  self.$panels = self.$panels.add(self._sanitizeSelector(a.hash));
  85              // remote tab

  86              else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#"
  87                  $.data(a, 'href.tabs', a.href); // required for restore on destroy

  88                  $.data(a, 'load.tabs', a.href); // mutable

  89                  var id = self._tabId(a);
  90                  a.href = '#' + id;
  91                  var $panel = $('#' + id);
  92                  if (!$panel.length) {
  93                      $panel = $(o.panelTemplate).attr('id', id).addClass(o.panelClass)
  94                          .insertAfter(self.$panels[i - 1] || self.element);
  95                      $panel.data('destroy.tabs', true);
  96                  }
  97                  self.$panels = self.$panels.add($panel);
  98              }
  99              // invalid tab href

 100              else
 101                  o.disabled.push(i + 1);
 102          });
 103  
 104          // initialization from scratch

 105          if (init) {
 106  
 107              // attach necessary classes for styling if not present

 108              this.element.addClass(o.navClass);
 109              this.$panels.addClass(o.panelClass);
 110  
 111              // Selected tab

 112              // use "selected" option or try to retrieve:

 113              // 1. from fragment identifier in url

 114              // 2. from cookie

 115              // 3. from selected class attribute on <li>

 116              if (o.selected === undefined) {
 117                  if (location.hash) {
 118                      this.$tabs.each(function(i, a) {
 119                          if (a.hash == location.hash) {
 120                              o.selected = i;
 121                              return false; // break

 122                          }
 123                      });
 124                  }
 125                  else if (o.cookie) {
 126                      var index = parseInt(self._cookie(), 10);
 127                      if (index && self.$tabs[index]) o.selected = index;
 128                  }
 129                  else if (self.$lis.filter('.' + o.selectedClass).length)
 130                      o.selected = self.$lis.index( self.$lis.filter('.' + o.selectedClass)[0] );
 131              }
 132              o.selected = o.selected === null || o.selected !== undefined ? o.selected : 0; // first tab selected by default

 133  
 134              // Take disabling tabs via class attribute from HTML

 135              // into account and update option properly.

 136              // A selected tab cannot become disabled.

 137              o.disabled = $.unique(o.disabled.concat(
 138                  $.map(this.$lis.filter('.' + o.disabledClass),
 139                      function(n, i) { return self.$lis.index(n); } )
 140              )).sort();
 141              if ($.inArray(o.selected, o.disabled) != -1)
 142                  o.disabled.splice($.inArray(o.selected, o.disabled), 1);
 143  
 144              // highlight selected tab

 145              this.$panels.addClass(o.hideClass);
 146              this.$lis.removeClass(o.selectedClass);
 147              if (o.selected !== null) {
 148                  this.$panels.eq(o.selected).removeClass(o.hideClass);
 149                  var classes = [o.selectedClass];
 150                  if (o.deselectable) classes.push(o.deselectableClass);
 151                  this.$lis.eq(o.selected).addClass(classes.join(' '));
 152  
 153                  // seems to be expected behavior that the show callback is fired

 154                  var onShow = function() {
 155                      self._trigger('show', null,
 156                          self.ui(self.$tabs[o.selected], self.$panels[o.selected]));
 157                  };
 158  
 159                  // load if remote tab

 160                  if ($.data(this.$tabs[o.selected], 'load.tabs'))
 161                      this.load(o.selected, onShow);
 162                  // just trigger show event

 163                  else onShow();
 164              }
 165  
 166              // clean up to avoid memory leaks in certain versions of IE 6

 167              $(window).bind('unload', function() {
 168                  self.$tabs.unbind('.tabs');
 169                  self.$lis = self.$tabs = self.$panels = null;
 170              });
 171  
 172          }
 173          // update selected after add/remove

 174          else
 175              o.selected = this.$lis.index( this.$lis.filter('.' + o.selectedClass)[0] );
 176  
 177          // set or update cookie after init and add/remove respectively

 178          if (o.cookie) this._cookie(o.selected, o.cookie);
 179  
 180          // disable tabs

 181          for (var i = 0, li; li = this.$lis[i]; i++)
 182              $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass(o.selectedClass) ? 'addClass' : 'removeClass'](o.disabledClass);
 183  
 184          // reset cache if switching from cached to not cached

 185          if (o.cache === false) this.$tabs.removeData('cache.tabs');
 186  
 187          // set up animations

 188          var hideFx, showFx;
 189          if (o.fx) {
 190              if (o.fx.constructor == Array) {
 191                  hideFx = o.fx[0];
 192                  showFx = o.fx[1];
 193              }
 194              else hideFx = showFx = o.fx;
 195          }
 196  
 197          // Reset certain styles left over from animation

 198          // and prevent IE's ClearType bug...

 199  		function resetStyle($el, fx) {
 200              $el.css({ display: '' });
 201              if ($.browser.msie && fx.opacity) $el[0].style.removeAttribute('filter');
 202          }
 203  
 204          // Show a tab...

 205          var showTab = showFx ?
 206              function(clicked, $show) {
 207                  $show.animate(showFx, showFx.duration || 'normal', function() {
 208                      $show.removeClass(o.hideClass);
 209                      resetStyle($show, showFx);
 210                      self._trigger('show', null, self.ui(clicked, $show[0]));
 211                  });
 212              } :
 213              function(clicked, $show) {
 214                  $show.removeClass(o.hideClass);
 215                  self._trigger('show', null, self.ui(clicked, $show[0]));
 216              };
 217  
 218          // Hide a tab, $show is optional...

 219          var hideTab = hideFx ?
 220              function(clicked, $hide, $show) {
 221                  $hide.animate(hideFx, hideFx.duration || 'normal', function() {
 222                      $hide.addClass(o.hideClass);
 223                      resetStyle($hide, hideFx);
 224                      if ($show) showTab(clicked, $show, $hide);
 225                  });
 226              } :
 227              function(clicked, $hide, $show) {
 228                  $hide.addClass(o.hideClass);
 229                  if ($show) showTab(clicked, $show);
 230              };
 231  
 232          // Switch a tab...

 233  		function switchTab(clicked, $li, $hide, $show) {
 234              var classes = [o.selectedClass];
 235              if (o.deselectable) classes.push(o.deselectableClass);
 236              $li.addClass(classes.join(' ')).siblings().removeClass(classes.join(' '));
 237              hideTab(clicked, $hide, $show);
 238          }
 239  
 240          // attach tab event handler, unbind to avoid duplicates from former tabifying...

 241          this.$tabs.unbind('.tabs').bind(o.event + '.tabs', function() {
 242  
 243              //var trueClick = event.clientX; // add to history only if true click occured, not a triggered click

 244              var $li = $(this).parents('li:eq(0)'),
 245                  $hide = self.$panels.filter(':visible'),
 246                  $show = $(self._sanitizeSelector(this.hash));
 247  
 248              // If tab is already selected and not deselectable or tab disabled or

 249              // or is already loading or click callback returns false stop here.

 250              // Check if click handler returns false last so that it is not executed

 251              // for a disabled or loading tab!

 252              if (($li.hasClass(o.selectedClass) && !o.deselectable)
 253                  || $li.hasClass(o.disabledClass)
 254                  || $(this).hasClass(o.loadingClass)
 255                  || self._trigger('select', null, self.ui(this, $show[0])) === false
 256                  ) {
 257                  this.blur();
 258                  return false;
 259              }
 260  
 261              o.selected = self.$tabs.index(this);
 262  
 263              // if tab may be closed

 264              if (o.deselectable) {
 265                  if ($li.hasClass(o.selectedClass)) {
 266                      self.options.selected = null;
 267                      $li.removeClass([o.selectedClass, o.deselectableClass].join(' '));
 268                      self.$panels.stop();
 269                      hideTab(this, $hide);
 270                      this.blur();
 271                      return false;
 272                  } else if (!$hide.length) {
 273                      self.$panels.stop();
 274                      var a = this;
 275                      self.load(self.$tabs.index(this), function() {
 276                          $li.addClass([o.selectedClass, o.deselectableClass].join(' '));
 277                          showTab(a, $show);
 278                      });
 279                      this.blur();
 280                      return false;
 281                  }
 282              }
 283  
 284              if (o.cookie) self._cookie(o.selected, o.cookie);
 285  
 286              // stop possibly running animations

 287              self.$panels.stop();
 288  
 289              // show new tab

 290              if ($show.length) {
 291                  var a = this;
 292                  self.load(self.$tabs.index(this), $hide.length ?
 293                      function() {
 294                          switchTab(a, $li, $hide, $show);
 295                      } :
 296                      function() {
 297                          $li.addClass(o.selectedClass);
 298                          showTab(a, $show);
 299                      }
 300                  );
 301              } else
 302                  throw 'jQuery UI Tabs: Mismatching fragment identifier.';
 303  
 304              // Prevent IE from keeping other link focussed when using the back button

 305              // and remove dotted border from clicked link. This is controlled via CSS

 306              // in modern browsers; blur() removes focus from address bar in Firefox

 307              // which can become a usability and annoying problem with tabs('rotate').

 308              if ($.browser.msie) this.blur();
 309  
 310              return false;
 311  
 312          });
 313  
 314          // disable click if event is configured to something else

 315          if (o.event != 'click') this.$tabs.bind('click.tabs', function(){return false;});
 316  
 317      },
 318  
 319      add: function(url, label, index) {
 320          if (index == undefined)
 321              index = this.$tabs.length; // append by default

 322  
 323          var o = this.options;
 324          var $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label));
 325          $li.data('destroy.tabs', true);
 326  
 327          var id = url.indexOf('#') == 0 ? url.replace('#', '') : this._tabId( $('a:first-child', $li)[0] );
 328  
 329          // try to find an existing element before creating a new one

 330          var $panel = $('#' + id);
 331          if (!$panel.length) {
 332              $panel = $(o.panelTemplate).attr('id', id)
 333                  .addClass(o.hideClass)
 334                  .data('destroy.tabs', true);
 335          }
 336          $panel.addClass(o.panelClass);
 337          if (index >= this.$lis.length) {
 338              $li.appendTo(this.element);
 339              $panel.appendTo(this.element[0].parentNode);
 340          } else {
 341              $li.insertBefore(this.$lis[index]);
 342              $panel.insertBefore(this.$panels[index]);
 343          }
 344  
 345          o.disabled = $.map(o.disabled,
 346              function(n, i) { return n >= index ? ++n : n });
 347  
 348          this._tabify();
 349  
 350          if (this.$tabs.length == 1) {
 351              $li.addClass(o.selectedClass);
 352              $panel.removeClass(o.hideClass);
 353              var href = $.data(this.$tabs[0], 'load.tabs');
 354              if (href)
 355                  this.load(index, href);
 356          }
 357  
 358          // callback

 359          this._trigger('add', null, this.ui(this.$tabs[index], this.$panels[index]));
 360      },
 361  
 362      remove: function(index) {
 363          var o = this.options, $li = this.$lis.eq(index).remove(),
 364              $panel = this.$panels.eq(index).remove();
 365  
 366          // If selected tab was removed focus tab to the right or

 367          // in case the last tab was removed the tab to the left.

 368          if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1)
 369              this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));
 370  
 371          o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
 372              function(n, i) { return n >= index ? --n : n });
 373  
 374          this._tabify();
 375  
 376          // callback

 377          this._trigger('remove', null, this.ui($li.find('a')[0], $panel[0]));
 378      },
 379  
 380      enable: function(index) {
 381          var o = this.options;
 382          if ($.inArray(index, o.disabled) == -1)
 383              return;
 384  
 385          var $li = this.$lis.eq(index).removeClass(o.disabledClass);
 386          if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2...
 387              $li.css('display', 'inline-block');
 388              setTimeout(function() {
 389                  $li.css('display', 'block');
 390              }, 0);
 391          }
 392  
 393          o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
 394  
 395          // callback

 396          this._trigger('enable', null, this.ui(this.$tabs[index], this.$panels[index]));
 397      },
 398  
 399      disable: function(index) {
 400          var self = this, o = this.options;
 401          if (index != o.selected) { // cannot disable already selected tab
 402              this.$lis.eq(index).addClass(o.disabledClass);
 403  
 404              o.disabled.push(index);
 405              o.disabled.sort();
 406  
 407              // callback

 408              this._trigger('disable', null, this.ui(this.$tabs[index], this.$panels[index]));
 409          }
 410      },
 411  
 412      select: function(index) {
 413          // TODO make null as argument work

 414          if (typeof index == 'string')
 415              index = this.$tabs.index( this.$tabs.filter('[href$=' + index + ']')[0] );
 416          this.$tabs.eq(index).trigger(this.options.event + '.tabs');
 417      },
 418  
 419      load: function(index, callback) { // callback is for internal usage only
 420  
 421          var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
 422                  bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
 423  
 424          callback = callback || function() {};
 425  
 426          // no remote or from cache - just finish with callback

 427          if (!url || !bypassCache && $.data(a, 'cache.tabs')) {
 428              callback();
 429              return;
 430          }
 431  
 432          // load remote from here on

 433  
 434          var inner = function(parent) {
 435              var $parent = $(parent), $inner = $parent.find('*:last');
 436              return $inner.length && $inner.is(':not(img)') && $inner || $parent;
 437          };
 438          var cleanup = function() {
 439              self.$tabs.filter('.' + o.loadingClass).removeClass(o.loadingClass)
 440                      .each(function() {
 441                          if (o.spinner)
 442                              inner(this).parent().html(inner(this).data('label.tabs'));
 443                      });
 444              self.xhr = null;
 445          };
 446  
 447          if (o.spinner) {
 448              var label = inner(a).html();
 449              inner(a).wrapInner('<em></em>')
 450                  .find('em').data('label.tabs', label).html(o.spinner);
 451          }
 452  
 453          var ajaxOptions = $.extend({}, o.ajaxOptions, {
 454              url: url,
 455              success: function(r, s) {
 456                  $(self._sanitizeSelector(a.hash)).html(r);
 457                  cleanup();
 458  
 459                  if (o.cache)
 460                      $.data(a, 'cache.tabs', true); // if loaded once do not load them again

 461  
 462                  // callbacks

 463                  self._trigger('load', null, self.ui(self.$tabs[index], self.$panels[index]));
 464                  try {
 465                      o.ajaxOptions.success(r, s);
 466                  }
 467                  catch (event) {}
 468  
 469                  // This callback is required because the switch has to take

 470                  // place after loading has completed. Call last in order to

 471                  // fire load before show callback...

 472                  callback();
 473              }
 474          });
 475          if (this.xhr) {
 476              // terminate pending requests from other tabs and restore tab label

 477              this.xhr.abort();
 478              cleanup();
 479          }
 480          $a.addClass(o.loadingClass);
 481          self.xhr = $.ajax(ajaxOptions);
 482      },
 483  
 484      url: function(index, url) {
 485          this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
 486      },
 487  
 488      ui: function(tab, panel) {
 489          return {
 490              options: this.options,
 491              tab: tab,
 492              panel: panel,
 493              index: this.$tabs.index(tab)
 494          };
 495      }
 496  
 497  });
 498  
 499  $.extend($.ui.tabs, {
 500      version: '1.6',
 501      getter: 'length',
 502      defaults: {
 503          ajaxOptions: null,
 504          cache: false,
 505          cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
 506          deselectable: false,
 507          deselectableClass: 'ui-tabs-deselectable',
 508          disabled: [],
 509          disabledClass: 'ui-tabs-disabled',
 510          event: 'click',
 511          fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
 512          hideClass: 'ui-tabs-hide',
 513          idPrefix: 'ui-tabs-',
 514          loadingClass: 'ui-tabs-loading',
 515          navClass: 'ui-tabs-nav',
 516          panelClass: 'ui-tabs-panel',
 517          panelTemplate: '<div></div>',
 518          selectedClass: 'ui-tabs-selected',
 519          spinner: 'Loading&#8230;',
 520          tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
 521      }
 522  });
 523  
 524  /*

 525   * Tabs Extensions

 526   */
 527  
 528  /*

 529   * Rotate

 530   */
 531  $.extend($.ui.tabs.prototype, {
 532      rotation: null,
 533      rotate: function(ms, continuing) {
 534  
 535          continuing = continuing || false;
 536  
 537          var self = this, t = this.options.selected;
 538  
 539  		function start() {
 540              self.rotation = setInterval(function() {
 541                  t = ++t < self.$tabs.length ? t : 0;
 542                  self.select(t);
 543              }, ms);
 544          }
 545  
 546  		function stop(event) {
 547              if (!event || event.clientX) { // only in case of a true click
 548                  clearInterval(self.rotation);
 549              }
 550          }
 551  
 552          // start interval

 553          if (ms) {
 554              start();
 555              if (!continuing)
 556                  this.$tabs.bind(this.options.event + '.tabs', stop);
 557              else
 558                  this.$tabs.bind(this.options.event + '.tabs', function() {
 559                      stop();
 560                      t = self.options.selected;
 561                      start();
 562                  });
 563          }
 564          // stop interval

 565          else {
 566              stop();
 567              this.$tabs.unbind(this.options.event + '.tabs', stop);
 568          }
 569      }
 570  });
 571  
 572  })(jQuery);


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7