| 8 | | |
|---|
| 9 | | (function($) { |
|---|
| 10 | | |
|---|
| 11 | | // if the UI scope is not availalable, add it |
|---|
| 12 | | $.ui = $.ui || {}; |
|---|
| 13 | | |
|---|
| 14 | | // tabs initialization |
|---|
| 15 | | $.fn.tabs = function(initial, options) { |
|---|
| 16 | | if (initial && initial.constructor == Object) { // shift arguments |
|---|
| 17 | | options = initial; |
|---|
| 18 | | initial = null; |
|---|
| 19 | | } |
|---|
| 20 | | options = options || {}; |
|---|
| 21 | | |
|---|
| 22 | | initial = initial && initial.constructor == Number && --initial || 0; |
|---|
| 23 | | |
|---|
| 24 | | return this.each(function() { |
|---|
| 25 | | new $.ui.tabs(this, $.extend(options, { initial: initial })); |
|---|
| 26 | | }); |
|---|
| 27 | | }; |
|---|
| 28 | | |
|---|
| 29 | | // other chainable tabs methods |
|---|
| 30 | | $.each(['Add', 'Remove', 'Enable', 'Disable', 'Click', 'Load', 'Href'], function(i, method) { |
|---|
| 31 | | $.fn['tabs' + method] = function() { |
|---|
| 32 | | var args = arguments; |
|---|
| 33 | | return this.each(function() { |
|---|
| 34 | | var instance = $.ui.tabs.getInstance(this); |
|---|
| 35 | | instance[method.toLowerCase()].apply(instance, args); |
|---|
| 36 | | }); |
|---|
| 37 | | }; |
|---|
| 38 | | }); |
|---|
| 39 | | $.fn.tabsSelected = function() { |
|---|
| 40 | | var selected = -1; |
|---|
| 41 | | if (this[0]) { |
|---|
| 42 | | var instance = $.ui.tabs.getInstance(this[0]), |
|---|
| 43 | | $lis = $('li', this); |
|---|
| 44 | | selected = $lis.index( $lis.filter('.' + instance.options.selectedClass)[0] ); |
|---|
| 45 | | } |
|---|
| 46 | | return selected >= 0 ? ++selected : -1; |
|---|
| 47 | | }; |
|---|
| 48 | | |
|---|
| 49 | | // tabs class |
|---|
| 50 | | $.ui.tabs = function(el, options) { |
|---|
| 51 | | |
|---|
| 52 | | this.source = el; |
|---|
| 53 | | |
|---|
| 54 | | this.options = $.extend({ |
|---|
| 55 | | |
|---|
| 56 | | // basic setup |
|---|
| 57 | | initial: 0, |
|---|
| 58 | | event: 'click', |
|---|
| 59 | | disabled: [], |
|---|
| 60 | | cookie: null, // pass options object as expected by cookie plugin: { expires: 7, path: '/', domain: 'jquery.com', secure: true } |
|---|
| 61 | | // TODO bookmarkable: $.ajaxHistory ? true : false, |
|---|
| 62 | | unselected: false, |
|---|
| 63 | | unselect: options.unselected ? true : false, |
|---|
| 64 | | |
|---|
| 65 | | // Ajax |
|---|
| 66 | | spinner: 'Loading…', |
|---|
| 67 | | cache: false, |
|---|
| 68 | | idPrefix: 'ui-tabs-', |
|---|
| 69 | | ajaxOptions: {}, |
|---|
| 70 | | |
|---|
| 71 | | // animations |
|---|
| 72 | | /*fxFade: null, |
|---|
| 73 | | fxSlide: null, |
|---|
| 74 | | fxShow: null, |
|---|
| 75 | | fxHide: null,*/ |
|---|
| 76 | | fxSpeed: 'normal', |
|---|
| 77 | | /*fxShowSpeed: null, |
|---|
| 78 | | fxHideSpeed: null,*/ |
|---|
| 79 | | |
|---|
| 80 | | // callbacks |
|---|
| 81 | | add: function() {}, |
|---|
| 82 | | remove: function() {}, |
|---|
| 83 | | enable: function() {}, |
|---|
| 84 | | disable: function() {}, |
|---|
| 85 | | click: function() {}, |
|---|
| 86 | | hide: function() {}, |
|---|
| 87 | | show: function() {}, |
|---|
| 88 | | load: function() {}, |
|---|
| 89 | | |
|---|
| 90 | | // templates |
|---|
| 91 | | tabTemplate: '<li><a href="#{href}"><span>#{text}</span></a></li>', |
|---|
| 92 | | panelTemplate: '<div></div>', |
|---|
| 93 | | |
|---|
| 94 | | // CSS classes |
|---|
| 95 | | navClass: 'ui-tabs-nav', |
|---|
| 96 | | selectedClass: 'ui-tabs-selected', |
|---|
| 97 | | unselectClass: 'ui-tabs-unselect', |
|---|
| 98 | | disabledClass: 'ui-tabs-disabled', |
|---|
| 99 | | panelClass: 'ui-tabs-panel', |
|---|
| 100 | | hideClass: 'ui-tabs-hide', |
|---|
| 101 | | loadingClass: 'ui-tabs-loading' |
|---|
| 102 | | |
|---|
| 103 | | }, options); |
|---|
| 104 | | |
|---|
| 105 | | this.options.event += '.ui-tabs'; // namespace event |
|---|
| 106 | | this.options.cookie = $.cookie && $.cookie.constructor == Function && this.options.cookie; |
|---|
| 107 | | |
|---|
| 108 | | // save instance for later |
|---|
| 109 | | $.data(el, $.ui.tabs.INSTANCE_KEY, this); |
|---|
| 110 | | |
|---|
| 111 | | // create tabs |
|---|
| 112 | | this.tabify(true); |
|---|
| 113 | | }; |
|---|
| 114 | | |
|---|
| 115 | | // static |
|---|
| 116 | | $.ui.tabs.INSTANCE_KEY = 'ui_tabs_instance'; |
|---|
| 117 | | $.ui.tabs.getInstance = function(el) { |
|---|
| 118 | | return $.data(el, $.ui.tabs.INSTANCE_KEY); |
|---|
| 119 | | }; |
|---|
| 120 | | |
|---|
| 121 | | // instance methods |
|---|
| 122 | | $.extend($.ui.tabs.prototype, { |
|---|
| 123 | | tabId: function(a) { |
|---|
| 124 | | return a.title ? a.title.replace(/\s/g, '_') |
|---|
| 125 | | : this.options.idPrefix + $.data(a); |
|---|
| 126 | | }, |
|---|
| 127 | | tabify: function(init) { |
|---|
| 128 | | |
|---|
| 129 | | this.$lis = $('li:has(a[href])', this.source); |
|---|
| 130 | | this.$tabs = this.$lis.map(function() { return $('a', this)[0] }); |
|---|
| 131 | | this.$panels = $([]); |
|---|
| 132 | | |
|---|
| 133 | | var self = this, o = this.options; |
|---|
| 134 | | |
|---|
| 135 | | this.$tabs.each(function(i, a) { |
|---|
| 136 | | // inline tab |
|---|
| 137 | | if (a.hash && a.hash.replace('#', '')) { // Safari 2 reports '#' for an empty hash |
|---|
| 138 | | self.$panels = self.$panels.add(a.hash); |
|---|
| 139 | | } |
|---|
| 140 | | // remote tab |
|---|
| 141 | | else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#" |
|---|
| 142 | | $.data(a, 'href', a.href); |
|---|
| 143 | | var id = self.tabId(a); |
|---|
| 144 | | a.href = '#' + id; |
|---|
| 145 | | self.$panels = self.$panels.add( |
|---|
| 146 | | $('#' + id)[0] || $(o.panelTemplate).attr('id', id).addClass(o.panelClass) |
|---|
| 147 | | .insertAfter( self.$panels[i - 1] || self.source ) |
|---|
| 148 | | ); |
|---|
| 149 | | } |
|---|
| 150 | | // invalid tab href |
|---|
| 151 | | else { |
|---|
| 152 | | o.disabled.push(i + 1); |
|---|
| 153 | | } |
|---|
| 154 | | }); |
|---|
| 155 | | |
|---|
| 156 | | if (init) { |
|---|
| 157 | | |
|---|
| 158 | | // attach necessary classes for styling if not present |
|---|
| 159 | | $(this.source).hasClass(o.navClass) || $(this.source).addClass(o.navClass); |
|---|
| 160 | | this.$panels.each(function() { |
|---|
| 161 | | var $this = $(this); |
|---|
| 162 | | $this.hasClass(o.panelClass) || $this.addClass(o.panelClass); |
|---|
| 163 | | }); |
|---|
| 164 | | |
|---|
| 165 | | // disabled tabs |
|---|
| 166 | | for (var i = 0, position; position = o.disabled[i]; i++) { |
|---|
| 167 | | this.disable(position); |
|---|
| 168 | | } |
|---|
| 169 | | |
|---|
| 170 | | // Try to retrieve initial tab: |
|---|
| 171 | | // 1. from fragment identifier in url if present |
|---|
| 172 | | // 2. from cookie |
|---|
| 173 | | // 3. from selected class attribute on <li> |
|---|
| 174 | | // 4. otherwise use given initial argument |
|---|
| 175 | | // 5. check if tab is disabled |
|---|
| 176 | | this.$tabs.each(function(i, a) { |
|---|
| 177 | | if (location.hash) { |
|---|
| 178 | | if (a.hash == location.hash) { |
|---|
| 179 | | o.initial = i; |
|---|
| 180 | | // prevent page scroll to fragment |
|---|
| 181 | | //if (($.browser.msie || $.browser.opera) && !o.remote) { |
|---|
| 182 | | if ($.browser.msie || $.browser.opera) { |
|---|
| 183 | | var $toShow = $(location.hash), toShowId = $toShow.attr('id'); |
|---|
| 184 | | $toShow.attr('id', ''); |
|---|
| 185 | | setTimeout(function() { |
|---|
| 186 | | $toShow.attr('id', toShowId); // restore id |
|---|
| 187 | | }, 500); |
|---|
| 188 | | } |
|---|
| 189 | | scrollTo(0, 0); |
|---|
| 190 | | return false; // break |
|---|
| 191 | | } |
|---|
| 192 | | } else if (o.cookie) { |
|---|
| 193 | | o.initial = parseInt($.cookie( $.ui.tabs.INSTANCE_KEY + $.data(self.source) )) || 0; |
|---|
| 194 | | return false; // break |
|---|
| 195 | | } else if ( self.$lis.eq(i).hasClass(o.selectedClass) ) { |
|---|
| 196 | | o.initial = i; |
|---|
| 197 | | return false; // break |
|---|
| 198 | | } |
|---|
| 199 | | }); |
|---|
| 200 | | var n = this.$lis.length; |
|---|
| 201 | | while (this.$lis.eq(o.initial).hasClass(o.disabledClass) && n) { |
|---|
| 202 | | o.initial = ++o.initial < this.$lis.length ? o.initial : 0; |
|---|
| 203 | | n--; |
|---|
| 204 | | } |
|---|
| 205 | | if (!n) { // all tabs disabled, set option unselected to true |
|---|
| 206 | | o.unselected = o.unselect = true; |
|---|
| 207 | | } |
|---|
| 208 | | |
|---|
| 209 | | // highlight selected tab |
|---|
| 210 | | this.$panels.addClass(o.hideClass); |
|---|
| 211 | | this.$lis.removeClass(o.selectedClass); |
|---|
| 212 | | if (!o.unselected) { |
|---|
| 213 | | this.$panels.eq(o.initial).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before |
|---|
| 214 | | this.$lis.eq(o.initial).addClass(o.selectedClass); |
|---|
| 215 | | } |
|---|
| 216 | | |
|---|
| 217 | | // load if remote tab |
|---|
| 218 | | var href = !o.unselected && $.data(this.$tabs[o.initial], 'href'); |
|---|
| 219 | | if (href) { |
|---|
| 220 | | this.load(o.initial + 1, href); |
|---|
| 221 | | } |
|---|
| 222 | | |
|---|
| 223 | | // disable click if event is configured to something else |
|---|
| 224 | | if (!/^click/.test(o.event)) { |
|---|
| 225 | | this.$tabs.bind('click', function(e) { e.preventDefault(); }); |
|---|
| 226 | | } |
|---|
| 227 | | |
|---|
| 228 | | } |
|---|
| 229 | | |
|---|
| 230 | | // setup animations |
|---|
| 231 | | var showAnim = {}, showSpeed = o.fxShowSpeed || o.fxSpeed, |
|---|
| 232 | | hideAnim = {}, hideSpeed = o.fxHideSpeed || o.fxSpeed; |
|---|
| 233 | | if (o.fxSlide || o.fxFade) { |
|---|
| 234 | | if (o.fxSlide) { |
|---|
| 235 | | showAnim['height'] = 'show'; |
|---|
| 236 | | hideAnim['height'] = 'hide'; |
|---|
| 237 | | } |
|---|
| 238 | | if (o.fxFade) { |
|---|
| 239 | | showAnim['opacity'] = 'show'; |
|---|
| 240 | | hideAnim['opacity'] = 'hide'; |
|---|
| 241 | | } |
|---|
| 242 | | } else { |
|---|
| 243 | | if (o.fxShow) { |
|---|
| 244 | | showAnim = o.fxShow; |
|---|
| 245 | | } else { // use some kind of animation to prevent browser scrolling to the tab |
|---|
| 246 | | showAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox |
|---|
| 247 | | showSpeed = 1; // as little as 1 is sufficient |
|---|
| 248 | | } |
|---|
| 249 | | if (o.fxHide) { |
|---|
| 250 | | hideAnim = o.fxHide; |
|---|
| 251 | | } else { // use some kind of animation to prevent browser scrolling to the tab |
|---|
| 252 | | hideAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox |
|---|
| 253 | | hideSpeed = 1; // as little as 1 is sufficient |
|---|
| 254 | | } |
|---|
| 255 | | } |
|---|
| 256 | | |
|---|
| 257 | | // reset some styles to maintain print style sheets etc. |
|---|
| 258 | | var resetCSS = { display: '', overflow: '', height: '' }; |
|---|
| 259 | | if (!$.browser.msie) { // not in IE to prevent ClearType font issue |
|---|
| 260 | | resetCSS['opacity'] = ''; |
|---|
| 261 | | } |
|---|
| 262 | | |
|---|
| 263 | | // Hide a tab, animation prevents browser scrolling to fragment, |
|---|
| 264 | | // $show is optional. |
|---|
| 265 | | function hideTab(clicked, $hide, $show) { |
|---|
| 266 | | $hide.animate(hideAnim, hideSpeed, function() { // |
|---|
| 267 | | $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. |
|---|
| 268 | | if ($.browser.msie && hideAnim['opacity']) { |
|---|
| 269 | | $hide[0].style.filter = ''; |
|---|
| 270 | | } |
|---|
| 271 | | o.hide(clicked, $hide[0], $show && $show[0] || null); |
|---|
| 272 | | if ($show) { |
|---|
| 273 | | showTab(clicked, $show, $hide); |
|---|
| 274 | | } |
|---|
| 275 | | }); |
|---|
| 276 | | } |
|---|
| 277 | | |
|---|
| 278 | | // Show a tab, animation prevents browser scrolling to fragment, |
|---|
| 279 | | // $hide is optional |
|---|
| 280 | | function showTab(clicked, $show, $hide) { |
|---|
| 281 | | if (!(o.fxSlide || o.fxFade || o.fxShow)) { |
|---|
| 282 | | $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels |
|---|
| 283 | | } |
|---|
| 284 | | $show.animate(showAnim, showSpeed, function() { |
|---|
| 285 | | $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. |
|---|
| 286 | | if ($.browser.msie && showAnim['opacity']) { |
|---|
| 287 | | $show[0].style.filter = ''; |
|---|
| 288 | | } |
|---|
| 289 | | o.show(clicked, $show[0], $hide && $hide[0] || null); |
|---|
| 290 | | }); |
|---|
| 291 | | } |
|---|
| 292 | | |
|---|
| 293 | | // switch a tab |
|---|
| 294 | | function switchTab(clicked, $li, $hide, $show) { |
|---|
| 295 | | /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click |
|---|
| 296 | | $.ajaxHistory.update(clicked.hash); |
|---|
| 297 | | }*/ |
|---|
| 298 | | $li.addClass(o.selectedClass) |
|---|
| 299 | | .siblings().removeClass(o.selectedClass); |
|---|
| 300 | | hideTab(clicked, $hide, $show); |
|---|
| 301 | | } |
|---|
| 302 | | |
|---|
| 303 | | // attach tab event handler, unbind to avoid duplicates from former tabifying... |
|---|
| 304 | | this.$tabs.unbind(o.event).bind(o.event, function() { |
|---|
| 305 | | |
|---|
| 306 | | //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click |
|---|
| 307 | | var $li = $(this).parents('li:eq(0)'), |
|---|
| 308 | | $hide = self.$panels.filter(':visible'), |
|---|
| 309 | | $show = $(this.hash); |
|---|
| 310 | | |
|---|
| 311 | | // If tab is already selected and not unselectable or tab disabled or click callback returns false stop here. |
|---|
| 312 | | // Check if click handler returns false last so that it is not executed for a disabled tab! |
|---|
| 313 | | if (($li.hasClass(o.selectedClass) && !o.unselect) || $li.hasClass(o.disabledClass) |
|---|
| 314 | | || o.click(this, $show[0], $hide[0]) === false) { |
|---|
| 315 | | this.blur(); |
|---|
| 316 | | return false; |
|---|
| 317 | | } |
|---|
| 318 | | |
|---|
| 319 | | if (o.cookie) { |
|---|
| 320 | | $.cookie($.ui.tabs.INSTANCE_KEY + $.data(self.source), self.$tabs.index(this), o.cookie); |
|---|
| 321 | | } |
|---|
| 322 | | |
|---|
| 323 | | // if tab may be closed |
|---|
| 324 | | if (o.unselect) { |
|---|
| 325 | | if ($li.hasClass(o.selectedClass)) { |
|---|
| 326 | | $li.removeClass(o.selectedClass); |
|---|
| 327 | | self.$panels.stop(); |
|---|
| 328 | | hideTab(this, $hide); |
|---|
| 329 | | this.blur(); |
|---|
| 330 | | return false; |
|---|
| 331 | | } else if (!$hide.length) { |
|---|
| 332 | | self.$panels.stop(); |
|---|
| 333 | | if ($.data(this, 'href')) { // remote tab |
|---|
| 334 | | var a = this; |
|---|
| 335 | | self.load(self.$tabs.index(this) + 1, $.data(this, 'href'), function() { |
|---|
| 336 | | $li.addClass(o.selectedClass).addClass(o.unselectClass); |
|---|
| 337 | | showTab(a, $show); |
|---|
| 338 | | }); |
|---|
| 339 | | } else { |
|---|
| 340 | | $li.addClass(o.selectedClass).addClass(o.unselectClass); |
|---|
| 341 | | showTab(this, $show); |
|---|
| 342 | | } |
|---|
| 343 | | this.blur(); |
|---|
| 344 | | return false; |
|---|
| 345 | | } |
|---|
| 346 | | } |
|---|
| 347 | | |
|---|
| 348 | | // stop possibly running animations |
|---|
| 349 | | self.$panels.stop(); |
|---|
| 350 | | |
|---|
| 351 | | // show new tab |
|---|
| 352 | | if ($show.length) { |
|---|
| 353 | | |
|---|
| 354 | | // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled |
|---|
| 355 | | /*if ($.browser.msie && o.bookmarkable) { |
|---|
| 356 | | var showId = this.hash.replace('#', ''); |
|---|
| 357 | | $show.attr('id', ''); |
|---|
| 358 | | setTimeout(function() { |
|---|
| 359 | | $show.attr('id', showId); // restore id |
|---|
| 360 | | }, 0); |
|---|
| 361 | | }*/ |
|---|
| 362 | | |
|---|
| 363 | | if ($.data(this, 'href')) { // remote tab |
|---|
| 364 | | var a = this; |
|---|
| 365 | | self.load(self.$tabs.index(this) + 1, $.data(this, 'href'), function() { |
|---|
| 366 | | switchTab(a, $li, $hide, $show); |
|---|
| 367 | | }); |
|---|
| 368 | | } else { |
|---|
| 369 | | switchTab(this, $li, $hide, $show); |
|---|
| 370 | | } |
|---|
| 371 | | |
|---|
| 372 | | // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash |
|---|
| 373 | | /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0; |
|---|
| 374 | | var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0; |
|---|
| 375 | | setTimeout(function() { |
|---|
| 376 | | scrollTo(scrollX, scrollY); |
|---|
| 377 | | }, 0);*/ |
|---|
| 378 | | |
|---|
| 379 | | } else { |
|---|
| 380 | | throw 'jQuery UI Tabs: Mismatching fragment identifier.'; |
|---|
| 381 | | } |
|---|
| 382 | | |
|---|
| 383 | | // Prevent IE from keeping other link focussed when using the back button |
|---|
| 384 | | // and remove dotted border from clicked link. This is controlled in modern |
|---|
| 385 | | // browsers via CSS, also blur removes focus from address bar in Firefox |
|---|
| 386 | | // which can become a usability and annoying problem with tabsRotate. |
|---|
| 387 | | if ($.browser.msie) { |
|---|
| 388 | | this.blur(); |
|---|
| 389 | | } |
|---|
| 390 | | |
|---|
| 391 | | //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE |
|---|
| 392 | | return false; |
|---|
| 393 | | |
|---|
| 394 | | }); |
|---|
| 395 | | |
|---|
| 396 | | }, |
|---|
| 397 | | add: function(url, text, position) { |
|---|
| 398 | | if (url && text) { |
|---|
| 399 | | position = position || this.$tabs.length; // append by default |
|---|
| 400 | | |
|---|
| 401 | | var o = this.options, |
|---|
| 402 | | $li = $(o.tabTemplate.replace(/#\{href\}/, url).replace(/#\{text\}/, text)); |
|---|
| 403 | | |
|---|
| 404 | | var id = url.indexOf('#') == 0 ? url.replace('#', '') : this.tabId( $('a:first-child', $li)[0] ); |
|---|
| 405 | | |
|---|
| 406 | | // try to find an existing element before creating a new one |
|---|
| 407 | | var $panel = $('#' + id); |
|---|
| 408 | | $panel = $panel.length && $panel |
|---|
| 409 | | || $(o.panelTemplate).attr('id', id).addClass(o.panelClass).addClass(o.hideClass); |
|---|
| 410 | | if (position >= this.$lis.length) { |
|---|
| 411 | | $li.appendTo(this.source); |
|---|
| 412 | | $panel.appendTo(this.source.parentNode); |
|---|
| 413 | | } else { |
|---|
| 414 | | $li.insertBefore(this.$lis[position - 1]); |
|---|
| 415 | | $panel.insertBefore(this.$panels[position - 1]); |
|---|
| 416 | | } |
|---|
| 417 | | |
|---|
| 418 | | this.tabify(); |
|---|
| 419 | | |
|---|
| 420 | | if (this.$tabs.length == 1) { |
|---|
| 421 | | $li.addClass(o.selectedClass); |
|---|
| 422 | | $panel.removeClass(o.hideClass); |
|---|
| 423 | | var href = $.data(this.$tabs[0], 'href'); |
|---|
| 424 | | if (href) { |
|---|
| 425 | | this.load(position + 1, href); |
|---|
| 426 | | } |
|---|
| 427 | | } |
|---|
| 428 | | o.add(this.$tabs[position], this.$panels[position]); // callback |
|---|
| 429 | | } else { |
|---|
| 430 | | throw 'jQuery UI Tabs: Not enough arguments to add tab.'; |
|---|
| 431 | | } |
|---|
| 432 | | }, |
|---|
| 433 | | remove: function(position) { |
|---|
| 434 | | if (position && position.constructor == Number) { |
|---|
| 435 | | var o = this.options, $li = this.$lis.eq(position - 1).remove(), |
|---|
| 436 | | $panel = this.$panels.eq(position - 1).remove(); |
|---|
| 437 | | |
|---|
| 438 | | // If selected tab was removed focus tab to the right or |
|---|
| 439 | | // tab to the left if last tab was removed. |
|---|
| 440 | | if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1) { |
|---|
| 441 | | this.click(position + (position < this.$tabs.length ? 1 : -1)); |
|---|
| 442 | | } |
|---|
| 443 | | this.tabify(); |
|---|
| 444 | | o.remove($li.end()[0], $panel[0]); // callback |
|---|
| 445 | | } |
|---|
| 446 | | }, |
|---|
| 447 | | enable: function(position) { |
|---|
| 448 | | var o = this.options, $li = this.$lis.eq(position - 1); |
|---|
| 449 | | $li.removeClass(o.disabledClass); |
|---|
| 450 | | if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2... |
|---|
| 451 | | $li.css('display', 'inline-block'); |
|---|
| 452 | | setTimeout(function() { |
|---|
| 453 | | $li.css('display', 'block') |
|---|
| 454 | | }, 0) |
|---|
| 455 | | } |
|---|
| 456 | | o.enable(this.$tabs[position - 1], this.$panels[position - 1]); // callback |
|---|
| 457 | | }, |
|---|
| 458 | | disable: function(position) { |
|---|
| 459 | | var o = this.options; |
|---|
| 460 | | this.$lis.eq(position - 1).addClass(o.disabledClass); |
|---|
| 461 | | o.disable(this.$tabs[position - 1], this.$panels[position - 1]); // callback |
|---|
| 462 | | }, |
|---|
| 463 | | click: function(position) { |
|---|
| 464 | | this.$tabs.eq(position - 1).trigger(this.options.event); |
|---|
| 465 | | }, |
|---|
| 466 | | load: function(position, url, callback) { |
|---|
| 467 | | var self = this, o = this.options, |
|---|
| 468 | | $a = this.$tabs.eq(position - 1), a = $a[0], $span = $('span', a); |
|---|
| 469 | | |
|---|
| 470 | | // shift arguments |
|---|
| 471 | | if (url && url.constructor == Function) { |
|---|
| 472 | | callback = url; |
|---|
| 473 | | url = null; |
|---|
| 474 | | } |
|---|
| 475 | | |
|---|
| 476 | | // set new URL or get existing |
|---|
| 477 | | if (url) { |
|---|
| 478 | | $.data(a, 'href', url); |
|---|
| 479 | | } else { |
|---|
| 480 | | url = $.data(a, 'href'); |
|---|
| 481 | | } |
|---|
| 482 | | |
|---|
| 483 | | // load |
|---|
| 484 | | if (o.spinner) { |
|---|
| 485 | | $.data(a, 'title', $span.html()); |
|---|
| 486 | | $span.html('<em>' + o.spinner + '</em>'); |
|---|
| 487 | | } |
|---|
| 488 | | var finish = function() { |
|---|
| 489 | | self.$tabs.filter('.' + o.loadingClass).each(function() { |
|---|
| 490 | | $(this).removeClass(o.loadingClass); |
|---|
| 491 | | if (o.spinner) { |
|---|
| 492 | | $('span', this).html( $.data(this, 'title') ); |
|---|
| 493 | | } |
|---|
| 494 | | }); |
|---|
| 495 | | self.xhr = null; |
|---|
| 496 | | }; |
|---|
| 497 | | var ajaxOptions = $.extend(o.ajaxOptions, { |
|---|
| 498 | | url: url, |
|---|
| 499 | | success: function(r) { |
|---|
| 500 | | $(a.hash).html(r); |
|---|
| 501 | | finish(); |
|---|
| 502 | | // This callback is required because the switch has to take |
|---|
| 503 | | // place after loading has completed. |
|---|
| 504 | | if (callback && callback.constructor == Function) { |
|---|
| 505 | | callback(); |
|---|
| 506 | | } |
|---|
| 507 | | if (o.cache) { |
|---|
| 508 | | $.removeData(a, 'href'); // if loaded once do not load them again |
|---|
| 509 | | } |
|---|
| 510 | | o.load(self.$tabs[position - 1], self.$panels[position - 1]); // callback |
|---|
| 511 | | } |
|---|
| 512 | | }); |
|---|
| 513 | | if (this.xhr) { |
|---|
| 514 | | // terminate pending requests from other tabs and restore title |
|---|
| 515 | | this.xhr.abort(); |
|---|
| 516 | | finish(); |
|---|
| 517 | | } |
|---|
| 518 | | $a.addClass(o.loadingClass); |
|---|
| 519 | | setTimeout(function() { // timeout is again required in IE, "wait" for id being restored |
|---|
| 520 | | self.xhr = $.ajax(ajaxOptions); |
|---|
| 521 | | }, 0); |
|---|
| 522 | | |
|---|
| 523 | | }, |
|---|
| 524 | | href: function(position, href) { |
|---|
| 525 | | $.data(this.$tabs.eq(position - 1)[0], 'href', href); |
|---|
| 526 | | } |
|---|
| 527 | | }); |
|---|
| | 15 | ;(function($) { |
|---|
| | 16 | |
|---|
| | 17 | $.widget("ui.tabs", { |
|---|
| | 18 | init: function() { |
|---|
| | 19 | this.options.event += '.tabs'; // namespace event |
|---|
| | 20 | |
|---|
| | 21 | // create tabs |
|---|
| | 22 | this.tabify(true); |
|---|
| | 23 | }, |
|---|
| | 24 | setData: function(key, value) { |
|---|
| | 25 | if ((/^selected/).test(key)) |
|---|
| | 26 | this.select(value); |
|---|
| | 27 | else { |
|---|
| | 28 | this.options[key] = value; |
|---|
| | 29 | this.tabify(); |
|---|
| | 30 | } |
|---|
| | 31 | }, |
|---|
| | 32 | length: function() { |
|---|
| | 33 | return this.$tabs.length; |
|---|
| | 34 | }, |
|---|
| | 35 | tabId: function(a) { |
|---|
| | 36 | return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') |
|---|
| | 37 | || this.options.idPrefix + $.data(a); |
|---|
| | 38 | }, |
|---|
| | 39 | ui: function(tab, panel) { |
|---|
| | 40 | return { |
|---|
| | 41 | instance: this, |
|---|
| | 42 | options: this.options, |
|---|
| | 43 | tab: tab, |
|---|
| | 44 | panel: panel |
|---|
| | 45 | }; |
|---|
| | 46 | }, |
|---|
| | 47 | tabify: function(init) { |
|---|
| | 48 | |
|---|
| | 49 | this.$lis = $('li:has(a[href])', this.element); |
|---|
| | 50 | this.$tabs = this.$lis.map(function() { return $('a', this)[0]; }); |
|---|
| | 51 | this.$panels = $([]); |
|---|
| | 52 | |
|---|
| | 53 | var self = this, o = this.options; |
|---|
| | 54 | |
|---|
| | 55 | this.$tabs.each(function(i, a) { |
|---|
| | 56 | // inline tab |
|---|
| | 57 | if (a.hash && a.hash.replace('#', '')) // Safari 2 reports '#' for an empty hash |
|---|
| | 58 | self.$panels = self.$panels.add(a.hash); |
|---|
| | 59 | // remote tab |
|---|
| | 60 | else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#" |
|---|
| | 61 | $.data(a, 'href.tabs', a.href); // required for restore on destroy |
|---|
| | 62 | $.data(a, 'load.tabs', a.href); // mutable |
|---|
| | 63 | var id = self.tabId(a); |
|---|
| | 64 | a.href = '#' + id; |
|---|
| | 65 | var $panel = $('#' + id); |
|---|
| | 66 | if (!$panel.length) { |
|---|
| | 67 | $panel = $(o.panelTemplate).attr('id', id).addClass(o.panelClass) |
|---|
| | 68 | .insertAfter( self.$panels[i - 1] || self.element ); |
|---|
| | 69 | $panel.data('destroy.tabs', true); |
|---|
| | 70 | } |
|---|
| | 71 | self.$panels = self.$panels.add( $panel ); |
|---|
| | 72 | } |
|---|
| | 73 | // invalid tab href |
|---|
| | 74 | else |
|---|
| | 75 | o.disabled.push(i + 1); |
|---|
| | 76 | }); |
|---|
| | 77 | |
|---|
| | 78 | if (init) { |
|---|
| | 79 | |
|---|
| | 80 | // attach necessary classes for styling if not present |
|---|
| | 81 | this.element.hasClass(o.navClass) || this.element.addClass(o.navClass); |
|---|
| | 82 | this.$panels.each(function() { |
|---|
| | 83 | var $this = $(this); |
|---|
| | 84 | $this.hasClass(o.panelClass) || $this.addClass(o.panelClass); |
|---|
| | 85 | }); |
|---|
| | 86 | |
|---|
| | 87 | // Selected tab |
|---|
| | 88 | // use "selected" option or try to retrieve: |
|---|
| | 89 | // 1. from fragment identifier in url |
|---|
| | 90 | // 2. from cookie |
|---|
| | 91 | // 3. from selected class attribute on <li> |
|---|
| | 92 | if (o.selected === undefined) { |
|---|
| | 93 | if (location.hash) { |
|---|
| | 94 | this.$tabs.each(function(i, a) { |
|---|
| | 95 | if (a.hash == location.hash) { |
|---|
| | 96 | o.selected = i; |
|---|
| | 97 | // prevent page scroll to fragment |
|---|
| | 98 | if ($.browser.msie || $.browser.opera) { // && !o.remote |
|---|
| | 99 | var $toShow = $(location.hash), toShowId = $toShow.attr('id'); |
|---|
| | 100 | $toShow.attr('id', ''); |
|---|
| | 101 | setTimeout(function() { |
|---|
| | 102 | $toShow.attr('id', toShowId); // restore id |
|---|
| | 103 | }, 500); |
|---|
| | 104 | } |
|---|
| | 105 | scrollTo(0, 0); |
|---|
| | 106 | return false; // break |
|---|
| | 107 | } |
|---|
| | 108 | }); |
|---|
| | 109 | } |
|---|
| | 110 | else if (o.cookie) { |
|---|
| | 111 | var index = parseInt($.cookie('ui-tabs' + $.data(self.element)),10); |
|---|
| | 112 | if (index && self.$tabs[index]) |
|---|
| | 113 | o.selected = index; |
|---|
| | 114 | } |
|---|
| | 115 | else if (self.$lis.filter('.' + o.selectedClass).length) |
|---|
| | 116 | o.selected = self.$lis.index( self.$lis.filter('.' + o.selectedClass)[0] ); |
|---|
| | 117 | } |
|---|
| | 118 | o.selected = o.selected === null || o.selected !== undefined ? o.selected : 0; // first tab selected by default |
|---|
| | 119 | |
|---|
| | 120 | // Take disabling tabs via class attribute from HTML |
|---|
| | 121 | // into account and update option properly. |
|---|
| | 122 | // A selected tab cannot become disabled. |
|---|
| | 123 | o.disabled = $.unique(o.disabled.concat( |
|---|
| | 124 | $.map(this.$lis.filter('.' + o.disabledClass), |
|---|
| | 125 | function(n, i) { return self.$lis.index(n); } ) |
|---|
| | 126 | )).sort(); |
|---|
| | 127 | if ($.inArray(o.selected, o.disabled) != -1) |
|---|
| | 128 | o.disabled.splice($.inArray(o.selected, o.disabled), 1); |
|---|
| | 129 | |
|---|
| | 130 | // highlight selected tab |
|---|
| | 131 | this.$panels.addClass(o.hideClass); |
|---|
| | 132 | this.$lis.removeClass(o.selectedClass); |
|---|
| | 133 | if (o.selected !== null) { |
|---|
| | 134 | this.$panels.eq(o.selected).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before |
|---|
| | 135 | this.$lis.eq(o.selected).addClass(o.selectedClass); |
|---|
| | 136 | |
|---|
| | 137 | // seems to be expected behavior that the show callback is fired |
|---|
| | 138 | var onShow = function() { |
|---|
| | 139 | $(self.element).triggerHandler('tabsshow', |
|---|
| | 140 | [self.ui(self.$tabs[o.selected], self.$panels[o.selected])], o.show); |
|---|
| | 141 | }; |
|---|
| | 142 | |
|---|
| | 143 | // load if remote tab |
|---|
| | 144 | if ($.data(this.$tabs[o.selected], 'load.tabs')) |
|---|
| | 145 | this.load(o.selected, onShow); |
|---|
| | 146 | // just trigger show event |
|---|
| | 147 | else |
|---|
| | 148 | onShow(); |
|---|
| | 149 | |
|---|
| | 150 | } |
|---|
| | 151 | |
|---|
| | 152 | // clean up to avoid memory leaks in certain versions of IE 6 |
|---|
| | 153 | $(window).bind('unload', function() { |
|---|
| | 154 | self.$tabs.unbind('.tabs'); |
|---|
| | 155 | self.$lis = self.$tabs = self.$panels = null; |
|---|
| | 156 | }); |
|---|
| | 157 | |
|---|
| | 158 | } |
|---|
| | 159 | |
|---|
| | 160 | // disable tabs |
|---|
| | 161 | for (var i = 0, li; li = this.$lis[i]; i++) |
|---|
| | 162 | $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass(o.selectedClass) ? 'addClass' : 'removeClass'](o.disabledClass); |
|---|
| | 163 | |
|---|
| | 164 | // reset cache if switching from cached to not cached |
|---|
| | 165 | if (o.cache === false) |
|---|
| | 166 | this.$tabs.removeData('cache.tabs'); |
|---|
| | 167 | |
|---|
| | 168 | // set up animations |
|---|
| | 169 | var hideFx, showFx, baseFx = { 'min-width': 0, duration: 1 }, baseDuration = 'normal'; |
|---|
| | 170 | if (o.fx && o.fx.constructor == Array) |
|---|
| | 171 | hideFx = o.fx[0] || baseFx, showFx = o.fx[1] || baseFx; |
|---|
| | 172 | else |
|---|
| | 173 | hideFx = showFx = o.fx || baseFx; |
|---|
| | 174 | |
|---|
| | 175 | // reset some styles to maintain print style sheets etc. |
|---|
| | 176 | var resetCSS = { display: '', overflow: '', height: '' }; |
|---|
| | 177 | if (!$.browser.msie) // not in IE to prevent ClearType font issue |
|---|
| | 178 | resetCSS.opacity = ''; |
|---|
| | 179 | |
|---|
| | 180 | // Hide a tab, animation prevents browser scrolling to fragment, |
|---|
| | 181 | // $show is optional. |
|---|
| | 182 | function hideTab(clicked, $hide, $show) { |
|---|
| | 183 | $hide.animate(hideFx, hideFx.duration || baseDuration, function() { // |
|---|
| | 184 | $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. |
|---|
| | 185 | if ($.browser.msie && hideFx.opacity) |
|---|
| | 186 | $hide[0].style.filter = ''; |
|---|
| | 187 | if ($show) |
|---|
| | 188 | showTab(clicked, $show, $hide); |
|---|
| | 189 | }); |
|---|
| | 190 | } |
|---|
| | 191 | |
|---|
| | 192 | // Show a tab, animation prevents browser scrolling to fragment, |
|---|
| | 193 | // $hide is optional. |
|---|
| | 194 | function showTab(clicked, $show, $hide) { |
|---|
| | 195 | if (showFx === baseFx) |
|---|
| | 196 | $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels |
|---|
| | 197 | $show.animate(showFx, showFx.duration || baseDuration, function() { |
|---|
| | 198 | $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. |
|---|
| | 199 | if ($.browser.msie && showFx.opacity) |
|---|
| | 200 | $show[0].style.filter = ''; |
|---|
| | 201 | |
|---|
| | 202 | // callback |
|---|
| | 203 | $(self.element).triggerHandler('tabsshow', |
|---|
| | 204 | [self.ui(clicked, $show[0])], o.show); |
|---|
| | 205 | |
|---|
| | 206 | }); |
|---|
| | 207 | } |
|---|
| | 208 | |
|---|
| | 209 | // switch a tab |
|---|
| | 210 | function switchTab(clicked, $li, $hide, $show) { |
|---|
| | 211 | /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click |
|---|
| | 212 | $.ajaxHistory.update(clicked.hash); |
|---|
| | 213 | }*/ |
|---|
| | 214 | $li.addClass(o.selectedClass) |
|---|
| | 215 | .siblings().removeClass(o.selectedClass); |
|---|
| | 216 | hideTab(clicked, $hide, $show); |
|---|
| | 217 | } |
|---|
| | 218 | |
|---|
| | 219 | // attach tab event handler, unbind to avoid duplicates from former tabifying... |
|---|
| | 220 | this.$tabs.unbind('.tabs').bind(o.event, function() { |
|---|
| | 221 | |
|---|
| | 222 | //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click |
|---|
| | 223 | var $li = $(this).parents('li:eq(0)'), |
|---|
| | 224 | $hide = self.$panels.filter(':visible'), |
|---|
| | 225 | $show = $(this.hash); |
|---|
| | 226 | |
|---|
| | 227 | // If tab is already selected and not unselectable or tab disabled or |
|---|
| | 228 | // or is already loading or click callback returns false stop here. |
|---|
| | 229 | // Check if click handler returns false last so that it is not executed |
|---|
| | 230 | // for a disabled or loading tab! |
|---|
| | 231 | if (($li.hasClass(o.selectedClass) && !o.unselect) |
|---|
| | 232 | || $li.hasClass(o.disabledClass) |
|---|
| | 233 | || $(this).hasClass(o.loadingClass) |
|---|
| | 234 | || $(self.element).triggerHandler('tabsselect', [self.ui(this, $show[0])], o.select) === false |
|---|
| | 235 | ) { |
|---|
| | 236 | this.blur(); |
|---|
| | 237 | return false; |
|---|
| | 238 | } |
|---|
| | 239 | |
|---|
| | 240 | self.options.selected = self.$tabs.index(this); |
|---|
| | 241 | |
|---|
| | 242 | // if tab may be closed |
|---|
| | 243 | if (o.unselect) { |
|---|
| | 244 | if ($li.hasClass(o.selectedClass)) { |
|---|
| | 245 | self.options.selected = null; |
|---|
| | 246 | $li.removeClass(o.selectedClass); |
|---|
| | 247 | self.$panels.stop(); |
|---|
| | 248 | hideTab(this, $hide); |
|---|
| | 249 | this.blur(); |
|---|
| | 250 | return false; |
|---|
| | 251 | } else if (!$hide.length) { |
|---|
| | 252 | self.$panels.stop(); |
|---|
| | 253 | var a = this; |
|---|
| | 254 | self.load(self.$tabs.index(this), function() { |
|---|
| | 255 | $li.addClass(o.selectedClass).addClass(o.unselectClass); |
|---|
| | 256 | showTab(a, $show); |
|---|
| | 257 | }); |
|---|
| | 258 | this.blur(); |
|---|
| | 259 | return false; |
|---|
| | 260 | } |
|---|
| | 261 | } |
|---|
| | 262 | |
|---|
| | 263 | if (o.cookie) |
|---|
| | 264 | $.cookie('ui-tabs' + $.data(self.element), self.options.selected, o.cookie); |
|---|
| | 265 | |
|---|
| | 266 | // stop possibly running animations |
|---|
| | 267 | self.$panels.stop(); |
|---|
| | 268 | |
|---|
| | 269 | // show new tab |
|---|
| | 270 | if ($show.length) { |
|---|
| | 271 | |
|---|
| | 272 | // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled |
|---|
| | 273 | /*if ($.browser.msie && o.bookmarkable) { |
|---|
| | 274 | var showId = this.hash.replace('#', ''); |
|---|
| | 275 | $show.attr('id', ''); |
|---|
| | 276 | setTimeout(function() { |
|---|
| | 277 | $show.attr('id', showId); // restore id |
|---|
| | 278 | }, 0); |
|---|
| | 279 | }*/ |
|---|
| | 280 | |
|---|
| | 281 | var a = this; |
|---|
| | 282 | self.load(self.$tabs.index(this), $hide.length ? |
|---|
| | 283 | function() { |
|---|
| | 284 | switchTab(a, $li, $hide, $show); |
|---|
| | 285 | } : |
|---|
| | 286 | function() { |
|---|
| | 287 | $li.addClass(o.selectedClass); |
|---|
| | 288 | showTab(a, $show); |
|---|
| | 289 | } |
|---|
| | 290 | ); |
|---|
| | 291 | |
|---|
| | 292 | // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash |
|---|
| | 293 | /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0; |
|---|
| | 294 | var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0; |
|---|
| | 295 | setTimeout(function() { |
|---|
| | 296 | scrollTo(scrollX, scrollY); |
|---|
| | 297 | }, 0);*/ |
|---|
| | 298 | |
|---|
| | 299 | } else |
|---|
| | 300 | throw 'jQuery UI Tabs: Mismatching fragment identifier.'; |
|---|
| | 301 | |
|---|
| | 302 | // Prevent IE from keeping other link focussed when using the back button |
|---|
| | 303 | // and remove dotted border from clicked link. This is controlled in modern |
|---|
| | 304 | // browsers via CSS, also blur removes focus from address bar in Firefox |
|---|
| | 305 | // which can become a usability and annoying problem with tabsRotate. |
|---|
| | 306 | if ($.browser.msie) |
|---|
| | 307 | this.blur(); |
|---|
| | 308 | |
|---|
| | 309 | //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE |
|---|
| | 310 | return false; |
|---|
| | 311 | |
|---|
| | 312 | }); |
|---|
| | 313 | |
|---|
| | 314 | // disable click if event is configured to something else |
|---|
| | 315 | if (!(/^click/).test(o.event)) |
|---|
| | 316 | this.$tabs.bind('click.tabs', function() { return false; }); |
|---|
| | 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\}/, url).replace(/#\{label\}/, 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.panelClass).addClass(o.hideClass); |
|---|
| | 334 | $panel.data('destroy.tabs', true); |
|---|
| | 335 | } |
|---|
| | 336 | if (index >= this.$lis.length) { |
|---|
| | 337 | $li.appendTo(this.element); |
|---|
| | 338 | $panel.appendTo(this.element[0].parentNode); |
|---|
| | 339 | } else { |
|---|
| | 340 | $li.insertBefore(this.$lis[index]); |
|---|
| | 341 | $panel.insertBefore(this.$panels[index]); |
|---|
| | 342 | } |
|---|
| | 343 | |
|---|
| | 344 | o.disabled = $.map(o.disabled, |
|---|
| | 345 | function(n, i) { return n >= index ? ++n : n }); |
|---|
| | 346 | |
|---|
| | 347 | this.tabify(); |
|---|
| | 348 | |
|---|
| | 349 | if (this.$tabs.length == 1) { |
|---|
| | 350 | $li.addClass(o.selectedClass); |
|---|
| | 351 | $panel.removeClass(o.hideClass); |
|---|
| | 352 | var href = $.data(this.$tabs[0], 'load.tabs'); |
|---|
| | 353 | if (href) |
|---|
| | 354 | this.load(index, href); |
|---|
| | 355 | } |
|---|
| | 356 | |
|---|
| | 357 | // callback |
|---|
| | 358 | this.element.triggerHandler('tabsadd', |
<