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