| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
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 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |