[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/views/js/ -> tabs.js (source)

   1  // $Id: tabs.js,v 1.4.2.1 2010/03/10 20:08:58 merlinofchaos Exp $
   2  
   3  /**
   4   * @file tabs.js
   5   * jQuery UI Tabs (Tabs 3)
   6   *
   7   * This is nothing more than the pure jquery UI tabs implementation.
   8   * It has been implemented under the Drupal.Views.Tabs namespace to
   9   * avoid conflicts with alternatve versions of jquery, jquery UI.
  10   */
  11  
  12  Drupal.Views = Drupal.Views || {};
  13  
  14  Drupal.Views.Tabs = function(el, options) {
  15  
  16    this.source = el;
  17  
  18    this.options = $.extend({
  19  
  20      // basic setup
  21      initial: 0,
  22      event: 'click',
  23      disabled: [],
  24      // TODO bookmarkable: $.ajaxHistory ? true : false,
  25      unselected: false,
  26      toggle: options.unselected ? true : false,
  27  
  28      // Ajax
  29      spinner: 'Loading…',
  30      cache: false,
  31      hashPrefix: 'tab-',
  32  
  33      // animations
  34      /*fxFade: null,
  35      fxSlide: null,
  36      fxShow: null,
  37      fxHide: null,*/
  38      fxSpeed: 'normal',
  39      /*fxShowSpeed: null,
  40      fxHideSpeed: null,*/
  41  
  42      // callbacks
  43      add: function() {},
  44      remove: function() {},
  45      enable: function() {},
  46      disable: function() {},
  47      click: function() {},
  48      hide: function() {},
  49      show: function() {},
  50      load: function() {},
  51  
  52      // CSS classes
  53      navClass: 'ui-tabs-nav',
  54      selectedClass: 'ui-tabs-selected',
  55      disabledClass: 'ui-tabs-disabled',
  56      containerClass: 'ui-tabs-container',
  57      hideClass: 'ui-tabs-hide',
  58      loadingClass: 'ui-tabs-loading'
  59  
  60    }, options);
  61  
  62    this.tabify(true);
  63  
  64    // save instance for later
  65    var uuid = 'instance-' + Drupal.Views.Tabs.prototype.count++;
  66    Drupal.Views.Tabs.instances[uuid] = this;
  67    this.source.data('UI_TABS_UUID', uuid);
  68  
  69  };
  70  
  71  // static
  72  Drupal.Views.Tabs.instances = {};
  73  
  74  $.extend(Drupal.Views.Tabs.prototype, {
  75    animating: false,
  76    count: 0,
  77    tabify: function(init) {
  78  
  79      this.$tabs = $('a:first-child', this.source);
  80      this.$containers = $([]);
  81  
  82      var self = this, o = this.options;
  83  
  84      this.$tabs.each(function(i, a) {
  85        // inline tab
  86        if (a.hash && a.hash.replace('#', '')) { // safari 2 reports '#' for an empty hash
  87          self.$containers = self.$containers.add(a.hash);
  88        }
  89        // remote tab
  90        else {
  91          var id = a.title && a.title.replace(/\s/g, '_') || o.hashPrefix + (self.count + 1) + '-' + (i + 1), url = a.href;
  92          a.href = '#' + id;
  93          a.url = url;
  94          self.$containers = self.$containers.add(
  95            $('#' + id)[0] || $('<div id="' + id + '" class="' + o.containerClass + '"></div>')
  96              .insertAfter( self.$containers[i - 1] || self.source )
  97          );
  98        }
  99      });
 100  
 101      if (init) {
 102  
 103        // Try to retrieve initial tab from fragment identifier in url if present,
 104        // otherwise try to find selected class attribute on <li>.
 105        this.$tabs.each(function(i, a) {
 106          if (location.hash) {
 107            if (a.hash == location.hash) {
 108              o.initial = i;
 109              // prevent page scroll to fragment
 110              //if (($.browser.msie || $.browser.opera) && !o.remote) {
 111              if ($.browser.msie || $.browser.opera) {
 112                var $toShow = $(location.hash), toShowId = $toShow.attr('id');
 113                $toShow.attr('id', '');
 114                setTimeout(function() {
 115                  $toShow.attr('id', toShowId); // restore id
 116                }, 500);
 117              }
 118              scrollTo(0, 0);
 119              return false; // break
 120            }
 121          } else if ( $(a).parents('li:eq(0)').is('li.' + o.selectedClass) ) {
 122            o.initial = i;
 123            return false; // break
 124          }
 125        });
 126  
 127        // attach necessary classes for styling if not present
 128        $(this.source).is('.' + o.navClass) || $(this.source).addClass(o.navClass);
 129        this.$containers.each(function() {
 130          var $this = $(this);
 131          $this.is('.' + o.containerClass) || $this.addClass(o.containerClass);
 132        });
 133  
 134        // highlight tab accordingly
 135        var $lis = $('li', this.source);
 136        this.$containers.addClass(o.hideClass);
 137        $lis.removeClass(o.selectedClass);
 138        if (!o.unselected) {
 139          this.$containers.slice(o.initial, o.initial + 1).show();
 140          $lis.slice(o.initial, o.initial + 1).addClass(o.selectedClass);
 141        }
 142  
 143        // trigger load of initial tab is remote tab
 144        if (this.$tabs[o.initial].url) {
 145          this.load(o.initial + 1, this.$tabs[o.initial].url);
 146          if (o.cache) {
 147            this.$tabs[o.initial].url = null; // if loaded once do not load them again
 148          }
 149        }
 150  
 151        // disabled tabs
 152        for (var i = 0, position; position = o.disabled[i]; i++) {
 153          this.disable(position);
 154        }
 155  
 156      }
 157  
 158      // setup animations
 159      var showAnim = {}, hideAnim = {}, showSpeed = o.fxShowSpeed || o.fxSpeed,
 160        hideSpeed = o.fxHideSpeed || o.fxSpeed;
 161      if (o.fxSlide || o.fxFade) {
 162        if (o.fxSlide) {
 163          showAnim['height'] = 'show';
 164          hideAnim['height'] = 'hide';
 165        }
 166        if (o.fxFade) {
 167          showAnim['opacity'] = 'show';
 168          hideAnim['opacity'] = 'hide';
 169        }
 170      } else {
 171        if (o.fxShow) {
 172          showAnim = o.fxShow;
 173        } else { // use some kind of animation to prevent browser scrolling to the tab
 174          showAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox
 175          showSpeed = 1; // as little as 1 is sufficient
 176        }
 177        if (o.fxHide) {
 178          hideAnim = o.fxHide;
 179        } else { // use some kind of animation to prevent browser scrolling to the tab
 180          hideAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox
 181          hideSpeed = 1; // as little as 1 is sufficient
 182        }
 183      }
 184  
 185      // callbacks
 186      var click = o.click, hide = o.hide, show = o.show;
 187  
 188      // reset some styles to maintain print style sheets etc.
 189      var resetCSS = { display: '', overflow: '', height: '' };
 190      if (!$.browser.msie) { // not in IE to prevent ClearType font issue
 191        resetCSS['opacity'] = '';
 192      }
 193  
 194      // hide a tab, animation prevents browser scrolling to fragment
 195      function hideTab(clicked, $hide, $show) {
 196        $hide.animate(hideAnim, hideSpeed, function() { //
 197          $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
 198          hide(clicked, $show, $hide[0]);
 199          if ($show) {
 200            showTab(clicked, $hide, $show);
 201          }
 202        });
 203      }
 204  
 205      // show a tab, animation prevents browser scrolling to fragment
 206      function showTab(clicked, $hide, $show) {
 207        // show next tab
 208        if (!(o.fxSlide || o.fxFade || o.fxShow)) {
 209          $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab containers
 210        }
 211        $show.animate(showAnim, showSpeed, function() {
 212          $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
 213          if ($.browser.msie) {
 214            $hide[0].style.filter = '';
 215            $show[0].style.filter = '';
 216          }
 217          show(clicked, $show[0], $hide[0]);
 218          self.animating = false;
 219        });
 220  
 221      }
 222  
 223      // switch a tab
 224      function switchTab(clicked, $hide, $show) {
 225        /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
 226          $.ajaxHistory.update(clicked.hash);
 227        }*/
 228        $(clicked).parents('li:eq(0)').addClass(o.selectedClass)
 229          .siblings().removeClass(o.selectedClass);
 230        hideTab(clicked, $hide, $show);
 231      }
 232  
 233      // tab click handler
 234      function tabClick(e) {
 235  
 236        //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
 237        var $li = $(this).parents('li:eq(0)'), $hide = self.$containers.filter(':visible'), $show = $(this.hash);
 238  
 239        // if tab may be closed
 240        if (o.toggle && !$li.is('.' + o.disabledClass) && !self.animating) {
 241          if ($li.is('.' + o.selectedClass)) {
 242            $li.removeClass(o.selectedClass);
 243            hideTab(this, $hide);
 244            this.blur();
 245            return false;
 246          } else if (!$hide.length) {
 247            $li.addClass(o.selectedClass);
 248            showTab(this, $hide, $show);
 249            this.blur();
 250            return false;
 251          }
 252        }
 253  
 254        // If tab is already selected or disabled, animation is still running or click callback
 255        // returns false stop here.
 256        // Check if click handler returns false last so that it is not executed for a disabled tab!
 257        if ($li.is('.' + o.selectedClass + ', .' + o.disabledClass)
 258          || self.animating || click(this, $show[0], $hide[0]) === false) {
 259          this.blur();
 260          return false;
 261        }
 262  
 263        self.animating = true;
 264  
 265        // show new tab
 266        if ($show.length) {
 267  
 268          // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
 269          /*if ($.browser.msie && o.bookmarkable) {
 270            var showId = this.hash.replace('#', '');
 271            $show.attr('id', '');
 272            setTimeout(function() {
 273              $show.attr('id', showId); // restore id
 274            }, 0);
 275          }*/
 276  
 277          if (this.url) { // remote tab
 278            var a = this;
 279            self.load(self.$tabs.index(this) + 1, this.url, function() {
 280              switchTab(a, $hide, $show);
 281            });
 282            if (o.cache) {
 283              this.url = null; // if loaded once do not load them again
 284            }
 285          } else {
 286            switchTab(this, $hide, $show);
 287          }
 288  
 289          // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
 290          /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
 291          var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
 292          setTimeout(function() {
 293            scrollTo(scrollX, scrollY);
 294          }, 0);*/
 295  
 296        } else {
 297          throw Drupal.t('jQuery UI Tabs: Mismatching fragment identifier.');
 298        }
 299  
 300        this.blur(); // prevent IE from keeping other link focussed when using the back button
 301  
 302        //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE
 303        return false;
 304  
 305      }
 306  
 307      // attach click event, avoid duplicates from former tabifying
 308      this.$tabs.unbind(o.event, tabClick).bind(o.event, tabClick);
 309  
 310    },
 311    add: function(url, text, position) {
 312      if (url && text) {
 313        var o = this.options;
 314        position = position || this.$tabs.length; // append by default
 315        if (position >= this.$tabs.length) {
 316          var method = 'insertAfter';
 317          position = this.$tabs.length;
 318        } else {
 319          var method = 'insertBefore';
 320        }
 321        if (url.indexOf('#') == 0) { // ajax container is created by tabify automatically
 322          var $container = $(url);
 323          // try to find an existing element before creating a new one
 324          ($container.length && $container || $('<div id="' + url.replace('#', '') + '" class="' + o.containerClass + ' ' + o.hideClass + '"></div>'))
 325            [method](this.$containers[position - 1]);
 326        }
 327        $('<li><a href="' + url + '"><span>' + text + '</span></a></li>')
 328          [method](this.$tabs.slice(position - 1, position).parents('li:eq(0)'));
 329        this.tabify();
 330        o.add(this.$tabs[position - 1], this.$containers[position - 1]); // callback
 331      } else {
 332        throw Drupal.t('jQuery UI Tabs: Not enough arguments to add tab.');
 333      }
 334    },
 335    remove: function(position) {
 336      if (position && position.constructor == Number) {
 337        this.$tabs.slice(position - 1, position).parents('li:eq(0)').remove();
 338        this.$containers.slice(position - 1, position).remove();
 339        this.tabify();
 340      }
 341      this.options.remove(); // callback
 342    },
 343    enable: function(position) {
 344      var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options;
 345      $li.removeClass(o.disabledClass);
 346      if ($.browser.safari) { // fix disappearing tab after enabling in Safari... TODO check Safari 3
 347        $li.animate({ opacity: 1 }, 1, function() {
 348          $li.css({ opacity: '' });
 349        });
 350      }
 351      o.enable(this.$tabs[position - 1], this.$containers[position - 1]); // callback
 352    },
 353    disable: function(position) {
 354      var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options;
 355      if ($.browser.safari) { // fix opacity of tab after disabling in Safari... TODO check Safari 3
 356        $li.animate({ opacity: 0 }, 1, function() {
 357            $li.css({ opacity: '' });
 358        });
 359      }
 360      $li.addClass(this.options.disabledClass);
 361      o.disable(this.$tabs[position - 1], this.$containers[position - 1]); // callback
 362    },
 363    click: function(position) {
 364      this.$tabs.slice(position - 1, position).trigger('click');
 365    },
 366    load: function(position, url, callback) {
 367      var self = this,
 368        o = this.options,
 369        $a = this.$tabs.slice(position - 1, position).addClass(o.loadingClass),
 370        $span = $('span', $a),
 371        text = $span.html();
 372  
 373      // shift arguments
 374      if (url && url.constructor == Function) {
 375        callback = url;
 376      }
 377  
 378      // set new URL
 379      if (url) {
 380        $a[0].url = url;
 381      }
 382  
 383      // load
 384      if (o.spinner) {
 385        $span.html('<em>' + o.spinner + '</em>');
 386      }
 387      setTimeout(function() { // timeout is again required in IE, "wait" for id being restored
 388        $($a[0].hash).load(url, function() {
 389          if (o.spinner) {
 390            $span.html(text);
 391          }
 392          $a.removeClass(o.loadingClass);
 393          // This callback is needed because the switch has to take place after loading
 394          // has completed.
 395          if (callback && callback.constructor == Function) {
 396            callback();
 397          }
 398          o.load(self.$tabs[position - 1], self.$containers[position - 1]); // callback
 399        });
 400      }, 0);
 401    }
 402  });


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