From 03ef2fb4525dc57cd397bfebf7b1f97e696ca3ff Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 12:04:14 -0400 Subject: Tabs: Split out event handler, showtab, hidetab, resetStyle to their own methods --- ui/jquery.ui.tabs.js | 227 ++++++++++++++++++++++++++------------------------- 1 file changed, 116 insertions(+), 111 deletions(-) diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index fcdf22c0e..f12383d08 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -258,147 +258,152 @@ $.widget( "ui.tabs", { this._hoverable( this.lis ); // set up animations - var hideFx, showFx; if ( o.fx ) { if ( $.isArray( o.fx ) ) { - hideFx = o.fx[ 0 ]; - showFx = o.fx[ 1 ]; + this.hideFx = o.fx[ 0 ]; + this.showFx = o.fx[ 1 ]; } else { - hideFx = showFx = o.fx; + this.hideFx = this.showFx = o.fx; } } - // Reset certain styles left over from animation - // and prevent IE's ClearType bug... - function resetStyle( $el, fx ) { - $el.css( "display", "" ); - if ( !$.support.opacity && fx.opacity ) { - $el[ 0 ].style.removeAttribute( "filter" ); - } + // attach tab event handler, unbind to avoid duplicates from former tabifying... + this.anchors.bind( o.event + ".tabs", $.proxy( this, "_eventHandler" )); + + // disable click in any case + this.anchors.bind( "click.tabs", function( event ){ + event.preventDefault(); + }); + }, + + // Reset certain styles left over from animation + // and prevent IE's ClearType bug... + _resetStyle: function ( $el, fx ) { + $el.css( "display", "" ); + if ( !$.support.opacity && fx.opacity ) { + $el[ 0 ].style.removeAttribute( "filter" ); } + }, - // Show a tab... - var showTab = showFx - ? function( clicked, $show, event ) { - $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); - $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way - .animate( showFx, showFx.duration || "normal", function() { - resetStyle( $show, showFx ); - self._trigger( "show", event, self._ui( clicked, $show[ 0 ] ) ); - }); - } - : function( clicked, $show, event ) { - $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); - $show.removeClass( "ui-tabs-hide" ); - self._trigger( "show", event, self._ui( clicked, $show[ 0 ] ) ); - }; - - // Hide a tab, $show is optional... - var hideTab = hideFx - ? function( clicked, $hide ) { - $hide.animate( hideFx, hideFx.duration || "normal", function() { - self.lis.removeClass( "ui-tabs-selected ui-state-active" ); - $hide.addClass( "ui-tabs-hide" ); - resetStyle( $hide, hideFx ); - self.element.dequeue( "tabs" ); + _showTab: function( clicked, show, event ) { + var self = this; + + $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); + + if ( this.showFx ) { + show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way + .animate( showFx, showFx.duration || "normal", function() { + self._resetStyle( show, showFx ); + self._trigger( "show", event, self._ui( clicked, show[ 0 ] ) ); }); - } - : function( clicked, $hide, $show ) { + } else { + show.removeClass( "ui-tabs-hide" ); + self._trigger( "show", event, self._ui( clicked, show[ 0 ] ) ); + } + }, + + _hideTab: function( clicked, $hide ) { + var self = this; + + if ( this.hideFx ) { + $hide.animate( hideFx, hideFx.duration || "normal", function() { self.lis.removeClass( "ui-tabs-selected ui-state-active" ); $hide.addClass( "ui-tabs-hide" ); + self._resetStyle( $hide, hideFx ); self.element.dequeue( "tabs" ); - }; + }); + } else { + self.lis.removeClass( "ui-tabs-selected ui-state-active" ); + $hide.addClass( "ui-tabs-hide" ); + self.element.dequeue( "tabs" ); + } + }, - // attach tab event handler, unbind to avoid duplicates from former tabifying... - this.anchors.bind( o.event + ".tabs", function( event ) { - event.preventDefault(); - var el = this, - $li = $(el).closest( "li" ), - $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), - $show = self.element.find( self._sanitizeSelector( el.hash ) ); - - // If tab is already selected and not collapsible or tab disabled or - // or is already loading or click callback returns false stop here. - // Check if click handler returns false last so that it is not executed - // for a disabled or loading tab! - if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || - $li.hasClass( "ui-state-disabled" ) || - $li.hasClass( "ui-state-processing" ) || - self.panels.filter( ":animated" ).length || - self._trigger( "select", event, self._ui( this, $show[ 0 ] ) ) === false ) { - this.blur(); - return; - } + _eventHandler: function( event ) { + event.preventDefault(); + var self = this, + o = this.options, + el = event.currentTarget, + $li = $(el).closest( "li" ), + $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), + $show = self.element.find( self._sanitizeSelector( el.hash ) ); + + // If tab is already selected and not collapsible or tab disabled or + // or is already loading or click callback returns false stop here. + // Check if click handler returns false last so that it is not executed + // for a disabled or loading tab! + if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || + $li.hasClass( "ui-state-disabled" ) || + $li.hasClass( "ui-state-processing" ) || + self.panels.filter( ":animated" ).length || + self._trigger( "select", event, self._ui( el, $show[ 0 ] ) ) === false ) { + el.blur(); + return; + } - o.selected = self.anchors.index( this ); + o.selected = self.anchors.index( el ); - self.abort(); + self.abort(); - // if tab may be closed - if ( o.collapsible ) { - if ( $li.hasClass( "ui-tabs-selected" ) ) { - o.selected = -1; + // if tab may be closed + if ( o.collapsible ) { + if ( $li.hasClass( "ui-tabs-selected" ) ) { + o.selected = -1; - if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); - } + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } - self.element.queue( "tabs", function() { - hideTab( el, $hide ); - }).dequeue( "tabs" ); + self.element.queue( "tabs", function() { + self._hideTab( el, $hide ); + }).dequeue( "tabs" ); - this.blur(); - return; - } else if ( !$hide.length ) { - if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); - } + el.blur(); + return; + } else if ( !$hide.length ) { + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } - self.element.queue( "tabs", function() { - showTab( el, $show, event ); - }); + self.element.queue( "tabs", function() { + self._showTab( el, $show, event ); + }); - // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 - self.load( self.anchors.index( this ) ); + // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 + self.load( self.anchors.index( el ) ); - this.blur(); - return; - } + el.blur(); + return; } + } - if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); - } + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } - // show new tab - if ( $show.length ) { - if ( $hide.length ) { - self.element.queue( "tabs", function() { - hideTab( el, $hide ); - }); - } + // show new tab + if ( $show.length ) { + if ( $hide.length ) { self.element.queue( "tabs", function() { - showTab( el, $show, event ); + self._hideTab( el, $hide ); }); - - self.load( self.anchors.index( this ) ); - } else { - throw "jQuery UI Tabs: Mismatching fragment identifier."; } + self.element.queue( "tabs", function() { + self._showTab( el, $show, event ); + }); - // Prevent IE from keeping other link focussed when using the back button - // and remove dotted border from clicked link. This is controlled via CSS - // in modern browsers; blur() removes focus from address bar in Firefox - // which can become a usability - if ( $.browser.msie ) { - this.blur(); - } - }); + self.load( self.anchors.index( el ) ); + } else { + throw "jQuery UI Tabs: Mismatching fragment identifier."; + } - // disable click in any case - this.anchors.bind( "click.tabs", function( event ){ - event.preventDefault(); - }); + // Prevent IE from keeping other link focussed when using the back button + // and remove dotted border from clicked link. This is controlled via CSS + // in modern browsers; blur() removes focus from address bar in Firefox + // which can become a usability + if ( $.browser.msie ) { + el.blur(); + } }, _getIndex: function( index ) { -- cgit v1.2.3 From aeaaf93ebb51ab6ff61a42d365edfd3872ae2ebd Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 15:00:39 -0400 Subject: Tabs: Add beforeload event; deprecate ajaxOptions and cache options. Fixes #7131 Tabs: Add beforeload event; deprecate ajaxOptions and cache options --- tests/unit/tabs/tabs.html | 3 + tests/unit/tabs/tabs_defaults.js | 3 +- tests/unit/tabs/tabs_defaults_deprecated.js | 28 ++++++ tests/unit/tabs/tabs_deprecated.html | 122 ++++++++++++++++++++++ tests/unit/tabs/tabs_deprecated.js | 13 +++ tests/unit/tabs/tabs_events.js | 19 ++++ tests/unit/tabs/tabs_options.js | 8 -- ui/jquery.ui.tabs.js | 150 +++++++++++++++++++--------- 8 files changed, 287 insertions(+), 59 deletions(-) create mode 100644 tests/unit/tabs/tabs_defaults_deprecated.js create mode 100644 tests/unit/tabs/tabs_deprecated.html create mode 100644 tests/unit/tabs/tabs_deprecated.js diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 74855ca9a..02fbfe3bb 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -7,6 +7,9 @@ + diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index ef93c69ee..4f663fbf2 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -4,8 +4,7 @@ var tabs_defaults = { add: null, - ajaxOptions: null, - cache: false, + beforeload: null, collapsible: false, cookie: null, disable: null, diff --git a/tests/unit/tabs/tabs_defaults_deprecated.js b/tests/unit/tabs/tabs_defaults_deprecated.js new file mode 100644 index 000000000..73e9ffede --- /dev/null +++ b/tests/unit/tabs/tabs_defaults_deprecated.js @@ -0,0 +1,28 @@ +/* + * tabs_defaults.js + */ + +var tabs_defaults = { + add: null, + ajaxOptions: null, + beforeload: null, + cache: false, + collapsible: false, + cookie: null, + disable: null, + disabled: false, + enable: null, + event: "click", + fx: null, + idPrefix: "ui-tabs-", + load: null, + panelTemplate: "
", + remove: null, + select: null, + show: null, + spinner: "Loading…", + tabTemplate: "
  • #{label}
  • " +}; + +// FAIL: falsy values break the cookie option +commonWidgetTests( "tabs", { defaults: tabs_defaults } ); diff --git a/tests/unit/tabs/tabs_deprecated.html b/tests/unit/tabs/tabs_deprecated.html new file mode 100644 index 000000000..3b927675c --- /dev/null +++ b/tests/unit/tabs/tabs_deprecated.html @@ -0,0 +1,122 @@ + + + + + jQuery UI Tabs Test Suite + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    jQuery UI Tabs Test Suite (deprecated)

    +

    +
    +

    +
      +
    + +
    + +
    +
      +
    • 1
    • +
    • 2
    • +
    • 3
    • +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
      +
    • 1
    • +
    +
    +
    +
    +
      +
    • 1
    • +
    +
      +
    1. 1
    2. +
    +
    +
    +
      +
    1. 1
    2. +
    +
      +
    • 1
    • +
    +
    +
    +
    +
      +
      +
      +
      +
        +
      • 1 +
          +
        • 3
        • +
        • 4
        • +
        +
      • +
      • 2
      • +
      +
      +
      +
      +
      +
        +
      • 1
      • +
      • 2
      • +
      +
      +
      +
      +
      + + diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js new file mode 100644 index 000000000..72034c083 --- /dev/null +++ b/tests/unit/tabs/tabs_deprecated.js @@ -0,0 +1,13 @@ +(function( $ ) { + +module("tabs (deprecated): cache and ajaxoptions"); + +test('ajaxOptions', function() { + ok(false, "missing test - untested code is broken code."); +}); + +test('cache', function() { + ok(false, "missing test - untested code is broken code."); +}); + +}( jQuery ) ); diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index 24fb62f9b..26ea76fb4 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -26,6 +26,25 @@ test('select', function() { equals( evenObj.originalEvent.type, "click", "select triggered by click" ); }); +test('beforeload', function() { + expect( 5 ); + + el = $('#tabs2'); + + el.tabs({ + selected: 2, + beforeload: function( event, ui ) { + ok( $.isFunction( ui.jqXHR.promise ), 'contain jqXHR object'); + equals( ui.settings.url, "data/test.html", 'contain ajax settings url'); + equals( ui.tab, el.find('a')[ 2 ], 'contain tab as DOM anchor element'); + equals( ui.panel, el.find('div')[ 2 ], 'contain panel as DOM div element'); + equals( ui.index, 2, 'contain index'); + event.preventDefault(); + } + }); + +}); + test('load', function() { ok(false, "missing test - untested code is broken code."); }); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index 1c621ac28..cf50bd970 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -5,14 +5,6 @@ module("tabs: options"); -test('ajaxOptions', function() { - ok(false, "missing test - untested code is broken code."); -}); - -test('cache', function() { - ok(false, "missing test - untested code is broken code."); -}); - test('collapsible', function() { expect(4); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index f12383d08..39f1b537b 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -27,8 +27,7 @@ function getNextListId() { $.widget( "ui.tabs", { options: { add: null, - ajaxOptions: null, - cache: false, + beforeload: null, cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } collapsible: false, disable: null, @@ -246,11 +245,6 @@ $.widget( "ui.tabs", { $( li ).toggleClass( "ui-state-disabled", $.inArray( i, o.disabled ) != -1 ); } - // reset cache if switching from cached to not cached - if ( o.cache === false ) { - this.anchors.removeData( "cache.tabs" ); - } - // remove all handlers before, tabify may run on existing tabs after add or option change this.lis.add( this.anchors ).unbind( ".tabs" ); @@ -431,7 +425,7 @@ $.widget( "ui.tabs", { this.href = href; } var $this = $( this ).unbind( ".tabs" ); - $.each( [ "href", "load", "cache" ], function( i, prefix ) { + $.each( [ "href", "load" ], function( i, prefix ) { $this.removeData( prefix + ".tabs" ); }); }); @@ -607,57 +601,45 @@ $.widget( "ui.tabs", { var self = this, o = this.options, a = this.anchors.eq( index )[ 0 ], - url = $.data( a, "load.tabs" ); + url = $.data( a, "load.tabs" ), + eventData = self._ui( self.anchors[ index ], self.panels[ index ] ); this.abort(); - // not remote or from cache - if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { + // not remote + if ( !url ) { this.element.dequeue( "tabs" ); return; } - // load remote from here on - this.lis.eq( index ).addClass( "ui-state-processing" ); - - if ( o.spinner ) { - var span = $( "span", a ); - span.data( "label.tabs", span.html() ).html( o.spinner ); - } - - this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, { + this.xhr = $.ajax({ url: url, - success: function( r, s ) { - self.element.find( self._sanitizeSelector( a.hash ) ).html( r ); - - // take care of tab labels - self._cleanup(); + beforeSend: function( jqXHR, settings ) { + return self._trigger( "beforeload", null, + $.extend( { jqXHR: jqXHR, settings: settings }, eventData ) ); + } + }); - if ( o.cache ) { - $.data( a, "cache.tabs", true ); - } + if ( this.xhr ) { + // load remote from here on + this.lis.eq( index ).addClass( "ui-state-processing" ); - self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); - try { - o.ajaxOptions.success( r, s ); - } - catch ( e ) {} - }, - error: function( xhr, s, e ) { - // take care of tab labels - self._cleanup(); - - self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); - try { - // Passing index avoid a race condition when this method is - // called after the user has selected another tab. - // Pass the anchor that initiated this request allows - // loadError to manipulate the tab content panel via $(a.hash) - o.ajaxOptions.error( xhr, s, index, a ); - } - catch ( e ) {} + if ( o.spinner ) { + var span = $( "span", a ); + span.data( "label.tabs", span.html() ).html( o.spinner ); } - } ) ); + + this.xhr + .success( function( response ) { + self.element.find( self._sanitizeSelector( a.hash ) ).html( response ); + }) + .complete( function( jqXHR, status ) { + // take care of tab labels + self._cleanup(); + + self._trigger( "load", null, eventData ); + }); + } // last, so that load event is fired before show... self.element.dequeue( "tabs" ); @@ -686,7 +668,7 @@ $.widget( "ui.tabs", { }, url: function( index, url ) { - this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); + this.anchors.eq( index ).data( "load.tabs", url ); return this; }, @@ -699,4 +681,74 @@ $.extend( $.ui.tabs, { version: "@VERSION" }); +// DEPRECATED +if ( $.uiBackCompat !== false ) { + + // ajaxOptions and cache options + (function( $, prototype ) { + $.extend( prototype.options, { + ajaxOptions: null, + cache: false + }); + + var _create = prototype._create, + _setOption = prototype._setOption, + _destroy = prototype._destroy, + oldurl = prototype._url; + + $.extend( prototype, { + _create: function() { + _create.call( this ); + + var self = this; + + this.element.bind( "tabsbeforeload", function( event, ui ) { + // tab is already cached + if ( $.data( ui.tab, "cache.tabs" ) ) { + event.preventDefault(); + return; + } + + $.extend( ui.settings, self.options.ajaxOptions, { + error: function( xhr, s, e ) { + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + self.options.ajaxOptions.error( xhr, s, ui.index, ui.tab ); + } + catch ( e ) {} + } + }); + + ui.jqXHR.success( function() { + if ( self.options.cache ) { + $.data( ui.tab, "cache.tabs", true ); + } + }); + }); + }, + + _setOption: function( key, value ) { + // reset cache if switching from cached to not cached + if ( key === "cache" && value === false ) { + this.anchors.removeData( "cache.tabs" ); + } + _setOption.apply( this, arguments ); + }, + + _destroy: function() { + this.anchors.removeData( "cache.tabs" ); + _destroy.call( this ); + }, + + url: function( index, url ){ + this.anchors.eq( index ).removeData( "cache.tabs" ); + oldurl.apply( this, arguments ); + } + }); + }( jQuery, jQuery.ui.tabs.prototype ) ); +} + })( jQuery ); -- cgit v1.2.3 From 3d612445264ba1a5f76917aee78217b92b04543b Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 15:23:08 -0400 Subject: Tabs: Deprecate abort method. Fixes #7133 Tabs: Deprecate abort method --- ui/jquery.ui.tabs.js | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 39f1b537b..617e84848 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -337,7 +337,9 @@ $.widget( "ui.tabs", { o.selected = self.anchors.index( el ); - self.abort(); + if ( self.xhr ) { + self.xhr.abort(); + } // if tab may be closed if ( o.collapsible ) { @@ -413,7 +415,9 @@ $.widget( "ui.tabs", { _destroy: function() { var o = this.options; - this.abort(); + if ( this.xhr ) { + this.xhr.abort(); + } this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); @@ -604,7 +608,9 @@ $.widget( "ui.tabs", { url = $.data( a, "load.tabs" ), eventData = self._ui( self.anchors[ index ], self.panels[ index ] ); - this.abort(); + if ( this.xhr ) { + this.xhr.abort(); + } // not remote if ( !url ) { @@ -634,6 +640,17 @@ $.widget( "ui.tabs", { self.element.find( self._sanitizeSelector( a.hash ) ).html( response ); }) .complete( function( jqXHR, status ) { + if ( status === "abort" ) { + // stop possibly running animations + self.element.queue( [] ); + self.panels.stop( false, true ); + + // "tabs" queue must not contain more than two elements, + // which are the callbacks for the latest clicked tab... + self.element.queue( "tabs", self.element.queue( "tabs" ).splice( -2, 2 ) ); + + delete this.xhr; + } // take care of tab labels self._cleanup(); @@ -647,26 +664,6 @@ $.widget( "ui.tabs", { return this; }, - abort: function() { - // stop possibly running animations - this.element.queue( [] ); - this.panels.stop( false, true ); - - // "tabs" queue must not contain more than two elements, - // which are the callbacks for the latest clicked tab... - this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); - - // terminate pending requests from other tabs - if ( this.xhr ) { - this.xhr.abort(); - delete this.xhr; - } - - // take care of tab labels - this._cleanup(); - return this; - }, - url: function( index, url ) { this.anchors.eq( index ).data( "load.tabs", url ); return this; @@ -749,6 +746,15 @@ if ( $.uiBackCompat !== false ) { } }); }( jQuery, jQuery.ui.tabs.prototype ) ); + + // abort method + (function( $, prototype ) { + prototype.abort = function() { + if ( this.xhr ) { + this.xhr.abort(); + } + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); } })( jQuery ); -- cgit v1.2.3 From e7971c9077ce1f8e4f9afb123118349544bf1acb Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 15:48:53 -0400 Subject: Tabs: Deprecate spinner option. Fixes #7134 Tabs: Deprecate spinner option --- tests/unit/tabs/tabs_core.js | 30 ---------------------- tests/unit/tabs/tabs_defaults.js | 1 - tests/unit/tabs/tabs_deprecated.js | 31 +++++++++++++++++++++++ tests/unit/tabs/tabs_options.js | 4 --- ui/jquery.ui.tabs.js | 51 ++++++++++++++++++++++++-------------- 5 files changed, 63 insertions(+), 54 deletions(-) diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 652788bba..7d9074819 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -25,34 +25,4 @@ test('navigation markup', function() { el.tabs('destroy'); }); -test('ajax', function() { - expect(4); - stop(); - - el = $('#tabs2'); - - el.tabs({ - selected: 2, - load: function() { - // spinner: default spinner - setTimeout(function() { - equals($('li:eq(2) > a > span', el).length, 1, "should restore tab markup after spinner is removed"); - equals($('li:eq(2) > a > span', el).html(), '3', "should restore tab label after spinner is removed"); - el.tabs('destroy'); - el.tabs({ - selected: 2, - spinner: '', - load: function() { - // spinner: image - equals($('li:eq(2) > a > span', el).length, 1, "should restore tab markup after spinner is removed"); - equals($('li:eq(2) > a > span', el).html(), '3', "should restore tab label after spinner is removed"); - start(); - } - }); - }, 1); - } - }); - -}); - })(jQuery); diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index 4f663fbf2..397d81ce6 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -18,7 +18,6 @@ var tabs_defaults = { remove: null, select: null, show: null, - spinner: "Loading…", tabTemplate: "
    • #{label}
    • " }; diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 72034c083..cec689808 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -10,4 +10,35 @@ test('cache', function() { ok(false, "missing test - untested code is broken code."); }); +module("tabs (deprecated): spinner"); + +test('spinner', function() { + expect(4); + stop(); + + el = $('#tabs2'); + + el.tabs({ + selected: 2, + load: function() { + // spinner: default spinner + setTimeout(function() { + equals($('li:eq(2) > a > span', el).length, 1, "should restore tab markup after spinner is removed"); + equals($('li:eq(2) > a > span', el).html(), '3', "should restore tab label after spinner is removed"); + el.tabs('destroy'); + el.tabs({ + selected: 2, + spinner: '', + load: function() { + // spinner: image + equals($('li:eq(2) > a > span', el).length, 1, "should restore tab markup after spinner is removed"); + equals($('li:eq(2) > a > span', el).html(), '3', "should restore tab label after spinner is removed"); + start(); + } + }); + }, 1); + } + }); +}); + }( jQuery ) ); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index cf50bd970..45fba8f32 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -117,10 +117,6 @@ test('selected', function() { equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if value is same as selected'); }); -test('spinner', function() { - ok(false, "missing test - untested code is broken code."); -}); - test('tabTemplate', function() { ok(false, "missing test - untested code is broken code."); }); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 617e84848..f54b166c9 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -41,7 +41,6 @@ $.widget( "ui.tabs", { remove: null, select: null, show: null, - spinner: "Loading…", tabTemplate: "
    • #{label}
    • " }, @@ -85,17 +84,6 @@ $.widget( "ui.tabs", { }; }, - _cleanup: function() { - // restore all former loading tabs labels - this.lis.filter( ".ui-state-processing" ) - .removeClass( "ui-state-processing" ) - .find( "span:data(label.tabs)" ) - .each(function() { - var el = $( this ); - el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" ); - }); - }, - _tabify: function( init ) { var self = this, o = this.options, @@ -630,11 +618,6 @@ $.widget( "ui.tabs", { // load remote from here on this.lis.eq( index ).addClass( "ui-state-processing" ); - if ( o.spinner ) { - var span = $( "span", a ); - span.data( "label.tabs", span.html() ).html( o.spinner ); - } - this.xhr .success( function( response ) { self.element.find( self._sanitizeSelector( a.hash ) ).html( response ); @@ -651,8 +634,8 @@ $.widget( "ui.tabs", { delete this.xhr; } - // take care of tab labels - self._cleanup(); + + self.lis.eq( index ).removeClass( "ui-state-processing" ); self._trigger( "load", null, eventData ); }); @@ -755,6 +738,36 @@ if ( $.uiBackCompat !== false ) { } }; }( jQuery, jQuery.ui.tabs.prototype ) ); + + // spinner + (function( $, prototype ) { + $.extend( prototype.options, { + spinner: "Loading…" + }); + + var _create = prototype._create; + prototype._create = function() { + _create.call( this ); + var self = this; + + this.element.bind( "tabsbeforeload", function( event, ui ) { + if ( self.options.spinner ) { + var span = $( "span", ui.tab ); + if ( span.length ) { + span.data( "label.tabs", span.html() ).html( self.options.spinner ); + } + } + ui.jqXHR.complete( function() { + if ( self.options.spinner ) { + var span = $( "span", ui.tab ); + if ( span.length ) { + span.html( span.data( "label.tabs" ) ).removeData( "label.tabs" ); + } + } + }); + }); + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); } })( jQuery ); -- cgit v1.2.3 From e5f081bc1c16c051665eafc22c9a7af3fba456c8 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 16:12:05 -0400 Subject: Tabs: Deprecate enable and disable events. Fixes #7142 Tabs: Deprecate enable and disable events --- tests/unit/tabs/tabs_defaults.js | 2 -- tests/unit/tabs/tabs_deprecated.js | 35 +++++++++++++++++++++++++++++ tests/unit/tabs/tabs_events.js | 33 ---------------------------- ui/jquery.ui.tabs.js | 45 ++++++++++++++++++++++++++++++++++---- 4 files changed, 76 insertions(+), 39 deletions(-) diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index 397d81ce6..5a6bc065e 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -7,9 +7,7 @@ var tabs_defaults = { beforeload: null, collapsible: false, cookie: null, - disable: null, disabled: false, - enable: null, event: "click", fx: null, idPrefix: "ui-tabs-", diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index cec689808..ee2dbdc74 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -41,4 +41,39 @@ test('spinner', function() { }); }); +module("tabs (deprecated): enable/disable events"); + +test('enable', function() { + expect(4); + + var uiObj; + el = $('#tabs1').tabs({ + disabled: [ 0, 1 ], + enable: function (event, ui) { + uiObj = ui; + } + }); + el.tabs('enable', 1); + ok(uiObj !== undefined, 'trigger callback'); + equals(uiObj.tab, $('a', el)[1], 'contain tab as DOM anchor element'); + equals(uiObj.panel, $('div', el)[1], 'contain panel as DOM div element'); + equals(uiObj.index, 1, 'contain index'); +}); + +test('disable', function() { + expect(4); + + var uiObj; + el = $('#tabs1').tabs({ + disable: function (event, ui) { + uiObj = ui; + } + }); + el.tabs('disable', 1); + ok(uiObj !== undefined, 'trigger callback'); + equals(uiObj.tab, $('a', el)[1], 'contain tab as DOM anchor element'); + equals(uiObj.panel, $('div', el)[1], 'contain panel as DOM div element'); + equals(uiObj.index, 1, 'contain index'); +}); + }( jQuery ) ); diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index 26ea76fb4..56c1360ee 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -88,37 +88,4 @@ test('remove', function() { ok(false, "missing test - untested code is broken code."); }); -test('enable', function() { - expect(4); - - var uiObj; - el = $('#tabs1').tabs({ - disabled: [ 0, 1 ], - enable: function (event, ui) { - uiObj = ui; - } - }); - el.tabs('enable', 1); - ok(uiObj !== undefined, 'trigger callback'); - equals(uiObj.tab, $('a', el)[1], 'contain tab as DOM anchor element'); - equals(uiObj.panel, $('div', el)[1], 'contain panel as DOM div element'); - equals(uiObj.index, 1, 'contain index'); -}); - -test('disable', function() { - expect(4); - - var uiObj; - el = $('#tabs1').tabs({ - disable: function (event, ui) { - uiObj = ui; - } - }); - el.tabs('disable', 1); - ok(uiObj !== undefined, 'trigger callback'); - equals(uiObj.tab, $('a', el)[1], 'contain tab as DOM anchor element'); - equals(uiObj.panel, $('div', el)[1], 'contain panel as DOM div element'); - equals(uiObj.index, 1, 'contain index'); -}); - })(jQuery); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index f54b166c9..b7a270fb6 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -30,9 +30,7 @@ $.widget( "ui.tabs", { beforeload: null, cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } collapsible: false, - disable: null, disabled: false, - enable: null, event: "click", fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } idPrefix: "ui-tabs-", @@ -545,7 +543,6 @@ $.widget( "ui.tabs", { o.disabled = false; } - this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); return this; }, @@ -569,7 +566,6 @@ $.widget( "ui.tabs", { o.disabled = true; } - this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); } return this; @@ -768,6 +764,47 @@ if ( $.uiBackCompat !== false ) { }); }; }( jQuery, jQuery.ui.tabs.prototype ) ); + + // enable/disable events + (function( $, prototype ) { + $.extend( prototype.options, { + enable: null, + disable: null + }); + + var enable = prototype.enable, + disable = prototype.disable; + + prototype.enable = function( index ) { + var o = this.options, + trigger; + + if ( index && o.disabled || ($.isArray( o.disabled ) && $.inArray( index, o.disabled ) !== -1 ) ) { + trigger = true; + } + + enable.apply( this, arguments ); + + if ( trigger ) { + this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + }; + + prototype.disable = function( index ) { + var o = this.options, + trigger; + + if ( index && !o.disabled || ($.isArray( o.disabled ) && $.inArray( index, o.disabled ) == -1 ) ) { + trigger = true; + } + + disable.apply( this, arguments ); + + if ( trigger ) { + this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); } })( jQuery ); -- cgit v1.2.3 From e378876918361182e6cb6321159393828848b2c9 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 16:29:57 -0400 Subject: Tabs: Deprecate add and remove methods Fixes #7141 Tabs: Deprecate add and remove methods --- tests/unit/tabs/tabs_defaults.js | 2 - tests/unit/tabs/tabs_deprecated.js | 74 ++++++++++++++++- tests/unit/tabs/tabs_events.js | 19 ----- tests/unit/tabs/tabs_methods.js | 36 -------- tests/unit/tabs/tabs_tickets.js | 11 --- ui/jquery.ui.tabs.js | 163 +++++++++++++++++++------------------ 6 files changed, 155 insertions(+), 150 deletions(-) diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index 5a6bc065e..f7307b458 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -3,7 +3,6 @@ */ var tabs_defaults = { - add: null, beforeload: null, collapsible: false, cookie: null, @@ -13,7 +12,6 @@ var tabs_defaults = { idPrefix: "ui-tabs-", load: null, panelTemplate: "
      ", - remove: null, select: null, show: null, tabTemplate: "
    • #{label}
    • " diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index ee2dbdc74..b385a33c2 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -1,6 +1,6 @@ (function( $ ) { -module("tabs (deprecated): cache and ajaxoptions"); +module("tabs (deprecated): options"); test('ajaxOptions', function() { ok(false, "missing test - untested code is broken code."); @@ -10,8 +10,6 @@ test('cache', function() { ok(false, "missing test - untested code is broken code."); }); -module("tabs (deprecated): spinner"); - test('spinner', function() { expect(4); stop(); @@ -41,7 +39,7 @@ test('spinner', function() { }); }); -module("tabs (deprecated): enable/disable events"); +module("tabs (deprecated): events"); test('enable', function() { expect(4); @@ -76,4 +74,72 @@ test('disable', function() { equals(uiObj.index, 1, 'contain index'); }); +test('add', function() { + + // TODO move to methods, not at all event related... + + var el = $('
        ').tabs(); + equals(el.tabs('option', 'selected'), -1, 'Initially empty, no selected tab'); + + el.tabs('add', '#test1', 'Test 1'); + equals(el.tabs('option', 'selected'), 0, 'First tab added should be auto selected'); + + el.tabs('add', '#test2', 'Test 2'); + equals(el.tabs('option', 'selected'), 0, 'Second tab added should not be auto selected'); + +}); + +test('remove', function() { + ok(false, "missing test - untested code is broken code."); +}); + +module("tabs (deprecated): methods"); + +test('add', function() { + expect(4); + + el = $('#tabs1').tabs(); + el.tabs('add', '#new', 'New'); + + var added = $('li:last', el).simulate('mouseover'); + ok(added.is('.ui-state-hover'), 'should add mouseover handler to added tab'); + added.simulate('mouseout'); + var other = $('li:first', el).simulate('mouseover'); + ok(other.is('.ui-state-hover'), 'should not remove mouseover handler from existing tab'); + other.simulate('mouseout'); + + equals($('a', added).attr('href'), '#new', 'should not expand href to full url of current page'); + + ok(false, "missing test - untested code is broken code."); +}); + +test('remove', function() { + expect(4); + + el = $('#tabs1').tabs(); + + el.tabs('remove', 0); + equals(el.tabs('length'), 2, 'remove tab'); + equals($('li a[href$="fragment-1"]', el).length, 0, 'remove associated list item'); + equals($('#fragment-1').length, 0, 'remove associated panel'); + + // TODO delete tab -> focus tab to right + // TODO delete last tab -> focus tab to left + + el.tabs('select', 1); + el.tabs('remove', 1); + equals(el.tabs('option', 'selected'), 0, 'update selected property'); +}); + +test('#5069 - ui.tabs.add creates two tab panels when using a full URL', function() { + // http://dev.jqueryui.com/ticket/5069 + expect(2); + + el = $('#tabs2').tabs(); + equals(el.children('div').length, el.find('> ul > li').length, 'After creation, number of panels should be equal to number of tabs'); + el.tabs('add', '/ajax_html_echo', 'Test'); + equals(el.children('div').length, el.find('> ul > li').length, 'After add, number of panels should be equal to number of tabs'); + +}); + }( jQuery ) ); diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index 56c1360ee..b3f8653a2 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -69,23 +69,4 @@ test('show', function() { }); -test('add', function() { - - // TODO move to methods, not at all event related... - - var el = $('
          ').tabs(); - equals(el.tabs('option', 'selected'), -1, 'Initially empty, no selected tab'); - - el.tabs('add', '#test1', 'Test 1'); - equals(el.tabs('option', 'selected'), 0, 'First tab added should be auto selected'); - - el.tabs('add', '#test2', 'Test 2'); - equals(el.tabs('option', 'selected'), 0, 'Second tab added should not be auto selected'); - -}); - -test('remove', function() { - ok(false, "missing test - untested code is broken code."); -}); - })(jQuery); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index 0209af697..ac0747df9 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -130,42 +130,6 @@ test('disable', function() { same(el.tabs('option', 'disabled'), true, 'set to true'); }); -test('add', function() { - expect(4); - - el = $('#tabs1').tabs(); - el.tabs('add', '#new', 'New'); - - var added = $('li:last', el).simulate('mouseover'); - ok(added.is('.ui-state-hover'), 'should add mouseover handler to added tab'); - added.simulate('mouseout'); - var other = $('li:first', el).simulate('mouseover'); - ok(other.is('.ui-state-hover'), 'should not remove mouseover handler from existing tab'); - other.simulate('mouseout'); - - equals($('a', added).attr('href'), '#new', 'should not expand href to full url of current page'); - - ok(false, "missing test - untested code is broken code."); -}); - -test('remove', function() { - expect(4); - - el = $('#tabs1').tabs(); - - el.tabs('remove', 0); - equals(el.tabs('length'), 2, 'remove tab'); - equals($('li a[href$="fragment-1"]', el).length, 0, 'remove associated list item'); - equals($('#fragment-1').length, 0, 'remove associated panel'); - - // TODO delete tab -> focus tab to right - // TODO delete last tab -> focus tab to left - - el.tabs('select', 1); - el.tabs('remove', 1); - equals(el.tabs('option', 'selected'), 0, 'update selected property'); -}); - test('select', function() { expect(6); diff --git a/tests/unit/tabs/tabs_tickets.js b/tests/unit/tabs/tabs_tickets.js index 4a09d59e4..5da799730 100644 --- a/tests/unit/tabs/tabs_tickets.js +++ b/tests/unit/tabs/tabs_tickets.js @@ -59,17 +59,6 @@ test('#4033 - IE expands hash to full url and misinterprets tab as ajax', functi }); -test('#5069 - ui.tabs.add creates two tab panels when using a full URL', function() { - // http://dev.jqueryui.com/ticket/5069 - expect(2); - - el = $('#tabs2').tabs(); - equals(el.children('div').length, el.find('> ul > li').length, 'After creation, number of panels should be equal to number of tabs'); - el.tabs('add', '/ajax_html_echo', 'Test'); - equals(el.children('div').length, el.find('> ul > li').length, 'After add, number of panels should be equal to number of tabs'); - -}); - test('#5893 - Sublist in the tab list are considered as tab', function() { // http://dev.jqueryui.com/ticket/5893 expect(1); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index b7a270fb6..03f085ea2 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -26,7 +26,6 @@ function getNextListId() { $.widget( "ui.tabs", { options: { - add: null, beforeload: null, cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } collapsible: false, @@ -36,7 +35,6 @@ $.widget( "ui.tabs", { idPrefix: "ui-tabs-", load: null, panelTemplate: "
          ", - remove: null, select: null, show: null, tabTemplate: "
        • #{label}
        • " @@ -445,82 +443,6 @@ $.widget( "ui.tabs", { return this; }, - add: function( url, label, index ) { - if ( index === undefined ) { - index = this.anchors.length; - } - - var self = this, - o = this.options, - $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), - id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); - - $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); - - // try to find an existing element before creating a new one - var $panel = self.element.find( "#" + id ); - if ( !$panel.length ) { - $panel = $( o.panelTemplate ) - .attr( "id", id ) - .data( "destroy.tabs", true ); - } - $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); - - if ( index >= this.lis.length ) { - $li.appendTo( this.list ); - $panel.appendTo( this.list[ 0 ].parentNode ); - } else { - $li.insertBefore( this.lis[ index ] ); - $panel.insertBefore( this.panels[ index ] ); - } - - o.disabled = $.map( o.disabled, function( n, i ) { - return n >= index ? ++n : n; - }); - - this._tabify(); - - if ( this.anchors.length == 1 ) { - o.selected = 0; - $li.addClass( "ui-tabs-selected ui-state-active" ); - $panel.removeClass( "ui-tabs-hide" ); - this.element.queue( "tabs", function() { - self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); - }); - - this.load( 0 ); - } - - this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); - return this; - }, - - remove: function( index ) { - index = this._getIndex( index ); - var o = this.options, - $li = this.lis.eq( index ).remove(), - $panel = this.panels.eq( index ).remove(); - - // If selected tab was removed focus tab to the right or - // in case the last tab was removed the tab to the left. - if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { - this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); - } - - o.disabled = $.map( - $.grep( o.disabled, function(n, i) { - return n != index; - }), - function( n, i ) { - return n >= index ? --n : n; - }); - - this._tabify(); - - this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); - return this; - }, - enable: function( index ) { if ( index === undefined ) { for ( var i = 0, len = this.lis.length; i < len; i++ ) { @@ -805,6 +727,91 @@ if ( $.uiBackCompat !== false ) { } }; }( jQuery, jQuery.ui.tabs.prototype ) ); + + // add/remove methods and events + (function( $, prototype ) { + $.extend( prototype.options, { + add: null, + remove: null + }); + + prototype.add = function( url, label, index ) { + if ( index === undefined ) { + index = this.anchors.length; + } + + var self = this, + o = this.options, + $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), + id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); + + $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); + + // try to find an existing element before creating a new one + var $panel = self.element.find( "#" + id ); + if ( !$panel.length ) { + $panel = $( o.panelTemplate ) + .attr( "id", id ) + .data( "destroy.tabs", true ); + } + $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); + + if ( index >= this.lis.length ) { + $li.appendTo( this.list ); + $panel.appendTo( this.list[ 0 ].parentNode ); + } else { + $li.insertBefore( this.lis[ index ] ); + $panel.insertBefore( this.panels[ index ] ); + } + + o.disabled = $.map( o.disabled, function( n, i ) { + return n >= index ? ++n : n; + }); + + this._tabify(); + + if ( this.anchors.length == 1 ) { + o.selected = 0; + $li.addClass( "ui-tabs-selected ui-state-active" ); + $panel.removeClass( "ui-tabs-hide" ); + this.element.queue( "tabs", function() { + self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); + }); + + this.load( 0 ); + } + + this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }; + + prototype.remove = function( index ) { + index = this._getIndex( index ); + var o = this.options, + $li = this.lis.eq( index ).remove(), + $panel = this.panels.eq( index ).remove(); + + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { + this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); + } + + o.disabled = $.map( + $.grep( o.disabled, function(n, i) { + return n != index; + }), + function( n, i ) { + return n >= index ? --n : n; + }); + + this._tabify(); + + this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); + return this; + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); + } })( jQuery ); -- cgit v1.2.3 From 03eb54b37902db771accd3a53bad1b927c058bc7 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 16:49:14 -0400 Subject: Tabs: Deprecate the length method. Fixes #7143 Tabs: Deprecate the length method --- tests/unit/tabs/tabs_deprecated.js | 6 ++++++ tests/unit/tabs/tabs_methods.js | 7 ------- tests/unit/tabs/tabs_tickets.js | 4 ++-- ui/jquery.ui.tabs.js | 10 ++++++---- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index b385a33c2..880ea075e 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -139,7 +139,13 @@ test('#5069 - ui.tabs.add creates two tab panels when using a full URL', functio equals(el.children('div').length, el.find('> ul > li').length, 'After creation, number of panels should be equal to number of tabs'); el.tabs('add', '/ajax_html_echo', 'Test'); equals(el.children('div').length, el.find('> ul > li').length, 'After add, number of panels should be equal to number of tabs'); +}); + +test('length', function() { + expect(1); + el = $('#tabs1').tabs(); + equals(el.tabs('length'), $('ul a', el).length, ' should return length'); }); }( jQuery ) ); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index ac0747df9..44c91d492 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -167,11 +167,4 @@ test('url', function() { ok(false, "missing test - untested code is broken code."); }); -test('length', function() { - expect(1); - - el = $('#tabs1').tabs(); - equals(el.tabs('length'), $('ul a', el).length, ' should return length'); -}); - })(jQuery); diff --git a/tests/unit/tabs/tabs_tickets.js b/tests/unit/tabs/tabs_tickets.js index 5da799730..c301e9eb0 100644 --- a/tests/unit/tabs/tabs_tickets.js +++ b/tests/unit/tabs/tabs_tickets.js @@ -54,7 +54,7 @@ test('#4033 - IE expands hash to full url and misinterprets tab as ajax', functi el = $('') .appendTo('#main').tabs(); - + equals($('a', el).data('load.tabs'), undefined, 'should not create ajax tab'); }); @@ -64,7 +64,7 @@ test('#5893 - Sublist in the tab list are considered as tab', function() { expect(1); el = $('#tabs6').tabs(); - equals(el.tabs( "length" ), 2, 'should contain 2 tab'); + equals(el.data("tabs").anchors.length, 2, 'should contain 2 tab'); }); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 03f085ea2..c026858ee 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -568,10 +568,6 @@ $.widget( "ui.tabs", { url: function( index, url ) { this.anchors.eq( index ).data( "load.tabs", url ); return this; - }, - - length: function() { - return this.anchors.length; } }); @@ -812,6 +808,12 @@ if ( $.uiBackCompat !== false ) { }; }( jQuery, jQuery.ui.tabs.prototype ) ); + // length method + (function( $, prototype ) { + prototype.length = function() { + return this.anchors.length; + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); } })( jQuery ); -- cgit v1.2.3 From 8b89febbbb4d2f13c67bc8ec406b68ff29da3a5a Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 20:37:26 -0400 Subject: Tabs: split up _tabify, create refresh method. Fixes #7140 Tabs: Add refresh method --- tests/unit/tabs/tabs_methods.js | 28 ++++ ui/jquery.ui.tabs.js | 278 +++++++++++++++++++++++----------------- 2 files changed, 187 insertions(+), 119 deletions(-) diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index 44c91d492..50b8abd27 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -159,6 +159,34 @@ test('select', function() { equals(el.tabs('option', 'selected'), 1, 'should select tab by id'); }); +test('refresh', function() { + expect(5); + + var el = $('
            ').tabs(), + ul = el.find('ul'); + + equals(el.tabs('option', 'selected'), -1, 'Initially empty, no selected tab'); + + ul.append('
          • Test 1
          • '); + el.tabs('refresh'); + equals( el.find('.ui-tabs-panel').length, 1, 'Panel created after refresh'); + + ul.find('li').remove(); + el.tabs('refresh'); + equals( el.find('.ui-tabs-panel').length, 0, 'Panel removed after refresh'); + + ul.append('
          • Test 1
          • '); + $('
            Test Panel 1
            ').insertAfter( ul ); + el.tabs('refresh'); + el.tabs('select', 0); + equals( el.tabs('option', 'selected'), 0, 'First tab added should be auto selected'); + + ul.append('
          • Test 2
          • '); + $('
            Test Panel 2
            ').insertAfter( ul ); + el.tabs('refresh'); + equals( el.tabs('option', 'selected'), 0, 'Second tab added should not be auto selected'); +}); + test('load', function() { ok(false, "missing test - untested code is broken code."); }); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index c026858ee..14c74b110 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -41,7 +41,81 @@ $.widget( "ui.tabs", { }, _create: function() { - this._tabify( true ); + var self = this, + o = this.options; + + this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); + + this._processTabs(); + + // Selected tab + // use "selected" option or try to retrieve: + // 1. from fragment identifier in url + // 2. from cookie + // 3. from selected class attribute on
          • + if ( o.selected === undefined ) { + if ( location.hash ) { + this.anchors.each(function( i, a ) { + if ( a.hash == location.hash ) { + o.selected = i; + return false; + } + }); + } + if ( typeof o.selected !== "number" && o.cookie ) { + o.selected = parseInt( self._cookie(), 10 ); + } + if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { + o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + } + o.selected = o.selected || ( this.lis.length ? 0 : -1 ); + } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release + o.selected = -1; + } + + // sanity check - default to first tab... + o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) + ? o.selected + : 0; + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + if ( $.isArray( o.disabled ) ) { + o.disabled = $.unique( o.disabled.concat( + $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { + return self.lis.index( n ); + }) + ) ).sort(); + } + + this._setupFx( o.fx ); + + this._refresh(); + + // highlight selected tab + this.panels.addClass( "ui-tabs-hide" ); + this.lis.removeClass( "ui-tabs-selected ui-state-active" ); + // check for length avoids error when initializing empty list + if ( o.selected >= 0 && this.anchors.length ) { + var temp = self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) + .removeClass( "ui-tabs-hide" ); + + this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); + + // seems to be expected behavior that the show callback is fired + self.element.queue( "tabs", function() { + self._trigger( "show", null, + self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); + }); + + this.load( o.selected ); + } + + // clean up to avoid memory leaks in certain versions of IE 6 + $( window ).bind( "unload.tabs", function() { + self.lis.add( self.anchors ).unbind( ".tabs" ); + self.lis = self.anchors = self.panels = null; + }); }, _setOption: function( key, value ) { @@ -52,7 +126,7 @@ $.widget( "ui.tabs", { this.select( value ); } else { this.options[ key ] = value; - this._tabify(); + this.refresh(); } }, @@ -80,9 +154,64 @@ $.widget( "ui.tabs", { }; }, - _tabify: function( init ) { + refresh: function() { + var self = this; + + this._processTabs(); + + this._refresh(); + + // Remove panels that we created that are missing their tab + this.element.find(".ui-tabs-panel:data(destroy.tabs)").each( function( index, panel ) { + var anchor = self.anchors.filter( "[href$='#" + panel.id + "']"); + if ( !anchor.length ) { + $( panel ).remove(); + } + }); + }, + + _refresh: function() { + var self = this, + o = this.options; + + this.element + .toggleClass( "ui-tabs-collapsible", o.collapsible ); + + this.list + .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); + + this.lis + .addClass( "ui-state-default ui-corner-top" ); + + this.panels + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); + + if ( !o.disabled.length ) { + o.disabled = false; + } + + // set or update cookie after init and add/remove respectively + if ( o.cookie ) { + this._cookie( o.selected, o.cookie ); + } + + // disable tabs + for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { + $( li ).toggleClass( "ui-state-disabled", $.inArray( i, o.disabled ) != -1 ); + } + + this._setupEvents( o.event ); + + // remove all handlers, may run on existing tabs + this.lis.unbind( ".tabs" ); + + + this._focusable( this.lis ); + this._hoverable( this.lis ); + }, + + _processTabs: function() { var self = this, - o = this.options, fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash this.list = this.element.find( "ol,ul" ).eq( 0 ); @@ -124,7 +253,7 @@ $.widget( "ui.tabs", { a.href = "#" + id; var $panel = self.element.find( "#" + id ); if ( !$panel.length ) { - $panel = $( o.panelTemplate ) + $panel = $( self.options.panelTemplate ) .attr( "id", id ) .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) .insertAfter( self.panels[ i - 1 ] || self.list ); @@ -133,125 +262,21 @@ $.widget( "ui.tabs", { self.panels = self.panels.add( $panel ); // invalid tab href } else { - o.disabled.push( i ); + self.options.disabled.push( i ); } }); + }, - // initialization from scratch - if ( init ) { - // attach necessary classes for styling - this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); - this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); - this.lis.addClass( "ui-state-default ui-corner-top" ); - this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); - - // Selected tab - // use "selected" option or try to retrieve: - // 1. from fragment identifier in url - // 2. from cookie - // 3. from selected class attribute on
          • - if ( o.selected === undefined ) { - if ( location.hash ) { - this.anchors.each(function( i, a ) { - if ( a.hash == location.hash ) { - o.selected = i; - return false; - } - }); - } - if ( typeof o.selected !== "number" && o.cookie ) { - o.selected = parseInt( self._cookie(), 10 ); - } - if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { - o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); - } - o.selected = o.selected || ( this.lis.length ? 0 : -1 ); - } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release - o.selected = -1; - } - - // sanity check - default to first tab... - o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) - ? o.selected - : 0; - - // Take disabling tabs via class attribute from HTML - // into account and update option properly. - if ( $.isArray( o.disabled ) ) { - o.disabled = $.unique( o.disabled.concat( - $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { - return self.lis.index( n ); - }) - ) ).sort(); - } - - // highlight selected tab - this.panels.addClass( "ui-tabs-hide" ); - this.lis.removeClass( "ui-tabs-selected ui-state-active" ); - // check for length avoids error when initializing empty list - if ( o.selected >= 0 && this.anchors.length ) { - self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); - this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); - - // seems to be expected behavior that the show callback is fired - self.element.queue( "tabs", function() { - self._trigger( "show", null, - self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); - }); - - this.load( o.selected ); - } - - // clean up to avoid memory leaks in certain versions of IE 6 - // TODO: namespace this event - $( window ).bind( "unload", function() { - self.lis.add( self.anchors ).unbind( ".tabs" ); - self.lis = self.anchors = self.panels = null; - }); - // update selected after add/remove - } else { - o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); - } - - if ( !o.disabled.length ) { - o.disabled = false; - } - - this.element.toggleClass( "ui-tabs-collapsible", o.collapsible ); - - // set or update cookie after init and add/remove respectively - if ( o.cookie ) { - this._cookie( o.selected, o.cookie ); - } - - // disable tabs - for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { - $( li ).toggleClass( "ui-state-disabled", $.inArray( i, o.disabled ) != -1 ); - } - - // remove all handlers before, tabify may run on existing tabs after add or option change - this.lis.add( this.anchors ).unbind( ".tabs" ); - - this._focusable( this.lis ); - this._hoverable( this.lis ); - + _setupFx: function( fx ) { // set up animations - if ( o.fx ) { - if ( $.isArray( o.fx ) ) { - this.hideFx = o.fx[ 0 ]; - this.showFx = o.fx[ 1 ]; + if ( fx ) { + if ( $.isArray( fx ) ) { + this.hideFx = fx[ 0 ]; + this.showFx = fx[ 1 ]; } else { - this.hideFx = this.showFx = o.fx; + this.hideFx = this.showFx = fx; } } - - // attach tab event handler, unbind to avoid duplicates from former tabifying... - this.anchors.bind( o.event + ".tabs", $.proxy( this, "_eventHandler" )); - - // disable click in any case - this.anchors.bind( "click.tabs", function( event ){ - event.preventDefault(); - }); }, // Reset certain styles left over from animation @@ -297,6 +322,21 @@ $.widget( "ui.tabs", { } }, + _setupEvents: function( event ) { + // attach tab event handler, unbind to avoid duplicates from former tabifying... + this.anchors.unbind( ".tabs" ); + + if ( event ) { + this.anchors.bind( event.split( " " ).join( ".tabs " ) + ".tabs", + $.proxy( this, "_eventHandler" ) ); + } + + // disable click in any case + this.anchors.bind( "click.tabs", function( event ){ + event.preventDefault(); + }); + }, + _eventHandler: function( event ) { event.preventDefault(); var self = this, @@ -764,7 +804,7 @@ if ( $.uiBackCompat !== false ) { return n >= index ? ++n : n; }); - this._tabify(); + this.refresh(); if ( this.anchors.length == 1 ) { o.selected = 0; @@ -801,7 +841,7 @@ if ( $.uiBackCompat !== false ) { return n >= index ? --n : n; }); - this._tabify(); + this.refresh(); this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); return this; -- cgit v1.2.3 From f6e7b6c9f6b49e4c7ab648bd617fe724ce0fb417 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 20:49:59 -0400 Subject: Use this.running to know if we are still in process of showing/hidding a tab --- ui/jquery.ui.tabs.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 14c74b110..0157a3329 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -44,6 +44,8 @@ $.widget( "ui.tabs", { var self = this, o = this.options; + this.running = false; + this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); this._processTabs(); @@ -294,9 +296,11 @@ $.widget( "ui.tabs", { $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); if ( this.showFx ) { + self.running = true; show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way .animate( showFx, showFx.duration || "normal", function() { self._resetStyle( show, showFx ); + self.running = false; self._trigger( "show", event, self._ui( clicked, show[ 0 ] ) ); }); } else { @@ -309,7 +313,9 @@ $.widget( "ui.tabs", { var self = this; if ( this.hideFx ) { + self.running = true; $hide.animate( hideFx, hideFx.duration || "normal", function() { + self.running = false; self.lis.removeClass( "ui-tabs-selected ui-state-active" ); $hide.addClass( "ui-tabs-hide" ); self._resetStyle( $hide, hideFx ); @@ -346,14 +352,15 @@ $.widget( "ui.tabs", { $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), $show = self.element.find( self._sanitizeSelector( el.hash ) ); - // If tab is already selected and not collapsible or tab disabled or - // or is already loading or click callback returns false stop here. - // Check if click handler returns false last so that it is not executed - // for a disabled or loading tab! - if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || + // tab is already selected, but not collapsible + if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible ) || + // can't switch durning an animation + self.running || + // tab is disabled $li.hasClass( "ui-state-disabled" ) || + // tab is already loading $li.hasClass( "ui-state-processing" ) || - self.panels.filter( ":animated" ).length || + // allow canceling by select event self._trigger( "select", event, self._ui( el, $show[ 0 ] ) ) === false ) { el.blur(); return; -- cgit v1.2.3 From 1e2d3145fff7cdeca61e62f95eb1e30c37e664c5 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sat, 26 Mar 2011 22:14:17 -0400 Subject: Tabs: Deprecate url method; use aria-controls instead of title to specify panels. Fixes #7132 Tabs: Deprecate url method; use aria-controls instead of title to specify panels --- demos/tabs/ajax.html | 3 +- tests/unit/tabs/tabs_deprecated.js | 24 +++++++++++ tests/unit/tabs/tabs_methods.js | 4 -- tests/unit/tabs/tabs_tickets.js | 37 +++++++--------- ui/jquery.ui.tabs.js | 87 ++++++++++++++++++++++---------------- 5 files changed, 92 insertions(+), 63 deletions(-) diff --git a/demos/tabs/ajax.html b/demos/tabs/ajax.html index c62625791..284de57f9 100644 --- a/demos/tabs/ajax.html +++ b/demos/tabs/ajax.html @@ -14,7 +14,8 @@ $( "#tabs" ).tabs({ ajaxOptions: { error: function( xhr, status, index, anchor ) { - $( anchor.hash ).html( + var selector = $( anchor ).attr( "aria-controls" ); + $( selector ).html( "Couldn't load this tab. We'll try to fix this as soon as possible. " + "If this wouldn't be a demo." ); } diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 880ea075e..ef03d84cb 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -1,5 +1,19 @@ (function( $ ) { +module("tabs (deprecated): core"); + +test( "#4581 - title attribute for remote tabs does not support foreign languages", function() { + expect( 1 ); + + $( "#tabs2" ).tabs({ + selected: 3, + beforeload: function( event, ui ) { + event.preventDefault(); + equal( ui.panel.id, "∫ßáö_Սե", "proper title" ); + } + }); +}); + module("tabs (deprecated): options"); test('ajaxOptions', function() { @@ -148,4 +162,14 @@ test('length', function() { equals(el.tabs('length'), $('ul a', el).length, ' should return length'); }); +test('url', function() { + el = $('#tabs2').tabs(); + var tab = el.find('a:eq(3)'), + url = tab.attr('href'); + + el.tabs('url', 3, "data/test2.html"); + equals(tab.attr('href'), 'data/test2.html', 'Url was updated'); + tab.attr('href', url ); +}); + }( jQuery ) ); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index 50b8abd27..e00a95a3e 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -191,8 +191,4 @@ test('load', function() { ok(false, "missing test - untested code is broken code."); }); -test('url', function() { - ok(false, "missing test - untested code is broken code."); -}); - })(jQuery); diff --git a/tests/unit/tabs/tabs_tickets.js b/tests/unit/tabs/tabs_tickets.js index c301e9eb0..9df72a6f7 100644 --- a/tests/unit/tabs/tabs_tickets.js +++ b/tests/unit/tabs/tabs_tickets.js @@ -42,21 +42,29 @@ test('#3627 - Ajax tab with url containing a fragment identifier fails to load', // http://dev.jqueryui.com/ticket/3627 expect(1); - el = $('#tabs2').tabs(); - - ok(/test.html$/.test( $('a:eq(2)', el).data('load.tabs') ), 'should ignore fragment identifier'); - + el = $('#tabs2').tabs({ + selected: 2, + beforeload: function( event, ui ) { + event.preventDefault(); + ok(/test.html$/.test( ui.settings.url ), 'should ignore fragment identifier'); + } + }); }); test('#4033 - IE expands hash to full url and misinterprets tab as ajax', function() { // http://dev.jqueryui.com/ticket/4033 expect(1); - el = $('') - .appendTo('#main').tabs(); + el = $(''); + el.appendTo('#main'); + el.tabs({ + beforeload: function( event, ui ) { + event.preventDefault(); + ok( false, 'should not be an ajax tab'); + } + }); - equals($('a', el).data('load.tabs'), undefined, 'should not create ajax tab'); - + equals($('a', el).attr('aria-controls'), '#tab', 'aria-contorls attribute is correct'); }); test('#5893 - Sublist in the tab list are considered as tab', function() { @@ -68,19 +76,6 @@ test('#5893 - Sublist in the tab list are considered as tab', function() { }); -asyncTest( "#4581 - title attribute for remote tabs does not support foreign languages", function() { - expect( 1 ); - - $( "#tabs2" ).tabs({ - selected: 3, - load: function( event, ui ) { - equal( ui.panel.id, "∫ßáö_Սե", "proper title" ); - start(); - } - }); -}); - - test('#6710 - selectors are global', function() { // http://bugs.jqueryui.com/ticket/6710 expect(1); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 0157a3329..f3741f0a6 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -99,15 +99,16 @@ $.widget( "ui.tabs", { this.lis.removeClass( "ui-tabs-selected ui-state-active" ); // check for length avoids error when initializing empty list if ( o.selected >= 0 && this.anchors.length ) { - var temp = self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) - .removeClass( "ui-tabs-hide" ); + var tab = self.anchors[ o.selected ], + panel = self.element.find( self._sanitizeSelector( $( tab ).attr( "aria-controls" ) ) ); + + panel.removeClass( "ui-tabs-hide" ); this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); // seems to be expected behavior that the show callback is fired self.element.queue( "tabs", function() { - self._trigger( "show", null, - self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); + self._trigger( "show", null, self._ui( tab, panel[ 0 ] ) ); }); this.load( o.selected ); @@ -133,7 +134,7 @@ $.widget( "ui.tabs", { }, _tabId: function( a ) { - return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || + return ( $( a ).attr( "aria-controls" ) || "" ).replace( /^#/ , "" ) || this.options.idPrefix + getNextTabId(); }, @@ -165,7 +166,7 @@ $.widget( "ui.tabs", { // Remove panels that we created that are missing their tab this.element.find(".ui-tabs-panel:data(destroy.tabs)").each( function( index, panel ) { - var anchor = self.anchors.filter( "[href$='#" + panel.id + "']"); + var anchor = self.anchors.filter( "[aria-controls='#" + panel.id + "']"); if ( !anchor.length ) { $( panel ).remove(); } @@ -224,14 +225,17 @@ $.widget( "ui.tabs", { this.panels = $( [] ); this.anchors.each(function( i, a ) { - var href = $( a ).attr( "href" ); + var href = $( a ).attr( "href" ), + hrefBase = href.split( "#" )[ 0 ], + selector, + panel, + baseEl; + // For dynamically created HTML that contains a hash as href IE < 8 expands // such href to the full page url with hash and then misinterprets tab as ajax. // Same consideration applies for an added tab with a fragment identifier // since a[href=#fragment-identifier] does unexpectedly not match. // Thus normalize href attribute... - var hrefBase = href.split( "#" )[ 0 ], - baseEl; if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] || ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) { href = a.hash; @@ -240,32 +244,30 @@ $.widget( "ui.tabs", { // inline tab if ( fragmentId.test( href ) ) { - self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); + selector = href; + panel = self.element.find( self._sanitizeSelector( selector ) ); // remote tab // prevent loading the page itself if href is just "#" } else if ( href && href !== "#" ) { - // required for restore on destroy - $.data( a, "href.tabs", href ); - - // TODO until #3808 is fixed strip fragment identifier from url - // (IE fails to load from such url) - $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); - var id = self._tabId( a ); - a.href = "#" + id; - var $panel = self.element.find( "#" + id ); - if ( !$panel.length ) { - $panel = $( self.options.panelTemplate ) + selector = "#" + id; + panel = self.element.find( selector ); + if ( !panel.length ) { + panel = $( self.options.panelTemplate ) .attr( "id", id ) .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "destroy.tabs", true ) .insertAfter( self.panels[ i - 1 ] || self.list ); - $panel.data( "destroy.tabs", true ); } - self.panels = self.panels.add( $panel ); // invalid tab href } else { self.options.disabled.push( i ); } + + if ( panel.length) { + self.panels = self.panels.add( panel ); + } + $( a ).attr( "aria-controls", selector ); }); }, @@ -348,9 +350,9 @@ $.widget( "ui.tabs", { var self = this, o = this.options, el = event.currentTarget, - $li = $(el).closest( "li" ), + $li = $( el ).closest( "li" ), $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), - $show = self.element.find( self._sanitizeSelector( el.hash ) ); + $show = self.element.find( self._sanitizeSelector( $( el ).attr( "aria-controls" ) ) ); // tab is already selected, but not collapsible if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible ) || @@ -455,10 +457,6 @@ $.widget( "ui.tabs", { this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); this.anchors.each(function() { - var href = $.data( this, "href.tabs" ); - if ( href ) { - this.href = href; - } var $this = $( this ).unbind( ".tabs" ); $.each( [ "href", "load" ], function( i, prefix ) { $this.removeData( prefix + ".tabs" ); @@ -558,8 +556,11 @@ $.widget( "ui.tabs", { var self = this, o = this.options, a = this.anchors.eq( index )[ 0 ], - url = $.data( a, "load.tabs" ), - eventData = self._ui( self.anchors[ index ], self.panels[ index ] ); + panel = self.element.find( self._sanitizeSelector( $( a ).attr( "aria-controls" ) ) ), + // TODO until #3808 is fixed strip fragment identifier from url + // (IE fails to load from such url) + url = $( a ).attr( "href" ).replace( /#.*$/, "" ), + eventData = self._ui( a, panel[ 0 ] ); if ( this.xhr ) { this.xhr.abort(); @@ -585,7 +586,7 @@ $.widget( "ui.tabs", { this.xhr .success( function( response ) { - self.element.find( self._sanitizeSelector( a.hash ) ).html( response ); + panel.html( response ); }) .complete( function( jqXHR, status ) { if ( status === "abort" ) { @@ -609,13 +610,9 @@ $.widget( "ui.tabs", { // last, so that load event is fired before show... self.element.dequeue( "tabs" ); - return this; - }, - - url: function( index, url ) { - this.anchors.eq( index ).data( "load.tabs", url ); return this; } + }); $.extend( $.ui.tabs, { @@ -861,6 +858,22 @@ if ( $.uiBackCompat !== false ) { return this.anchors.length; }; }( jQuery, jQuery.ui.tabs.prototype ) ); + + // url method + (function( $, prototype ) { + prototype.url = function( index, url ) { + this.anchors.eq( index ).attr( "href", url ); + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); + + // _tabId method + (function( $, prototype ) { + var _tabId = prototype._tabId; + prototype._tabId = function( a ) { + return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || + _tabId.apply( this, arguments ); + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); } })( jQuery ); -- cgit v1.2.3 From c363019590da9c38754fb7c60e5f44e25ca48e21 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sun, 27 Mar 2011 15:12:53 -0400 Subject: Tabs: Deprecate templating (idPrefix, tabTemplate, panelTemplate options) Fixes #7139 Tabs: Deprecate templating (idPrefix, tabTemplate, panelTemplate options) --- tests/unit/tabs/tabs_defaults.js | 5 +--- tests/unit/tabs/tabs_deprecated.js | 12 +++++++++ tests/unit/tabs/tabs_options.js | 12 --------- ui/jquery.ui.tabs.js | 52 ++++++++++++++++++++++++++------------ 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index f7307b458..98cb99fb5 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -9,12 +9,9 @@ var tabs_defaults = { disabled: false, event: "click", fx: null, - idPrefix: "ui-tabs-", load: null, - panelTemplate: "
            ", select: null, - show: null, - tabTemplate: "
          • #{label}
          • " + show: null }; // FAIL: falsy values break the cookie option diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index ef03d84cb..7e4816793 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -24,6 +24,18 @@ test('cache', function() { ok(false, "missing test - untested code is broken code."); }); +test('idPrefix', function() { + ok(false, "missing test - untested code is broken code."); +}); + +test('tabTemplate', function() { + ok(false, "missing test - untested code is broken code."); +}); + +test('panelTemplate', function() { + ok(false, "missing test - untested code is broken code."); +}); + test('spinner', function() { expect(4); stop(); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index 45fba8f32..de6d7e74e 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -79,14 +79,6 @@ test('fx', function() { ok(false, "missing test - untested code is broken code."); }); -test('idPrefix', function() { - ok(false, "missing test - untested code is broken code."); -}); - -test('panelTemplate', function() { - ok(false, "missing test - untested code is broken code."); -}); - test('selected', function() { expect(8); @@ -117,8 +109,4 @@ test('selected', function() { equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if value is same as selected'); }); -test('tabTemplate', function() { - ok(false, "missing test - untested code is broken code."); -}); - })(jQuery); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index f3741f0a6..4a7ae3981 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -32,12 +32,9 @@ $.widget( "ui.tabs", { disabled: false, event: "click", fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } - idPrefix: "ui-tabs-", load: null, - panelTemplate: "
            ", select: null, - show: null, - tabTemplate: "
          • #{label}
          • " + show: null }, _create: function() { @@ -135,7 +132,7 @@ $.widget( "ui.tabs", { _tabId: function( a ) { return ( $( a ).attr( "aria-controls" ) || "" ).replace( /^#/ , "" ) || - this.options.idPrefix + getNextTabId(); + "ui-tabs-" + getNextTabId(); }, _sanitizeSelector: function( hash ) { @@ -253,11 +250,8 @@ $.widget( "ui.tabs", { selector = "#" + id; panel = self.element.find( selector ); if ( !panel.length ) { - panel = $( self.options.panelTemplate ) - .attr( "id", id ) - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) - .data( "destroy.tabs", true ) - .insertAfter( self.panels[ i - 1 ] || self.list ); + panel = self._createPanel( id ); + panel.insertAfter( self.panels[ i - 1 ] || self.list ); } // invalid tab href } else { @@ -271,6 +265,13 @@ $.widget( "ui.tabs", { }); }, + _createPanel: function( id ) { + return $( "
            " ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "destroy.tabs", true ); + }, + _setupFx: function( fx ) { // set up animations if ( fx ) { @@ -772,7 +773,8 @@ if ( $.uiBackCompat !== false ) { (function( $, prototype ) { $.extend( prototype.options, { add: null, - remove: null + remove: null, + tabTemplate: "
          • #{label}
          • " }); prototype.add = function( url, label, index ) { @@ -790,9 +792,7 @@ if ( $.uiBackCompat !== false ) { // try to find an existing element before creating a new one var $panel = self.element.find( "#" + id ); if ( !$panel.length ) { - $panel = $( o.panelTemplate ) - .attr( "id", id ) - .data( "destroy.tabs", true ); + $panel = self._createPanel( id ); } $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); @@ -868,10 +868,30 @@ if ( $.uiBackCompat !== false ) { // _tabId method (function( $, prototype ) { + $.extend( prototype.options, { + idPrefix: "ui-tabs-" + }); + var _tabId = prototype._tabId; prototype._tabId = function( a ) { - return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || - _tabId.apply( this, arguments ); + return ( $( a ).attr( "aria-controls" ) || "" ).replace( /^#/ , "" ) || + a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || + this.options.idPrefix + getNextTabId(); + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); + + // _tabId method + (function( $, prototype ) { + $.extend( prototype.options, { + panelTemplate: "
            " + }); + + var _createPanel = prototype._createPanel; + prototype._createPanel = function( id ) { + return $( this.options.panelTemplate ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "destroy.tabs", true ); }; }( jQuery, jQuery.ui.tabs.prototype ) ); } -- cgit v1.2.3 From 9a00fd4c5ef637f29afc6debda4db136f1fcb3fb Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sun, 27 Mar 2011 16:37:43 -0400 Subject: Tabs: Rename selected option to active. Fixes #7135 Tabs: Rename selected option to active --- tests/unit/tabs/tabs_deprecated.js | 49 ++++++++++++++++++++++ tests/unit/tabs/tabs_events.js | 2 +- tests/unit/tabs/tabs_methods.js | 24 +++++------ tests/unit/tabs/tabs_options.js | 30 +++++++------- tests/unit/tabs/tabs_tickets.js | 2 +- ui/jquery.ui.tabs.js | 84 ++++++++++++++++++++++++++------------ 6 files changed, 136 insertions(+), 55 deletions(-) diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 7e4816793..8b6b50d7e 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -65,6 +65,55 @@ test('spinner', function() { }); }); +test('selected', function() { + expect(11); + + el = $('#tabs1').tabs(); + equals(el.tabs('option', 'selected'), 0, 'should be 0 by default'); + + el.tabs('destroy'); + //set a hash in the url + location.hash = '#fragment-2'; + //selection of tab with divs ordered differently than list + el = $('#tabs1').tabs(); + equals(el.tabs('option', 'selected'), 1, 'second tab should be selected'); + + el.tabs('destroy'); + //set a hash in the url + location.hash = '#tabs7-2'; + //selection of tab with divs ordered differently than list + el = $('#tabs7').tabs(); + equals(el.tabs('option', 'selected'), 1, 'second tab should be selected'); + + el.tabs('destroy'); + el = $('#tabs1').tabs({ selected: -1 }); + equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected'); + equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be selected' ); + equals( $('div.ui-tabs-hide', '#tabs1').length, 3, 'all panels should be hidden' ); + + el.tabs('destroy'); + el.tabs({ selected: null }); + equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected with value null (deprecated)'); + + el.tabs('destroy'); + el.tabs({ selected: 1 }); + equals(el.tabs('option', 'selected'), 1, 'should be specified tab'); + + el.tabs('destroy'); + el.tabs({ selected: 99 }); + equals(el.tabs('option', 'selected'), 0, 'selected should default to zero if given value is out of index'); + + el.tabs('destroy'); + el.tabs({ collapsible: true }); + el.tabs('option', 'selected', 0); + equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if value is same as selected'); + + el.tabs('destroy'); + el = $('#tabs1').tabs(); + el.tabs('select', 1); + equals(el.tabs('option', 'selected'), 1, 'should select tab'); +}); + module("tabs (deprecated): events"); test('enable', function() { diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index b3f8653a2..04f282157 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -32,7 +32,7 @@ test('beforeload', function() { el = $('#tabs2'); el.tabs({ - selected: 2, + active: 2, beforeload: function( event, ui ) { ok( $.isFunction( ui.jqXHR.promise ), 'contain jqXHR object'); equals( ui.settings.url, "data/test.html", 'contain ajax settings url'); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index e00a95a3e..dbb5c2d15 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -16,7 +16,7 @@ test('init', function() { ok( $('div:eq(0)', el).is('.ui-tabs-panel.ui-widget-content.ui-corner-bottom'), 'attach classes to panel' ); ok( $('li:eq(0)', el).is('.ui-tabs-selected.ui-state-active.ui-corner-top'), 'attach classes to active li'); ok( $('li:eq(1)', el).is('.ui-state-default.ui-corner-top'), 'attach classes to inactive li'); - equals( el.tabs('option', 'selected'), 0, 'selected option set' ); + equals( el.tabs('option', 'active'), 0, 'active option set' ); equals( $('li', el).index( $('li.ui-tabs-selected', el) ), 0, 'second tab active'); equals( $('div', el).index( $('div.ui-tabs-hide', '#tabs1') ), 1, 'second panel should be hidden' ); }); @@ -30,7 +30,7 @@ test('init with hash', function() { //selection of tab with divs ordered differently than list el = $('#tabs1').tabs(); - equals(el.tabs('option', 'selected'), 1, 'second tab should be selected'); + equals(el.tabs('option', 'active'), 1, 'second tab should be active'); ok(!$('#tabs1 ul li:eq(0)').is('.ui-tabs-selected.ui-state-active'), 'first tab should not be selected nor active'); ok($('#tabs1 div:eq(0)').is('.ui-tabs-hide'), 'first div for first tab should be hidden'); @@ -48,7 +48,7 @@ test('init mismatched order with hash', function() { //selection of tab with divs ordered differently than list el = $('#tabs7').tabs(); - equals(el.tabs('option', 'selected'), 1, 'second tab should be selected'); + equals(el.tabs('option', 'active'), 1, 'second tab should be active'); ok(!$('#tabs7-list li:eq(0)').is('.ui-tabs-selected.ui-state-active'), 'first tab should not be selected nor active'); ok($('#tabs7 div:eq(1)').is('.ui-tabs-hide'), 'second div for first tab should be hidden'); @@ -136,27 +136,27 @@ test('select', function() { el = $('#tabs1').tabs(); el.tabs('select', 1); - equals(el.tabs('option', 'selected'), 1, 'should select tab'); + equals(el.tabs('option', 'active'), 1, 'should select tab'); el.tabs('destroy'); el.tabs({ collapsible: true }); el.tabs('select', 0); - equals(el.tabs('option', 'selected'), -1, 'should collapse tab passing in the already selected tab'); + equals(el.tabs('option', 'active'), -1, 'should collapse tab passing in the already active tab'); el.tabs('destroy'); el.tabs({ collapsible: true }); el.tabs('select', -1); - equals(el.tabs('option', 'selected'), -1, 'should collapse tab passing in -1'); + equals(el.tabs('option', 'active'), -1, 'should collapse tab passing in -1'); el.tabs('destroy'); el.tabs(); el.tabs('select', 0); - equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if collapsible is not set to true'); + equals(el.tabs('option', 'active'), 0, 'should not collapse tab if collapsible is not set to true'); el.tabs('select', -1); - equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if collapsible is not set to true'); + equals(el.tabs('option', 'active'), 0, 'should not collapse tab if collapsible is not set to true'); el.tabs('select', '#fragment-2'); - equals(el.tabs('option', 'selected'), 1, 'should select tab by id'); + equals(el.tabs('option', 'active'), 1, 'should select tab by id'); }); test('refresh', function() { @@ -165,7 +165,7 @@ test('refresh', function() { var el = $('
              ').tabs(), ul = el.find('ul'); - equals(el.tabs('option', 'selected'), -1, 'Initially empty, no selected tab'); + equals(el.tabs('option', 'active'), -1, 'Initially empty, no active tab'); ul.append('
            • Test 1
            • '); el.tabs('refresh'); @@ -179,12 +179,12 @@ test('refresh', function() { $('
              Test Panel 1
              ').insertAfter( ul ); el.tabs('refresh'); el.tabs('select', 0); - equals( el.tabs('option', 'selected'), 0, 'First tab added should be auto selected'); + equals( el.tabs('option', 'active'), 0, 'First tab added should be auto active'); ul.append('
            • Test 2
            • '); $('
              Test Panel 2
              ').insertAfter( ul ); el.tabs('refresh'); - equals( el.tabs('option', 'selected'), 0, 'Second tab added should not be auto selected'); + equals( el.tabs('option', 'active'), 0, 'Second tab added should not be auto active'); }); test('load', function() { diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index de6d7e74e..b1a7a5e78 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -34,8 +34,8 @@ test('cookie', function() { equals(cookie(), 0, 'initial cookie value'); el.tabs('destroy'); - el.tabs({ selected: 1, cookie: cookieObj }); - equals(cookie(), 1, 'initial cookie value, from selected property'); + el.tabs({ active: 1, cookie: cookieObj }); + equals(cookie(), 1, 'initial cookie value, from active property'); el.tabs('select', 2); equals(cookie(), 2, 'cookie value updated after select'); @@ -79,34 +79,34 @@ test('fx', function() { ok(false, "missing test - untested code is broken code."); }); -test('selected', function() { +test('active', function() { expect(8); el = $('#tabs1').tabs(); - equals(el.tabs('option', 'selected'), 0, 'should be 0 by default'); + equals(el.tabs('option', 'active'), 0, 'should be 0 by default'); el.tabs('destroy'); - el.tabs({ selected: -1 }); - equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected'); - equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be selected' ); + el.tabs({ active: -1 }); + equals(el.tabs('option', 'active'), -1, 'should be -1 for all tabs deactive'); + equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be active' ); equals( $('div.ui-tabs-hide', '#tabs1').length, 3, 'all panels should be hidden' ); el.tabs('destroy'); - el.tabs({ selected: null }); - equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected with value null (deprecated)'); + el.tabs({ active: null }); + equals(el.tabs('option', 'active'), -1, 'should be -1 for all tabs deactive with value null (deprecated)'); el.tabs('destroy'); - el.tabs({ selected: 1 }); - equals(el.tabs('option', 'selected'), 1, 'should be specified tab'); + el.tabs({ active: 1 }); + equals(el.tabs('option', 'active'), 1, 'should be specified tab'); el.tabs('destroy'); - el.tabs({ selected: 99 }); - equals(el.tabs('option', 'selected'), 0, 'selected should default to zero if given value is out of index'); + el.tabs({ active: 99 }); + equals(el.tabs('option', 'active'), 0, 'active should default to zero if given value is out of index'); el.tabs('destroy'); el.tabs({ collapsible: true }); - el.tabs('option', 'selected', 0); - equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if value is same as selected'); + el.tabs('option', 'active', 0); + equals(el.tabs('option', 'active'), 0, 'should not collapse tab if value is same as active'); }); })(jQuery); diff --git a/tests/unit/tabs/tabs_tickets.js b/tests/unit/tabs/tabs_tickets.js index 9df72a6f7..486d3b6d2 100644 --- a/tests/unit/tabs/tabs_tickets.js +++ b/tests/unit/tabs/tabs_tickets.js @@ -43,7 +43,7 @@ test('#3627 - Ajax tab with url containing a fragment identifier fails to load', expect(1); el = $('#tabs2').tabs({ - selected: 2, + active: 2, beforeload: function( event, ui ) { event.preventDefault(); ok(/test.html$/.test( ui.settings.url ), 'should ignore fragment identifier'); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 4a7ae3981..d76565a2a 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -52,29 +52,29 @@ $.widget( "ui.tabs", { // 1. from fragment identifier in url // 2. from cookie // 3. from selected class attribute on
            • - if ( o.selected === undefined ) { + if ( o.active === undefined ) { if ( location.hash ) { this.anchors.each(function( i, a ) { if ( a.hash == location.hash ) { - o.selected = i; + o.active = i; return false; } }); } - if ( typeof o.selected !== "number" && o.cookie ) { - o.selected = parseInt( self._cookie(), 10 ); + if ( typeof o.active !== "number" && o.cookie ) { + o.active = parseInt( self._cookie(), 10 ); } - if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { - o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + if ( typeof o.active !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { + o.active = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); } - o.selected = o.selected || ( this.lis.length ? 0 : -1 ); - } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release - o.selected = -1; + o.active = o.active || ( this.lis.length ? 0 : -1 ); + } else if ( o.active === null ) { // usage of null is deprecated, TODO remove in next release + o.active = -1; } // sanity check - default to first tab... - o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) - ? o.selected + o.active = ( ( o.active >= 0 && this.anchors[ o.active ] ) || o.active < 0 ) + ? o.active : 0; // Take disabling tabs via class attribute from HTML @@ -95,20 +95,20 @@ $.widget( "ui.tabs", { this.panels.addClass( "ui-tabs-hide" ); this.lis.removeClass( "ui-tabs-selected ui-state-active" ); // check for length avoids error when initializing empty list - if ( o.selected >= 0 && this.anchors.length ) { - var tab = self.anchors[ o.selected ], + if ( o.active >= 0 && this.anchors.length ) { + var tab = self.anchors[ o.active ], panel = self.element.find( self._sanitizeSelector( $( tab ).attr( "aria-controls" ) ) ); panel.removeClass( "ui-tabs-hide" ); - this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); + this.lis.eq( o.active ).addClass( "ui-tabs-selected ui-state-active" ); // seems to be expected behavior that the show callback is fired self.element.queue( "tabs", function() { self._trigger( "show", null, self._ui( tab, panel[ 0 ] ) ); }); - this.load( o.selected ); + this.load( o.active ); } // clean up to avoid memory leaks in certain versions of IE 6 @@ -119,8 +119,8 @@ $.widget( "ui.tabs", { }, _setOption: function( key, value ) { - if ( key == "selected" ) { - if (this.options.collapsible && value == this.options.selected ) { + if ( key == "active" ) { + if (this.options.collapsible && value == this.options.active ) { return; } this.select( value ); @@ -192,7 +192,7 @@ $.widget( "ui.tabs", { // set or update cookie after init and add/remove respectively if ( o.cookie ) { - this._cookie( o.selected, o.cookie ); + this._cookie( o.active, o.cookie ); } // disable tabs @@ -369,7 +369,7 @@ $.widget( "ui.tabs", { return; } - o.selected = self.anchors.index( el ); + o.active = self.anchors.index( el ); if ( self.xhr ) { self.xhr.abort(); @@ -378,10 +378,10 @@ $.widget( "ui.tabs", { // if tab may be closed if ( o.collapsible ) { if ( $li.hasClass( "ui-tabs-selected" ) ) { - o.selected = -1; + o.active = -1; if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); + self._cookie( o.active, o.cookie ); } self.element.queue( "tabs", function() { @@ -392,7 +392,7 @@ $.widget( "ui.tabs", { return; } else if ( !$hide.length ) { if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); + self._cookie( o.active, o.cookie ); } self.element.queue( "tabs", function() { @@ -408,7 +408,7 @@ $.widget( "ui.tabs", { } if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); + self._cookie( o.active, o.cookie ); } // show new tab @@ -542,8 +542,8 @@ $.widget( "ui.tabs", { select: function( index ) { index = this._getIndex( index ); if ( index == -1 ) { - if ( this.options.collapsible && this.options.selected != -1 ) { - index = this.options.selected; + if ( this.options.collapsible && this.options.active != -1 ) { + index = this.options.active; } else { return this; } @@ -811,7 +811,7 @@ if ( $.uiBackCompat !== false ) { this.refresh(); if ( this.anchors.length == 1 ) { - o.selected = 0; + o.active = o.selected = 0; $li.addClass( "ui-tabs-selected ui-state-active" ); $panel.removeClass( "ui-tabs-hide" ); this.element.queue( "tabs", function() { @@ -894,6 +894,38 @@ if ( $.uiBackCompat !== false ) { .data( "destroy.tabs", true ); }; }( jQuery, jQuery.ui.tabs.prototype ) ); + + // selected option + (function( $, prototype ) { + var _create = prototype._create, + _setOption = prototype._setOption, + _eventHandler = prototype._eventHandler; + + prototype._create = function() { + var options = this.options; + if ( options.active === undefined && options.selected !== undefined ) { + options.active = options.selected; + } + _create.call( this ); + options.selected = options.active; + }; + + prototype._setOption = function( key, value ) { + var options = this.options; + if ( key === "selected" ) { + key = "active"; + } + _setOption.apply( this, arguments ); + if ( key === "active" ) { + options.selected = options.active ; + } + }; + + prototype._eventHandler = function( event ) { + _eventHandler.apply( this, arguments ); + this.options.selected = this.options.active ; + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); } })( jQuery ); -- cgit v1.2.3 From 787efd307aff11ad3c51a72f520c58b8158ae973 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sun, 27 Mar 2011 16:55:05 -0400 Subject: Tabs: Rename show event to activate. Fixes #7137 Tabs: Rename show event to activate --- tests/unit/tabs/tabs_defaults.js | 4 ++-- tests/unit/tabs/tabs_defaults_deprecated.js | 1 + tests/unit/tabs/tabs_deprecated.js | 20 ++++++++++++++++++ tests/unit/tabs/tabs_events.js | 4 ++-- ui/jquery.ui.tabs.js | 32 ++++++++++++++++++++++------- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index 98cb99fb5..e155a3dac 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -3,6 +3,7 @@ */ var tabs_defaults = { + activate: null, beforeload: null, collapsible: false, cookie: null, @@ -10,8 +11,7 @@ var tabs_defaults = { event: "click", fx: null, load: null, - select: null, - show: null + select: null }; // FAIL: falsy values break the cookie option diff --git a/tests/unit/tabs/tabs_defaults_deprecated.js b/tests/unit/tabs/tabs_defaults_deprecated.js index 73e9ffede..47fd75d8f 100644 --- a/tests/unit/tabs/tabs_defaults_deprecated.js +++ b/tests/unit/tabs/tabs_defaults_deprecated.js @@ -3,6 +3,7 @@ */ var tabs_defaults = { + activate: null, add: null, ajaxOptions: null, beforeload: null, diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 8b6b50d7e..ba1a778b0 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -168,6 +168,26 @@ test('remove', function() { ok(false, "missing test - untested code is broken code."); }); +test('show', function() { + expect(5); + + var uiObj, eventObj; + el = $('#tabs1').tabs({ + show: function(event, ui) { + uiObj = ui; + eventObj = event; + } + }); + ok(uiObj !== undefined, 'trigger callback after initialization'); + equals(uiObj.tab, $('a', el)[0], 'contain tab as DOM anchor element'); + equals(uiObj.panel, $('div', el)[0], 'contain panel as DOM div element'); + equals(uiObj.index, 0, 'contain index'); + + el.find( "li:eq(1) a" ).simulate( "click" ); + equals( eventObj.originalEvent.type, "click", "show triggered by click" ); + +}); + module("tabs (deprecated): methods"); test('add', function() { diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index 04f282157..60affd7ff 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -49,12 +49,12 @@ test('load', function() { ok(false, "missing test - untested code is broken code."); }); -test('show', function() { +test('activate', function() { expect(5); var uiObj, eventObj; el = $('#tabs1').tabs({ - show: function(event, ui) { + activate: function(event, ui) { uiObj = ui; eventObj = event; } diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index d76565a2a..d605b2d48 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -26,6 +26,7 @@ function getNextListId() { $.widget( "ui.tabs", { options: { + activate: null, beforeload: null, cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } collapsible: false, @@ -33,8 +34,7 @@ $.widget( "ui.tabs", { event: "click", fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } load: null, - select: null, - show: null + select: null }, _create: function() { @@ -103,9 +103,9 @@ $.widget( "ui.tabs", { this.lis.eq( o.active ).addClass( "ui-tabs-selected ui-state-active" ); - // seems to be expected behavior that the show callback is fired + // seems to be expected behavior that the activate callback is fired self.element.queue( "tabs", function() { - self._trigger( "show", null, self._ui( tab, panel[ 0 ] ) ); + self._trigger( "activate", null, self._ui( tab, panel[ 0 ] ) ); }); this.load( o.active ); @@ -304,11 +304,11 @@ $.widget( "ui.tabs", { .animate( showFx, showFx.duration || "normal", function() { self._resetStyle( show, showFx ); self.running = false; - self._trigger( "show", event, self._ui( clicked, show[ 0 ] ) ); + self._trigger( "activate", event, self._ui( clicked, show[ 0 ] ) ); }); } else { show.removeClass( "ui-tabs-hide" ); - self._trigger( "show", event, self._ui( clicked, show[ 0 ] ) ); + self._trigger( "activate", event, self._ui( clicked, show[ 0 ] ) ); } }, @@ -815,7 +815,7 @@ if ( $.uiBackCompat !== false ) { $li.addClass( "ui-tabs-selected ui-state-active" ); $panel.removeClass( "ui-tabs-hide" ); this.element.queue( "tabs", function() { - self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); + self._trigger( "activate", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); }); this.load( 0 ); @@ -926,6 +926,24 @@ if ( $.uiBackCompat !== false ) { this.options.selected = this.options.active ; }; }( jQuery, jQuery.ui.tabs.prototype ) ); + + // show event + (function( $, prototype ) { + $.extend( prototype.options, { + show: null + }); + var _trigger = prototype._trigger; + + prototype._trigger = function( type, event, data ) { + var ret = _trigger.apply( this, arguments ); + if ( !ret ) { + return false; + } + if ( type === "activate" ) { + ret = _trigger.call( this, "show", event, data ); + } + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); } })( jQuery ); -- cgit v1.2.3 From 8b0c3618bdebddd98d4c09e77d14c50c4f4d3190 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sun, 27 Mar 2011 17:02:58 -0400 Subject: Tabs: Rename select event to beforeActivate. Fixes #7136 Tabs: Rename select event to beforeActivate --- tests/unit/tabs/tabs_defaults.js | 4 ++-- tests/unit/tabs/tabs_defaults_deprecated.js | 1 + tests/unit/tabs/tabs_deprecated.js | 21 +++++++++++++++++++++ tests/unit/tabs/tabs_events.js | 10 +++++----- ui/jquery.ui.tabs.js | 17 ++++++++++------- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index e155a3dac..194d2b76c 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -5,13 +5,13 @@ var tabs_defaults = { activate: null, beforeload: null, + beforeActivate: null, collapsible: false, cookie: null, disabled: false, event: "click", fx: null, - load: null, - select: null + load: null }; // FAIL: falsy values break the cookie option diff --git a/tests/unit/tabs/tabs_defaults_deprecated.js b/tests/unit/tabs/tabs_defaults_deprecated.js index 47fd75d8f..03ee13d3d 100644 --- a/tests/unit/tabs/tabs_defaults_deprecated.js +++ b/tests/unit/tabs/tabs_defaults_deprecated.js @@ -7,6 +7,7 @@ var tabs_defaults = { add: null, ajaxOptions: null, beforeload: null, + beforeActivate: null, cache: false, collapsible: false, cookie: null, diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index ba1a778b0..38fa6db71 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -188,6 +188,27 @@ test('show', function() { }); +test('select', function() { + expect(7); + + var eventObj; + el = $('#tabs1').tabs({ + select: function(event, ui) { + ok(true, 'select triggered after initialization'); + equals(this, el[0], "context of callback"); + equals(event.type, 'tabsselect', 'event type in callback'); + equals(ui.tab, el.find('a')[1], 'contain tab as DOM anchor element'); + equals(ui.panel, el.find('div')[1], 'contain panel as DOM div element'); + equals(ui.index, 1, 'contain index'); + evenObj = event; + } + }); + el.tabs('select', 1); + + el.find( "li:eq(1) a" ).simulate( "click" ); + equals( evenObj.originalEvent.type, "click", "select triggered by click" ); +}); + module("tabs (deprecated): methods"); test('add', function() { diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index 60affd7ff..4fedde842 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -5,15 +5,15 @@ module("tabs: events"); -test('select', function() { +test('beforeActivate', function() { expect(7); var eventObj; el = $('#tabs1').tabs({ - select: function(event, ui) { - ok(true, 'select triggered after initialization'); + beforeActivate: function(event, ui) { + ok(true, 'beforeActivate triggered after initialization'); equals(this, el[0], "context of callback"); - equals(event.type, 'tabsselect', 'event type in callback'); + equals(event.type, 'tabsbeforeactivate', 'event type in callback'); equals(ui.tab, el.find('a')[1], 'contain tab as DOM anchor element'); equals(ui.panel, el.find('div')[1], 'contain panel as DOM div element'); equals(ui.index, 1, 'contain index'); @@ -23,7 +23,7 @@ test('select', function() { el.tabs('select', 1); el.find( "li:eq(1) a" ).simulate( "click" ); - equals( evenObj.originalEvent.type, "click", "select triggered by click" ); + equals( evenObj.originalEvent.type, "click", "beforeActivate triggered by click" ); }); test('beforeload', function() { diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index d605b2d48..8508f0adb 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -28,13 +28,13 @@ $.widget( "ui.tabs", { options: { activate: null, beforeload: null, + beforeActivate: null, cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } collapsible: false, disabled: false, event: "click", fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } - load: null, - select: null + load: null }, _create: function() { @@ -363,8 +363,8 @@ $.widget( "ui.tabs", { $li.hasClass( "ui-state-disabled" ) || // tab is already loading $li.hasClass( "ui-state-processing" ) || - // allow canceling by select event - self._trigger( "select", event, self._ui( el, $show[ 0 ] ) ) === false ) { + // allow canceling by beforeActivate event + self._trigger( "beforeActivate", event, self._ui( el, $show[ 0 ] ) ) === false ) { el.blur(); return; } @@ -927,10 +927,11 @@ if ( $.uiBackCompat !== false ) { }; }( jQuery, jQuery.ui.tabs.prototype ) ); - // show event + // show and select event (function( $, prototype ) { $.extend( prototype.options, { - show: null + show: null, + select: null }); var _trigger = prototype._trigger; @@ -939,7 +940,9 @@ if ( $.uiBackCompat !== false ) { if ( !ret ) { return false; } - if ( type === "activate" ) { + if ( type === "beforeActivate" ) { + ret = _trigger.call( this, "select", event, data ); + } else if ( type === "activate" ) { ret = _trigger.call( this, "show", event, data ); } }; -- cgit v1.2.3 From b5e67861bb552c39bb76b13382a052701e4649e5 Mon Sep 17 00:00:00 2001 From: Richard Worth Date: Mon, 28 Mar 2011 11:13:53 -0400 Subject: Autocomplete: changed autoFocus default back to false. Reverts #7042 - Autocomplete: Default autoFocus to true --- tests/unit/autocomplete/autocomplete_defaults.js | 2 +- ui/jquery.ui.autocomplete.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/autocomplete/autocomplete_defaults.js b/tests/unit/autocomplete/autocomplete_defaults.js index e2196ea9e..dd5007089 100644 --- a/tests/unit/autocomplete/autocomplete_defaults.js +++ b/tests/unit/autocomplete/autocomplete_defaults.js @@ -4,7 +4,7 @@ var autocomplete_defaults = { appendTo: "body", - autoFocus: true, + autoFocus: false, delay: 300, disabled: false, minLength: 1, diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index ca06fff65..1685c0652 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -22,7 +22,7 @@ $.widget( "ui.autocomplete", { defaultElement: "", options: { appendTo: "body", - autoFocus: true, + autoFocus: false, delay: 300, minLength: 1, position: { -- cgit v1.2.3 From ec4825535dc0654721df60f56b7bc7e73b61bfcc Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 28 Mar 2011 11:15:29 -0400 Subject: Accordion: Removed empty ticket test file. --- tests/unit/accordion/accordion_tickets.js | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 tests/unit/accordion/accordion_tickets.js diff --git a/tests/unit/accordion/accordion_tickets.js b/tests/unit/accordion/accordion_tickets.js deleted file mode 100644 index b301051da..000000000 --- a/tests/unit/accordion/accordion_tickets.js +++ /dev/null @@ -1,5 +0,0 @@ -(function( $ ) { - -module( "accordion: tickets", accordionSetupTeardown() ); - -}( jQuery ) ); -- cgit v1.2.3 From ec0a9cc4544a124043aa618dc599d42e750b9e67 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 28 Mar 2011 11:20:03 -0400 Subject: Removed empty ticket test files. --- tests/unit/accordion/accordio.html | 1 - tests/unit/accordion/accordion.html | 1 - tests/unit/autocomplete/autocomplete.html | 1 - tests/unit/autocomplete/autocomplete_tickets.js | 14 -------------- 4 files changed, 17 deletions(-) delete mode 100644 tests/unit/autocomplete/autocomplete_tickets.js diff --git a/tests/unit/accordion/accordio.html b/tests/unit/accordion/accordio.html index 4e4df72b4..69d445d1d 100644 --- a/tests/unit/accordion/accordio.html +++ b/tests/unit/accordion/accordio.html @@ -51,7 +51,6 @@ - diff --git a/tests/unit/accordion/accordion.html b/tests/unit/accordion/accordion.html index 65fd16ab6..be9ceb05d 100644 --- a/tests/unit/accordion/accordion.html +++ b/tests/unit/accordion/accordion.html @@ -54,7 +54,6 @@ - - - -

              jQuery UI Accordion Test Suite

              -

              -
              -

              -
                -
                - -
                -

                There is one obvious advantage:

                -
                -

                - You've seen it coming! -
                - Buy now and get nothing for free! -
                - Well, at least no free beer. Perhaps a bear, if you can afford it. -

                -
                -

                Now that you've got...

                -
                -

                - your bear, you have to admit it! -
                - No, we aren't selling bears. -

                -

                - We could talk about renting one. -

                -
                -

                Rent one bear, ...

                -
                -

                - get two for three beer. -

                -

                - And now, for something completely different. -

                -
                -
                - - - -
                -
                - Accordion Header 1 -
                -
                - Accordion Content 1 -
                -
                - Accordion Header 2 -
                -
                - Accordion Content 2 -
                -
                - Accordion Header 3 -
                -
                - Accordion Content 3 -
                -
                - -
                - - diff --git a/tests/unit/accordion/accordion_deprecated.html b/tests/unit/accordion/accordion_deprecated.html new file mode 100644 index 000000000..879b5fe12 --- /dev/null +++ b/tests/unit/accordion/accordion_deprecated.html @@ -0,0 +1,161 @@ + + + + + jQuery UI Accordion Test Suite + + + + + + + + + + + + + + + + + + + + + + + + + +

                jQuery UI Accordion Test Suite

                +

                +
                +

                +
                  +
                  + +
                  +

                  There is one obvious advantage:

                  +
                  +

                  + You've seen it coming! +
                  + Buy now and get nothing for free! +
                  + Well, at least no free beer. Perhaps a bear, if you can afford it. +

                  +
                  +

                  Now that you've got...

                  +
                  +

                  + your bear, you have to admit it! +
                  + No, we aren't selling bears. +

                  +

                  + We could talk about renting one. +

                  +
                  +

                  Rent one bear, ...

                  +
                  +

                  + get two for three beer. +

                  +

                  + And now, for something completely different. +

                  +
                  +
                  + + + +
                  +
                  + Accordion Header 1 +
                  +
                  + Accordion Content 1 +
                  +
                  + Accordion Header 2 +
                  +
                  + Accordion Content 2 +
                  +
                  + Accordion Header 3 +
                  +
                  + Accordion Content 3 +
                  +
                  + +
                  + + diff --git a/tests/unit/position/positio.html b/tests/unit/position/positio.html deleted file mode 100644 index 156235d7b..000000000 --- a/tests/unit/position/positio.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - jQuery UI Position Test Suite - - - - - - - - - - - - - - - - -

                  jQuery UI Position Test Suite

                  -

                  -
                  -

                  -
                    -
                  - - - -
                  -
                  -
                  -
                  -
                  - -
                  -
                  -
                  -
                  - -
                  -
                  -
                  -
                  -
                  -
                  -
                  - -
                  - -
                  -
                  -
                  - - - diff --git a/tests/unit/position/position_deprecated.html b/tests/unit/position/position_deprecated.html new file mode 100644 index 000000000..156235d7b --- /dev/null +++ b/tests/unit/position/position_deprecated.html @@ -0,0 +1,60 @@ + + + + + jQuery UI Position Test Suite + + + + + + + + + + + + + + + + +

                  jQuery UI Position Test Suite

                  +

                  +
                  +

                  +
                    +
                  + + + +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + + + -- cgit v1.2.3 From fdedf1616d03b07c84045a3fd57d3cff073c6148 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 4 Apr 2011 10:11:19 -0400 Subject: Tabs: Test cleanup. --- tests/unit/tabs/tabs.html | 193 +++++++++++++++++----------------- tests/unit/tabs/tabs_core.js | 49 +++++---- tests/unit/tabs/tabs_deprecated.html | 196 ++++++++++++++++++----------------- 3 files changed, 227 insertions(+), 211 deletions(-) diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 02fbfe3bb..36e30517e 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -1,33 +1,32 @@ - + - + jQuery UI Tabs Test Suite - + - + - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + - + @@ -45,80 +44,86 @@

                  -
                    -
                  - +
                    -
                    -
                      -
                    • 1
                    • -
                    • 2
                    • -
                    • 3
                    • -
                    -
                    -
                    -
                    -
                    -
                    - -
                    -
                    -
                    -
                    -
                    -
                      -
                    • 1
                    • -
                    -
                    -
                    -
                    -
                      -
                    • 1
                    • -
                    -
                      -
                    1. 1
                    2. -
                    -
                    -
                    -
                      -
                    1. 1
                    2. -
                    +
                    +
                      +
                    • 1
                    • +
                    • 2
                    • +
                    • 3
                    • +
                    +
                    +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    +
                    +
                      +
                    • 1
                    • +
                    +
                    +
                    + +
                    +
                      +
                    • 1
                    • +
                    +
                      +
                    1. 1
                    2. +
                    +
                    + +
                    +
                      +
                    1. 1
                    2. +
                    +
                      +
                    • 1
                    • +
                    +
                    + +
                    +
                    +
                      +
                      +
                      + +
                      +
                      -
                      -
                      -
                        -
                        -
                        -
                        -
                          -
                        • 1 -
                            -
                          • 3
                          • -
                          • 4
                          • -
                          -
                        • -
                        • 2
                        • -
                        -
                        -
                        -
                        -
                        -
                          -
                        • 1
                        • -
                        • 2
                        • -
                        -
                        -
                        -
                        -
                        +
                      • +
                      • 2
                      • + +
                        +
                        + + +
                        +
                          +
                        • 1
                        • +
                        • 2
                        • +
                        +
                        +
                        +
                        + + diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 7d9074819..25e54c3ee 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -1,28 +1,33 @@ -/* - * tabs_core.js - */ -var el; +(function( $ ) { -(function($) { +module( "tabs: core" ); -module("tabs: core"); - -test('navigation markup', function() { - el = $('#tabs3').tabs(); - ok($('#tabs3-list').hasClass('ui-tabs-nav'), 'custom markup; allow list to be any descendant'); - el.tabs('destroy'); - - el = $('#tabs4').tabs(); - ok($('#tabs4-list').hasClass('ui-tabs-nav'), 'first list found becomes nav - ul'); - el.tabs('destroy'); +test( "markup structure", function() { + expect( 3 ); + var el = $( "#tabs1" ).tabs(); + ok( el.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); + ok( el.find( "ul" ).hasClass( "ui-tabs-nav" ), "list item is .ui-tabs-nav" ); + equal( el.find( ".ui-tabs-panel" ).length, 3, + ".ui-tabs-panel elements exist, correct number" ); +}); - el = $('#tabs4a').tabs(); - ok($('#tabs4a-list').hasClass('ui-tabs-nav'), 'first list found becomes nav - ol'); - el.tabs('destroy'); +$.each({ + "deep ul": "#tabs3", + "multiple lists, ul first": "#tabs4", + "multiple lists, ol first": "#tabs5", + "empty list": "#tabs6" +}, function( type, selector ) { + test( "markup structure: " + type, function() { + expect( 2 ); + var el = $( selector ).tabs(); + ok( el.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); + ok( $( selector + "-list" ).hasClass( "ui-tabs-nav" ), + "list item is .ui-tabs-nav" ); + }); +}); - el = $('#tabs5').tabs(); - ok($('#tabs5-list').hasClass('ui-tabs-nav'), 'empty list can be used'); - el.tabs('destroy'); +test( "accessibility", function() { + // TODO: add tests }); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/tabs/tabs_deprecated.html b/tests/unit/tabs/tabs_deprecated.html index 3b927675c..f886a9b7b 100644 --- a/tests/unit/tabs/tabs_deprecated.html +++ b/tests/unit/tabs/tabs_deprecated.html @@ -1,31 +1,31 @@ - + - + jQuery UI Tabs Test Suite - + - - - - - + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + - + -

                        jQuery UI Tabs Test Suite (deprecated)

                        +

                        jQuery UI Tabs Test Suite

                        -
                          -
                        - +
                          -
                          -
                            -
                          • 1
                          • -
                          • 2
                          • -
                          • 3
                          • -
                          -
                          -
                          -
                          -
                          -
                          - -
                          -
                          -
                          -
                          -
                          -
                            -
                          • 1
                          • -
                          -
                          -
                          -
                          -
                            -
                          • 1
                          • -
                          -
                            -
                          1. 1
                          2. -
                          -
                          -
                          -
                            -
                          1. 1
                          2. -
                          +
                          +
                            +
                          • 1
                          • +
                          • 2
                          • +
                          • 3
                          • +
                          +
                          +
                          +
                          +
                          + +
                          + +
                          +
                          +
                          + +
                          +
                          +
                            +
                          • 1
                          • +
                          +
                          +
                          + +
                          +
                            +
                          • 1
                          • +
                          +
                            +
                          1. 1
                          2. +
                          +
                          + +
                          +
                            +
                          1. 1
                          2. +
                          +
                            +
                          • 1
                          • +
                          +
                          + +
                          +
                          +
                            +
                            +
                            + +
                            +
                            -
                            -
                            -
                              -
                              -
                              -
                              -
                                -
                              • 1 -
                                  -
                                • 3
                                • -
                                • 4
                                • -
                                -
                              • -
                              • 2
                              • -
                              -
                              -
                              -
                              -
                              -
                                -
                              • 1
                              • -
                              • 2
                              • -
                              -
                              -
                              -
                              -
                              + +
                            • 2
                            • + +
                              +
                              +
                              + +
                              +
                                +
                              • 1
                              • +
                              • 2
                              • +
                              +
                              +
                              +
                              + + -- cgit v1.2.3 From 632e6c76185664f1831c2f008e40f9057ef91bd0 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 4 Apr 2011 11:22:32 -0400 Subject: Tabs: Pass appropriate data for beforeActivate event. Fixes #7136 - Tabs: Rename select event to beforeActivate. --- tests/unit/tabs/tabs.html | 9 ++++ tests/unit/tabs/tabs_deprecated.html | 9 ++++ tests/unit/tabs/tabs_events.js | 69 +++++++++++++++++--------- ui/jquery.ui.tabs.js | 93 ++++++++++++++++++++---------------- 4 files changed, 117 insertions(+), 63 deletions(-) diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 36e30517e..3d1c78040 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -26,6 +26,15 @@ + + - - - - - - - - - -

                              #4551 - Sortable connectWith fails if item is floated

                              - -
                              -
                              1
                              -
                              2
                              -
                              3
                              -
                              4
                              -
                              5
                              -
                              6
                              -
                              7
                              -
                              8
                              -
                              9
                              -
                              10
                              -
                              11
                              -
                              12
                              -
                              - -
                              -
                              - -
                              -
                              12
                              -
                              14
                              -
                              - - - diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index 8356eeb9f..131fb50d0 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -614,6 +614,10 @@ $.widget("ui.sortable", $.ui.mouse, { for (var i = this.items.length - 1; i >= 0; i--){ var item = this.items[i]; + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; if (!fast) { -- cgit v1.2.3 From d573a92bebf881d6ad68e4e128b5f534e047ae0c Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 7 Apr 2011 13:53:20 -0400 Subject: Tabs: Added tests for aria-controls attribute being assigned on init. --- tests/unit/tabs/tabs.html | 3 ++- tests/unit/tabs/tabs_core.js | 29 +++++++++++++++++++++++------ tests/unit/tabs/tabs_deprecated.html | 3 ++- tests/unit/tabs/tabs_deprecated.js | 4 ++-- tests/unit/tabs/tabs_events.js | 8 ++++---- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 3d1c78040..c800894ff 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -72,7 +72,8 @@
                            • 1
                            • 2
                            • 3
                            • -
                            • 4
                            • +
                            • 4
                            • +
                            • 5
                            • diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 25e54c3ee..30d58c254 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -4,10 +4,10 @@ module( "tabs: core" ); test( "markup structure", function() { expect( 3 ); - var el = $( "#tabs1" ).tabs(); - ok( el.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); - ok( el.find( "ul" ).hasClass( "ui-tabs-nav" ), "list item is .ui-tabs-nav" ); - equal( el.find( ".ui-tabs-panel" ).length, 3, + var element = $( "#tabs1" ).tabs(); + ok( element.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); + ok( element.find( "ul" ).hasClass( "ui-tabs-nav" ), "list item is .ui-tabs-nav" ); + equal( element.find( ".ui-tabs-panel" ).length, 3, ".ui-tabs-panel elements exist, correct number" ); }); @@ -19,13 +19,30 @@ $.each({ }, function( type, selector ) { test( "markup structure: " + type, function() { expect( 2 ); - var el = $( selector ).tabs(); - ok( el.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); + var element = $( selector ).tabs(); + ok( element.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); ok( $( selector + "-list" ).hasClass( "ui-tabs-nav" ), "list item is .ui-tabs-nav" ); }); }); +test( "aria-controls", function() { + expect( 7 ); + var element = $( "#tabs1" ).tabs(), + tabs = element.find( ".ui-tabs-nav a" ); + tabs.each(function() { + var tab = $( this ); + equal( tab.attr( "href" ).substring( 1 ), tab.attr( "aria-controls" ) ); + }); + + element = $( "#tabs2" ).tabs(); + tabs = element.find( ".ui-tabs-nav a" ); + equal( tabs.eq( 0 ).attr( "aria-controls" ), "colon:test" ); + equal( tabs.eq( 1 ).attr( "aria-controls" ), "inline-style" ); + ok( /^ui-tabs-\d+$/.test( tabs.eq( 2 ).attr( "aria-controls" ) ), "generated id" ); + equal( tabs.eq( 3 ).attr( "aria-controls" ), "custom-id" ); +}); + test( "accessibility", function() { // TODO: add tests }); diff --git a/tests/unit/tabs/tabs_deprecated.html b/tests/unit/tabs/tabs_deprecated.html index b50cebebc..54e0c39d6 100644 --- a/tests/unit/tabs/tabs_deprecated.html +++ b/tests/unit/tabs/tabs_deprecated.html @@ -71,7 +71,8 @@
                            • 1
                            • 2
                            • 3
                            • -
                            • 4
                            • +
                            • 4
                            • +
                            • 5
                            • diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index c6549fd50..c3116989e 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -11,7 +11,7 @@ test( "panel ids", function() { equal( ui.panel.attr( "id" ), "∫ßáö_Սե", "from title attribute" ); event.preventDefault(); }); - element.tabs( "option", "active", 3 ); + element.tabs( "option", "active", 4 ); element.one( "tabsbeforeload", function( event, ui ) { ok( /^ui-tabs-\d+$/.test( ui.panel.attr( "id" ) ), "generated id" ); @@ -329,7 +329,7 @@ test( "length", function() { expect( 2 ); equals( $( "#tabs1" ).tabs().tabs( "length" ), 3, "basic tabs" ); - equals( $( "#tabs2" ).tabs().tabs( "length" ), 4, "ajax tabs with missing panels" ); + equals( $( "#tabs2" ).tabs().tabs( "length" ), 5, "ajax tabs with missing panels" ); }); test( "url", function() { diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index 2e54407de..28925a2b9 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -163,10 +163,10 @@ test( "beforeLoad", function() { strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); equals( ui.panel.html(), "", "panel html" ); event.preventDefault(); - tabs_state( element, 1, 0, 0, 0 ); + tabs_state( element, 1, 0, 0, 0, 0 ); }); element.tabs( "option", "active", 2 ); - tabs_state( element, 0, 0, 1, 0 ); + tabs_state( element, 0, 0, 1, 0, 0 ); equals( panel.html(), "", "panel html after" ); // click, change panel content @@ -184,10 +184,10 @@ test( "beforeLoad", function() { strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); ui.panel.html( "

                              testing

                              " ); event.preventDefault(); - tabs_state( element, 0, 0, 1, 0 ); + tabs_state( element, 0, 0, 1, 0, 0 ); }); element.find( ".ui-tabs-nav a" ).eq( 3 ).click(); - tabs_state( element, 0, 0, 0, 1 ); + tabs_state( element, 0, 0, 0, 1, 0 ); equals( panel.html(), "

                              testing

                              ", "panel html after" ); }); -- cgit v1.2.3 From 9d9e1ce12225302776497d0a98271e904740b4fd Mon Sep 17 00:00:00 2001 From: jzaefferer Date: Fri, 8 Apr 2011 15:31:06 +0200 Subject: Adding popup utility prototype to visual menu tests --- tests/visual/menu/popup.html | 159 +++++++++++++++++++++++++++++++++++++++++++ tests/visual/menu/popup.js | 107 +++++++++++++++++++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 tests/visual/menu/popup.html create mode 100644 tests/visual/menu/popup.js diff --git a/tests/visual/menu/popup.html b/tests/visual/menu/popup.html new file mode 100644 index 000000000..de9796133 --- /dev/null +++ b/tests/visual/menu/popup.html @@ -0,0 +1,159 @@ + + + + Visual Test for Popup Utility + + + + + + + + + + + + + + + + + + +
                              +
                              + + +
                              + +
                              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                              NameRelease YearAverage Rating
                              Red Hot Chili Peppers: Funky Monks19933.6 + +
                              Rod Stewart: Storyteller 1984-199119913.1
                              Stevie Ray Vaughan and Double Trouble: Live at the El Mocambo 198319913.9
                              Spike and Mike's Sick & Twisted Festival of Animation19972.6
                              + +
                              + Log: +
                              +
                              + + + diff --git a/tests/visual/menu/popup.js b/tests/visual/menu/popup.js new file mode 100644 index 000000000..dea1452e0 --- /dev/null +++ b/tests/visual/menu/popup.js @@ -0,0 +1,107 @@ +/* + * jQuery UI popup utility + */ +(function($) { + +var idIncrement = 0; + +$.widget( "ui.popup", { + options: { + position: { + my: "left top", + at: "left bottom" + } + }, + _create: function() { + if ( !this.options.trigger ) { + this.options.trigger = this.element.prev(); + } + + if ( !this.element.attr( "id" ) ) { + this.element.attr( "id", "ui-popup-" + idIncrement++ ); + this.generatedId = true; + } + + if ( !this.element.attr( "role" ) ) { + // TODO alternatives to tooltip are dialog and menu, all three aren't generic popups + this.element.attr( "role", "tooltip" ); + this.generatedRole = true; + } + + this.options.trigger + .attr( "aria-haspop", true ) + .attr( "aria-owns", this.element.attr( "id" ) ); + + this.element + .addClass("ui-popup") + this._close(); + + this._bind(this.options.trigger, { + click: function( event ) { + event.stopPropagation(); + event.preventDefault(); + this._open( event ); + } + }); + + this._bind({ + keyup: function( event ) { + if (event.keyCode == $.ui.keyCode.ESCAPE && this.element.is( ":visible" )) { + this._close( event ); + this.options.trigger.focus(); + } + } + }); + + this._bind(document, { + click: function( event ) { + if (this.open && !$(event.target).closest(".ui-popup").length) { + this._close( event ); + } + } + }) + }, + + _destroy: function() { + this.element + .show() + .removeClass( "ui-popup" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-expanded" ); + + if ( this.generatedId ) { + this.element.removeAttr( "id" ); + } + if ( this.generatedRole ) { + this.element.removeAttr( "role" ); + } + }, + + _open: function( event ) { + var position = $.extend( {}, { + of: this.options.trigger + }, this.options.position ); + + this.element + .show() + .attr( "aria-hidden", false ) + .attr( "aria-expanded", true ) + .position( position ) + .focus(); + this.open = true; + this._trigger( "open", event ); + }, + + _close: function( event ) { + this.element + .hide() + .attr( "aria-hidden", true ) + .attr( "aria-expanded", false ); + this.open = false; + this._trigger( "close", event ); + } + + +}); + +}(jQuery)); -- cgit v1.2.3 From 3b77ac654b079a3098d12cca04d2397bb3863b85 Mon Sep 17 00:00:00 2001 From: Kyle Florence Date: Fri, 8 Apr 2011 16:55:14 -0700 Subject: Progressbar: hide valueDiv when value is 0. Fixes #7231 - valueDiv should be hidden when value is at 0% --- ui/jquery.ui.progressbar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/jquery.ui.progressbar.js b/ui/jquery.ui.progressbar.js index cb89a1c39..e3b25cfd7 100644 --- a/ui/jquery.ui.progressbar.js +++ b/ui/jquery.ui.progressbar.js @@ -93,6 +93,7 @@ $.widget( "ui.progressbar", { } this.valueDiv + .toggle( value > this.min ) .toggleClass( "ui-corner-right", value === this.options.max ) .width( percentage.toFixed(0) + "%" ); this.element.attr( "aria-valuenow", value ); -- cgit v1.2.3 From 7272f3bdef8ebc81cc51d3749fdeb4696eda666a Mon Sep 17 00:00:00 2001 From: Richard Worth Date: Sat, 9 Apr 2011 14:53:15 -0400 Subject: Progressbar: Added unit test for #7231 - valueDiv should be hidden when value is at 0% --- tests/unit/progressbar/progressbar_options.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/progressbar/progressbar_options.js b/tests/unit/progressbar/progressbar_options.js index 70ad7abab..230c939ab 100644 --- a/tests/unit/progressbar/progressbar_options.js +++ b/tests/unit/progressbar/progressbar_options.js @@ -10,6 +10,23 @@ test("{ value : 0 }, default", function() { same( 0, $("#progressbar").progressbar("value") ); }); +// Ticket #7231 - valueDiv should be hidden when value is at 0% +test( "value: visibility of valueDiv", function() { + expect( 5 ); + var element = $( "#progressbar" ).progressbar({ + value: 0 + }); + ok( element.children( ".ui-progressbar-value" ).is( ":hidden" ), "valueDiv hidden when value is initialized at 0" ); + element.progressbar( "value", 1 ); + ok( element.children( ".ui-progressbar-value" ).is( ":visible" ), "valueDiv visible when value is set to 1" ); + element.progressbar( "value", 100 ); + ok( element.children( ".ui-progressbar-value" ).is( ":visible" ), "valueDiv visible when value is set to 100" ); + element.progressbar( "value", 0 ); + ok( element.children( ".ui-progressbar-value" ).is( ":hidden" ), "valueDiv hidden when value is set to 0" ); + element.progressbar( "value", -1 ); + ok( element.children( ".ui-progressbar-value" ).is( ":hidden" ), "valueDiv hidden when value set to -1 (normalizes to 0)" ); +}); + test("{ value : 5 }", function() { $("#progressbar").progressbar({ value: 5 -- cgit v1.2.3 From 64f13b661a571806bdfb181d1ef511ac9e2771b3 Mon Sep 17 00:00:00 2001 From: Richard Worth Date: Sat, 9 Apr 2011 15:54:17 -0400 Subject: Resizable: Added a non-visible yet non-transparent (apparently) no-request background-image on resizable handles to work around an IE bug. Fixed #7233 - Resizable: resizable handles fail to work in IE if transparent and content overlaps --- themes/base/jquery.ui.resizable.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.resizable.css b/themes/base/jquery.ui.resizable.css index eeb547b9f..6a258d702 100644 --- a/themes/base/jquery.ui.resizable.css +++ b/themes/base/jquery.ui.resizable.css @@ -8,7 +8,12 @@ * http://docs.jquery.com/UI/Resizable#theming */ .ui-resizable { position: relative;} -.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; + /* http://bugs.jqueryui.com/ticket/7233 + - Resizable: resizable handles fail to work in IE if transparent and content overlaps + */ + background-image:url(about:blank); +} .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } -- cgit v1.2.3 From 08b6a2b5189f62c62a0ee725629087b445f308d7 Mon Sep 17 00:00:00 2001 From: Richard Worth Date: Sat, 9 Apr 2011 23:12:53 -0400 Subject: Resizable: use background-image:url(data:) instead of background-image:url(about:blank) as it's shorter and safer. Thanks @epascarello . Better fixes #7233 - Resizable: resizable handles fail to work in IE if transparent and content overlaps --- themes/base/jquery.ui.resizable.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.resizable.css b/themes/base/jquery.ui.resizable.css index 6a258d702..05f855a71 100644 --- a/themes/base/jquery.ui.resizable.css +++ b/themes/base/jquery.ui.resizable.css @@ -12,7 +12,7 @@ /* http://bugs.jqueryui.com/ticket/7233 - Resizable: resizable handles fail to work in IE if transparent and content overlaps */ - background-image:url(about:blank); + background-image:url(data:); } .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } -- cgit v1.2.3 From ccac8cd4920f7d79d046fb34589d0dbb48d31551 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 11 Apr 2011 10:08:32 -0400 Subject: Tabs: Updated references to .ui-tabs-selected to use .ui-tabs-active. --- demos/demos.css | 8 ++++---- demos/tabs/bottom.html | 1 - demos/tabs/vertical.html | 2 +- tests/unit/tabs/tabs_deprecated.js | 2 +- tests/unit/tabs/tabs_options.js | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/demos/demos.css b/demos/demos.css index 2d2ce1fc8..f5f2dbe64 100644 --- a/demos/demos.css +++ b/demos/demos.css @@ -320,10 +320,10 @@ div.demo-description { #widget-docs .ui-tabs-nav li a:hover, #widget-docs .ui-tabs-nav li a:active { font-size:14px; padding:4px 1.2em 3px; color:#fff; } -#widget-docs .ui-tabs-nav li.ui-tabs-selected a:link, -#widget-docs .ui-tabs-nav li.ui-tabs-selected a:visited, -#widget-docs .ui-tabs-nav li.ui-tabs-selected a:hover, -#widget-docs .ui-tabs-nav li.ui-tabs-selected a:active { color:#e6820E; } +#widget-docs .ui-tabs-nav li.ui-tabs-active a:link, +#widget-docs .ui-tabs-nav li.ui-tabs-active a:visited, +#widget-docs .ui-tabs-nav li.ui-tabs-active a:hover, +#widget-docs .ui-tabs-nav li.ui-tabs-active a:active { color:#e6820E; } #widget-docs .ui-tabs-panel { padding:20px 9px; font-size:12px; line-height:1.4; color:#000; } diff --git a/demos/tabs/bottom.html b/demos/tabs/bottom.html index 4f0e3c2a4..68ccac902 100644 --- a/demos/tabs/bottom.html +++ b/demos/tabs/bottom.html @@ -23,7 +23,6 @@ .tabs-bottom .ui-tabs-panel { height: 140px; overflow: auto; } .tabs-bottom .ui-tabs-nav { position: absolute !important; left: 0; bottom: 0; right:0; padding: 0 0.2em 0.2em 0; } .tabs-bottom .ui-tabs-nav li { margin-top: -2px !important; margin-bottom: 1px !important; border-top: none; border-bottom-width: 1px; } - .ui-tabs-selected { margin-top: -3px !important; } diff --git a/demos/tabs/vertical.html b/demos/tabs/vertical.html index 4ddb5c9c9..690f03420 100644 --- a/demos/tabs/vertical.html +++ b/demos/tabs/vertical.html @@ -20,7 +20,7 @@ .ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 12em; } .ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; } .ui-tabs-vertical .ui-tabs-nav li a { display:block; } - .ui-tabs-vertical .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; } + .ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; } .ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 40em;} diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index c3116989e..c221868fc 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -130,7 +130,7 @@ test('selected', function() { el.tabs('destroy'); el = $('#tabs1').tabs({ selected: -1 }); equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected'); - equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be selected' ); + equals( $('li.ui-tabs-active', el).length, 0, 'no tab should be selected' ); equals( $('div:hidden', '#tabs1').length, 3, 'all panels should be hidden' ); el.tabs('destroy'); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index 49c77521e..ce556fc3e 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -55,7 +55,7 @@ test('active', function() { el.tabs('destroy'); el.tabs({ active: false }); equals(el.tabs('option', 'active'), false, 'should be false for all tabs deactive'); - equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be active' ); + equals( $('li.ui-tabs-active', el).length, 0, 'no tab should be active' ); equals( $('div:hidden', '#tabs1').length, 3, 'all panels should be hidden' ); el.tabs('destroy'); -- cgit v1.2.3 From a3370064d85b30d89846efde00e461a2d493dfda Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 11 Apr 2011 10:39:33 -0400 Subject: Tabs: Update ajax demo to use beforeLoad event instead of deprecated ajaxOptions option. --- demos/tabs/ajax.html | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/demos/tabs/ajax.html b/demos/tabs/ajax.html index 284de57f9..407914589 100644 --- a/demos/tabs/ajax.html +++ b/demos/tabs/ajax.html @@ -12,13 +12,12 @@ + - - - - - - - - - - - - -
                              - - - - - -

                              Default

                              - - - -

                              - -
                              - -

                              Drilldown

                              - - - -
                              - -

                              - -
                              - -

                              Flyout / nested

                              - - - -
                              - - - - diff --git a/tests/static/menu/default.html b/tests/static/menu/default.html deleted file mode 100644 index dd1e0ba7d..000000000 --- a/tests/static/menu/default.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - Menu Static Test : Default - - - - - - - - - - - - - - -- cgit v1.2.3 From 03132f93fc961fc23771b1784ada7d46c104dea1 Mon Sep 17 00:00:00 2001 From: Hans Hillen Date: Wed, 20 Apr 2011 20:15:26 +0200 Subject: Fix menubar escape key + minor css fix --- tests/visual/menu/menubar.html | 4 ++-- tests/visual/menu/menubar.js | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/visual/menu/menubar.html b/tests/visual/menu/menubar.html index 1b4b331f6..d2185e97c 100644 --- a/tests/visual/menu/menubar.html +++ b/tests/visual/menu/menubar.html @@ -55,9 +55,9 @@ .ui-menubar .ui-button { float: left; font-weight: normal; border-top-width: 0 !important; border-bottom-width: 0 !important; margin: 0; outline: none; } .ui-menubar .ui-menubar-link { border-right: 1px dashed transparent; border-left: 1px dashed transparent; } - .ui-menubar, .ui-menubar { + .ui-menubar { list-style: none; - margin-left: 0; + margin: 0; padding-left: 0; } diff --git a/tests/visual/menu/menubar.js b/tests/visual/menu/menubar.js index e6f6ab069..13a508811 100644 --- a/tests/visual/menu/menubar.js +++ b/tests/visual/menu/menubar.js @@ -38,7 +38,6 @@ $.widget("ui.menubar", { var menu = $(this); if (menu.is(":hidden")) return; - event.stopPropagation(); switch (event.keyCode) { case $.ui.keyCode.LEFT: self._left(event); @@ -119,7 +118,7 @@ $.widget("ui.menubar", { } }) self._bind({ - keyup: function(event) { + keydown: function(event) { if (event.keyCode == $.ui.keyCode.ESCAPE && self.open) { if (self.active.menu("left", event) !== true) { var active = self.active; -- cgit v1.2.3 From 5a5ce51aad3a60093905e0c93e7503aca2d59688 Mon Sep 17 00:00:00 2001 From: maggiewachs Date: Thu, 21 Apr 2011 11:30:29 -0400 Subject: Removed duplicate selector reference --- themes/base/jquery.ui.menu.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/themes/base/jquery.ui.menu.css b/themes/base/jquery.ui.menu.css index a700d2895..d5d802821 100644 --- a/themes/base/jquery.ui.menu.css +++ b/themes/base/jquery.ui.menu.css @@ -29,8 +29,6 @@ padding:.2em .4em; line-height:1.5; zoom:1; -} -.ui-menu .ui-menu-item a { font-weight: normal; } .ui-menu .ui-menu-item a.ui-state-focus, -- cgit v1.2.3 From 49556995d2dffb7b57169bc2462aef5e17370d41 Mon Sep 17 00:00:00 2001 From: maggiewachs Date: Thu, 21 Apr 2011 14:29:45 -0400 Subject: Set menu item link top padding to px (in place of em); this fixes the issue where the submenu jumped when mousing over the parent item's menu icon. --- themes/base/jquery.ui.menu.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.menu.css b/themes/base/jquery.ui.menu.css index d5d802821..ed4b4a13a 100644 --- a/themes/base/jquery.ui.menu.css +++ b/themes/base/jquery.ui.menu.css @@ -26,7 +26,7 @@ .ui-menu .ui-menu-item a { text-decoration:none; display:block; - padding:.2em .4em; + padding: 2px .4em; line-height:1.5; zoom:1; font-weight: normal; -- cgit v1.2.3 From 45c418d29327c83a54c06553ad0f7505ede64cbb Mon Sep 17 00:00:00 2001 From: Hans Hillen Date: Fri, 22 Apr 2011 20:22:16 +0200 Subject: Added focusin & focusout handler for menubar --- tests/visual/menu/menubar.js | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/tests/visual/menu/menubar.js b/tests/visual/menu/menubar.js index 13a508811..0fd5d0ecd 100644 --- a/tests/visual/menu/menubar.js +++ b/tests/visual/menu/menubar.js @@ -47,14 +47,8 @@ $.widget("ui.menubar", { self._right(event); event.preventDefault(); break; - case $.ui.keyCode.TAB: - self.open= false; - break; }; - }).blur(function( event ) { - if (!self.open) - self._close( event ); - }); + }) }); items.each(function() { var input = $(this), @@ -107,19 +101,9 @@ $.widget("ui.menubar", { }; }); - self._bind(document, { - click: function(event) { - if (self.open) { - var menubar = $(event.target).closest(".ui-menubar"); - if (!menubar.length || menubar.get(0) !== self.element.get(0)) { - self._close(); - } - } - } - }) self._bind({ keydown: function(event) { - if (event.keyCode == $.ui.keyCode.ESCAPE && self.open) { + if (event.keyCode == $.ui.keyCode.ESCAPE) { if (self.active.menu("left", event) !== true) { var active = self.active; self.active.blur(); @@ -127,6 +111,14 @@ $.widget("ui.menubar", { active.prev().focus(); } } + }, + focusout : function( event ) { + self.closeTimer = setTimeout(function() { + self._close( event ); + }, 100); + }, + focusin :function( event ) { + clearTimeout(self.closeTimer); } }); }, @@ -158,7 +150,7 @@ $.widget("ui.menubar", { .removeAttr("aria-hidden", "true") .removeAttr("aria-expanded", "false") .removeAttr("tabindex") - .unbind("keydown", "blur") + .unbind("keydown", "blur", "focusin", "focusout") ; }, @@ -168,11 +160,7 @@ $.widget("ui.menubar", { this.active.menu("closeAll").hide().attr("aria-hidden", "true").attr("aria-expanded", "false"); this.active.prev().removeClass("ui-state-active").removeAttr("tabIndex"); this.active = null; - var self = this; - // delay for the next focus event to see it as still "open" - self.timer = setTimeout(function() { - self.open = false; - }, 13); + self.open = false; }, _open: function(event, menu) { @@ -185,8 +173,6 @@ $.widget("ui.menubar", { this.active.menu("closeAll").hide().attr("aria-hidden", "true").attr("aria-expanded", "false"); this.active.prev().removeClass("ui-state-active"); } - clearTimeout(this.timer); - this.open = true; // set tabIndex -1 to have the button skipped on shift-tab when menu is open (it gets focus) var button = menu.prev().addClass("ui-state-active").attr("tabIndex", -1); this.active = menu.show().position({ @@ -196,8 +182,10 @@ $.widget("ui.menubar", { }) .removeAttr("aria-hidden").attr("aria-expanded", "true") .menu("focus", event, menu.children("li").first()) - .focus(); - + .focus() + .focusin() + ; + self.open = true; }, _prev: function( event, button ) { -- cgit v1.2.3 From dc7410f55b4398891e278efec110d1ed5e6f1f92 Mon Sep 17 00:00:00 2001 From: Hans Hillen Date: Fri, 22 Apr 2011 20:22:56 +0200 Subject: Prevent branch menuitems from firing select event --- ui/jquery.ui.menu.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 0a06fe0b5..f9ad84fda 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -108,9 +108,16 @@ $.widget("ui.menu", { event.preventDefault(); break; case $.ui.keyCode.ENTER: - self.select( event ); + if (self.active.children("a[aria-haspopup='true']").length) { + if (self.right( event )) { + event.stopImmediatePropagation(); + } + } + else { + self.select( event ); + event.stopImmediatePropagation(); + } event.preventDefault(); - event.stopImmediatePropagation(); break; case $.ui.keyCode.ESCAPE: if ( self.left( event ) ) { -- cgit v1.2.3 From 42e11d8e41253571d67a7e1a62caa9376771c292 Mon Sep 17 00:00:00 2001 From: Hans Hillen Date: Fri, 22 Apr 2011 23:11:53 +0200 Subject: Fix error for Escape key on menubar item --- tests/visual/menu/menubar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/visual/menu/menubar.js b/tests/visual/menu/menubar.js index 0fd5d0ecd..8c0bd4904 100644 --- a/tests/visual/menu/menubar.js +++ b/tests/visual/menu/menubar.js @@ -104,7 +104,7 @@ $.widget("ui.menubar", { self._bind({ keydown: function(event) { if (event.keyCode == $.ui.keyCode.ESCAPE) { - if (self.active.menu("left", event) !== true) { + if (self.active && self.active.menu("left", event) !== true) { var active = self.active; self.active.blur(); self._close( event ); -- cgit v1.2.3 From 84f918ae44ed6002d67f568ecffbb262f1e9e115 Mon Sep 17 00:00:00 2001 From: Hans Hillen Date: Fri, 22 Apr 2011 23:14:04 +0200 Subject: Fix collapsing submenus issue --- ui/jquery.ui.menu.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index f9ad84fda..8738f5c27 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -283,17 +283,15 @@ $.widget("ui.menu", { }, _open: function(submenu) { + clearTimeout(this.timer); this.element.find(".ui-menu").not(submenu.parents()).hide().attr("aria-hidden", "true"); - var position = $.extend({}, { of: this.active }, $.type(this.options.position) == "function" ? this.options.position(this.active) : this.options.position ); - submenu.show().removeAttr("aria-hidden").attr("aria-expanded", "true").position(position); - this.active.find(">a:first").addClass("ui-state-active"); }, -- cgit v1.2.3 From 54795b56509cb5562fb9385ae59f10552df5cd78 Mon Sep 17 00:00:00 2001 From: Hans Hillen Date: Sat, 23 Apr 2011 17:31:25 +0200 Subject: change self.open to this.open --- tests/visual/menu/menubar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/visual/menu/menubar.js b/tests/visual/menu/menubar.js index 8c0bd4904..8e2d51e30 100644 --- a/tests/visual/menu/menubar.js +++ b/tests/visual/menu/menubar.js @@ -160,7 +160,7 @@ $.widget("ui.menubar", { this.active.menu("closeAll").hide().attr("aria-hidden", "true").attr("aria-expanded", "false"); this.active.prev().removeClass("ui-state-active").removeAttr("tabIndex"); this.active = null; - self.open = false; + this.open = false; }, _open: function(event, menu) { @@ -185,7 +185,7 @@ $.widget("ui.menubar", { .focus() .focusin() ; - self.open = true; + this.open = true; }, _prev: function( event, button ) { -- cgit v1.2.3 From f7d2fdbab8f6e0ea37fb02f9458489990305ff2f Mon Sep 17 00:00:00 2001 From: Hans Hillen Date: Sat, 23 Apr 2011 17:35:03 +0200 Subject: removed unbind for focusin and focusout --- tests/visual/menu/menubar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/visual/menu/menubar.js b/tests/visual/menu/menubar.js index 8e2d51e30..cc3258d4a 100644 --- a/tests/visual/menu/menubar.js +++ b/tests/visual/menu/menubar.js @@ -150,7 +150,7 @@ $.widget("ui.menubar", { .removeAttr("aria-hidden", "true") .removeAttr("aria-expanded", "false") .removeAttr("tabindex") - .unbind("keydown", "blur", "focusin", "focusout") + .unbind("keydown", "blur") ; }, -- cgit v1.2.3 From 6326da3fdb29ea4f40e39bc06abf14cde5ba5c8c Mon Sep 17 00:00:00 2001 From: jzaefferer Date: Sat, 23 Apr 2011 17:36:52 +0200 Subject: Menu: Add ui-state-active to parent item when submenu item receives focus. --- ui/jquery.ui.menu.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 3b48d29a3..7c0c8d3d3 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -229,6 +229,9 @@ $.widget("ui.menu", { // need to remove the attribute before adding it for the screenreader to pick up the change // see http://groups.google.com/group/jquery-a11y/msg/929e0c1e8c5efc8f this.element.removeAttr("aria-activedescendant").attr("aria-activedescendant", self.itemId) + + // highlight active parent menu item, if any + this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"); self.timer = setTimeout(function() { self._close(); @@ -277,8 +280,6 @@ $.widget("ui.menu", { ); submenu.show().position(position); - - this.active.find(">a:first").addClass("ui-state-active"); }, closeAll: function() { -- cgit v1.2.3 From c4c36e557ef2b3450bc365708064f7314bc6fdc4 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 25 Apr 2011 08:10:39 -0400 Subject: Accordion, Autocomplete, Tabs: Separate callbacks and options in the defaults. --- tests/unit/accordion/accordion_defaults.js | 6 +++- .../accordion/accordion_defaults_deprecated.js | 8 ++++- tests/unit/autocomplete/autocomplete_defaults.js | 41 ++++++++++++---------- tests/unit/tabs/tabs_defaults.js | 8 +++-- tests/unit/tabs/tabs_defaults_deprecated.js | 22 ++++++------ ui/jquery.ui.accordion.js | 11 +++++- ui/jquery.ui.autocomplete.js | 11 +++++- ui/jquery.ui.tabs.js | 8 +++-- 8 files changed, 77 insertions(+), 38 deletions(-) diff --git a/tests/unit/accordion/accordion_defaults.js b/tests/unit/accordion/accordion_defaults.js index 95a478057..847a394e2 100644 --- a/tests/unit/accordion/accordion_defaults.js +++ b/tests/unit/accordion/accordion_defaults.js @@ -10,6 +10,10 @@ commonWidgetTests( "accordion", { icons: { "activeHeader": "ui-icon-triangle-1-s", "header": "ui-icon-triangle-1-e" - } + }, + + // callbacks + activate: null, + beforeActivate: null } }); diff --git a/tests/unit/accordion/accordion_defaults_deprecated.js b/tests/unit/accordion/accordion_defaults_deprecated.js index b90b472e2..bdc059d10 100644 --- a/tests/unit/accordion/accordion_defaults_deprecated.js +++ b/tests/unit/accordion/accordion_defaults_deprecated.js @@ -16,6 +16,12 @@ commonWidgetTests( "accordion", { "headerSelected": "ui-icon-triangle-1-s" }, navigation: false, - navigationFilter: function() {} + navigationFilter: function() {}, + + // callbacks + activate: null, + beforeActivate: null, + change: null, + changestart: null } }); diff --git a/tests/unit/autocomplete/autocomplete_defaults.js b/tests/unit/autocomplete/autocomplete_defaults.js index dd5007089..05897b848 100644 --- a/tests/unit/autocomplete/autocomplete_defaults.js +++ b/tests/unit/autocomplete/autocomplete_defaults.js @@ -1,19 +1,24 @@ -/* - * autocomplete_defaults.js - */ +commonWidgetTests( "autocomplete", { + defaults: { + appendTo: "body", + autoFocus: false, + delay: 300, + disabled: false, + minLength: 1, + position: { + my: "left top", + at: "left bottom", + collision: "none" + }, + source: null, -var autocomplete_defaults = { - appendTo: "body", - autoFocus: false, - delay: 300, - disabled: false, - minLength: 1, - position: { - my: "left top", - at: "left bottom", - collision: "none" - }, - source: null -}; - -commonWidgetTests('autocomplete', { defaults: autocomplete_defaults }); + // callbacks + change: null, + close: null, + focus: null, + open: null, + response: null, + search: null, + select: null + } +}); diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index e15d618de..0750094e4 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -1,13 +1,15 @@ commonWidgetTests( "tabs", { defaults: { - activate: null, active: null, - beforeLoad: null, - beforeActivate: null, collapsible: false, disabled: false, event: "click", fx: null, + + // callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, load: null } }); diff --git a/tests/unit/tabs/tabs_defaults_deprecated.js b/tests/unit/tabs/tabs_defaults_deprecated.js index 2d9772c6d..84f7de073 100644 --- a/tests/unit/tabs/tabs_defaults_deprecated.js +++ b/tests/unit/tabs/tabs_defaults_deprecated.js @@ -1,26 +1,28 @@ commonWidgetTests( "tabs", { defaults: { - activate: null, active: null, - add: null, ajaxOptions: null, - beforeLoad: null, - beforeActivate: null, cache: false, collapsible: false, cookie: null, - disable: null, disabled: false, - enable: null, event: "click", fx: null, idPrefix: "ui-tabs-", - load: null, panelTemplate: "
                              ", + spinner: "Loading…", + tabTemplate: "
                            • #{label}
                            • ", + + // callbacks + activate: null, + add: null, + beforeActivate: null, + beforeLoad: null, + disable: null, + enable: null, + load: null, remove: null, select: null, - show: null, - spinner: "Loading…", - tabTemplate: "
                            • #{label}
                            • " + show: null } }); diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 455c66a28..0cc1f9e2a 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -25,7 +25,11 @@ $.widget( "ui.accordion", { icons: { activeHeader: "ui-icon-triangle-1-s", header: "ui-icon-triangle-1-e" - } + }, + + // callbacks + activate: null, + beforeActivate: null }, _create: function() { @@ -649,6 +653,11 @@ if ( $.uiBackCompat !== false ) { // change events (function( $, prototype ) { + $.extend( prototype.options, { + change: null, + changestart: null + }); + var _trigger = prototype._trigger; prototype._trigger = function( type, event, data ) { var ret = _trigger.apply( this, arguments ); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 1685c0652..526eb3869 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -30,7 +30,16 @@ $.widget( "ui.autocomplete", { at: "left bottom", collision: "none" }, - source: null + source: null, + + // callbacks + change: null, + close: null, + focus: null, + open: null, + response: null, + search: null, + select: null }, pending: 0, diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 699c1a5ee..82d3f186d 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -26,13 +26,15 @@ function getNextListId() { $.widget( "ui.tabs", { options: { - activate: null, active: null, - beforeActivate: null, - beforeLoad: null, collapsible: false, event: "click", fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } + + // callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, load: null }, -- cgit v1.2.3 From 325ee6e87133dd2a507c820dd3c356e3b897a3ec Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 25 Apr 2011 14:04:30 -0400 Subject: Widget: define a null default for the create callback. --- tests/unit/accordion/accordion_defaults.js | 3 +- .../accordion/accordion_defaults_deprecated.js | 3 +- tests/unit/autocomplete/autocomplete_defaults.js | 1 + tests/unit/button/button_defaults.js | 25 ++++---- tests/unit/dialog/dialog_defaults.js | 67 +++++++++++----------- tests/unit/dialog/dialog_options.js | 4 +- tests/unit/menu/menu_defaults.js | 21 ++++--- tests/unit/progressbar/progressbar_defaults.js | 19 +++--- tests/unit/slider/slider_defaults.js | 37 ++++++------ tests/unit/spinner/spinner_defaults.js | 29 +++++----- tests/unit/tabs/tabs_defaults.js | 1 + tests/unit/tabs/tabs_defaults_deprecated.js | 1 + tests/unit/tooltip/tooltip_defaults.js | 27 +++++---- tests/unit/widget/widget_core.js | 3 + ui/jquery.ui.widget.js | 5 +- 15 files changed, 125 insertions(+), 121 deletions(-) diff --git a/tests/unit/accordion/accordion_defaults.js b/tests/unit/accordion/accordion_defaults.js index 847a394e2..9aa58e650 100644 --- a/tests/unit/accordion/accordion_defaults.js +++ b/tests/unit/accordion/accordion_defaults.js @@ -14,6 +14,7 @@ commonWidgetTests( "accordion", { // callbacks activate: null, - beforeActivate: null + beforeActivate: null, + create: null } }); diff --git a/tests/unit/accordion/accordion_defaults_deprecated.js b/tests/unit/accordion/accordion_defaults_deprecated.js index bdc059d10..3f45a1f10 100644 --- a/tests/unit/accordion/accordion_defaults_deprecated.js +++ b/tests/unit/accordion/accordion_defaults_deprecated.js @@ -22,6 +22,7 @@ commonWidgetTests( "accordion", { activate: null, beforeActivate: null, change: null, - changestart: null + changestart: null, + create: null } }); diff --git a/tests/unit/autocomplete/autocomplete_defaults.js b/tests/unit/autocomplete/autocomplete_defaults.js index 05897b848..ac83eaea4 100644 --- a/tests/unit/autocomplete/autocomplete_defaults.js +++ b/tests/unit/autocomplete/autocomplete_defaults.js @@ -15,6 +15,7 @@ commonWidgetTests( "autocomplete", { // callbacks change: null, close: null, + create: null, focus: null, open: null, response: null, diff --git a/tests/unit/button/button_defaults.js b/tests/unit/button/button_defaults.js index b81fa7cbb..96c7e5bfa 100644 --- a/tests/unit/button/button_defaults.js +++ b/tests/unit/button/button_defaults.js @@ -1,15 +1,14 @@ -/* - * button_defaults.js - */ +commonWidgetTests( "button", { + defaults: { + disabled: null, + icons: { + primary: null, + secondary: null + }, + label: null, + text: true, -var button_defaults = { - disabled: null, - text: true, - label: null, - icons: { - primary: null, - secondary: null + // callbacks + create: null } -}; - -commonWidgetTests('button', { defaults: button_defaults }); +}); diff --git a/tests/unit/dialog/dialog_defaults.js b/tests/unit/dialog/dialog_defaults.js index 612fd58c8..9f2e4c6a8 100644 --- a/tests/unit/dialog/dialog_defaults.js +++ b/tests/unit/dialog/dialog_defaults.js @@ -1,35 +1,34 @@ -/* - * dialog_defaults.js - */ +commonWidgetTests( "dialog", { + defaults: { + autoOpen: true, + buttons: {}, + closeOnEscape: true, + closeText: 'close', + disabled: false, + dialogClass: '', + draggable: true, + height: 'auto', + hide: null, + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: 'center', + at: 'center', + of: window, + collision: 'fit', + using: $.ui.dialog.prototype.options.position.using + }, + resizable: true, + show: null, + stack: true, + title: '', + width: 300, + zIndex: 1000, -var dialog_defaults = { - autoOpen: true, - buttons: {}, - closeOnEscape: true, - closeText: 'close', - disabled: false, - dialogClass: '', - draggable: true, - height: 'auto', - hide: null, - maxHeight: false, - maxWidth: false, - minHeight: 150, - minWidth: 150, - modal: false, - position: { - my: 'center', - at: 'center', - of: window, - collision: 'fit', - using: $.ui.dialog.prototype.options.position.using - }, - resizable: true, - show: null, - stack: true, - title: '', - width: 300, - zIndex: 1000 -}; - -commonWidgetTests('dialog', { defaults: dialog_defaults }); + // callbacks + create: null + } +}); diff --git a/tests/unit/dialog/dialog_options.js b/tests/unit/dialog/dialog_options.js index fb8dea775..5705da079 100644 --- a/tests/unit/dialog/dialog_options.js +++ b/tests/unit/dialog/dialog_options.js @@ -180,7 +180,7 @@ test("height", function() { expect(3); el = $('
                              ').dialog(); - equals(dlg().height(), dialog_defaults.minHeight, "default height"); + equals(dlg().height(), 150, "default height"); el.remove(); el = $('
                              ').dialog({ height: 237 }); @@ -431,7 +431,7 @@ test("width", function() { expect(3); el = $('
                              ').dialog(); - equals(dlg().width(), dialog_defaults.width, "default width"); + equals(dlg().width(), 300, "default width"); el.remove(); el = $('
                              ').dialog({width: 437 }); diff --git a/tests/unit/menu/menu_defaults.js b/tests/unit/menu/menu_defaults.js index 58122fea2..dd182ca09 100644 --- a/tests/unit/menu/menu_defaults.js +++ b/tests/unit/menu/menu_defaults.js @@ -1,13 +1,12 @@ -/* - * menu_defaults.js - */ +commonWidgetTests( "menu", { + defaults: { + disabled: false, + position: { + my: "left top", + at: "right top" + }, -var menu_defaults = { - disabled: false, - position: { - my: "left top", - at: "right top" + // callbacks + create: null } -}; - -commonWidgetTests('menu', { defaults: menu_defaults }); +}); diff --git a/tests/unit/progressbar/progressbar_defaults.js b/tests/unit/progressbar/progressbar_defaults.js index 925510871..3856e31a0 100644 --- a/tests/unit/progressbar/progressbar_defaults.js +++ b/tests/unit/progressbar/progressbar_defaults.js @@ -1,11 +1,10 @@ -/* - * progressbar_defaults.js - */ +commonWidgetTests( "progressbar", { + defaults: { + disabled: false, + value: 0, + max: 100, -var progressbar_defaults = { - disabled: false, - value: 0, - max: 100 -}; - -commonWidgetTests('progressbar', { defaults: progressbar_defaults }); + //callbacks + create: null + } +}); diff --git a/tests/unit/slider/slider_defaults.js b/tests/unit/slider/slider_defaults.js index 76e5da8ea..03f2a4f8e 100644 --- a/tests/unit/slider/slider_defaults.js +++ b/tests/unit/slider/slider_defaults.js @@ -1,20 +1,19 @@ -/* - * slider_defaults.js - */ +commonWidgetTests( "slider", { + defaults: { + animate: false, + cancel: function() {}, + delay: 0, + disabled: false, + distance: 0, + max: 100, + min: 0, + orientation: 'horizontal', + range: false, + step: 1, + value: 0, + values: null, -var slider_defaults = { - animate: false, - cancel: function() {}, - delay: 0, - disabled: false, - distance: 0, - max: 100, - min: 0, - orientation: 'horizontal', - range: false, - step: 1, - value: 0, - values: null -}; - -commonWidgetTests('slider', { defaults: slider_defaults }); + // callbacks + create: null + } +}); diff --git a/tests/unit/spinner/spinner_defaults.js b/tests/unit/spinner/spinner_defaults.js index 0389ab169..f6081b1f3 100644 --- a/tests/unit/spinner/spinner_defaults.js +++ b/tests/unit/spinner/spinner_defaults.js @@ -1,16 +1,15 @@ -/* - * spinner_defaults.js - */ +commonWidgetTests( "spinner", { + defaults: { + disabled: false, + incremental: true, + max: null, + min: null, + numberformat: null, + page: 10, + step: null, + value: null, -var spinner_defaults = { - disabled: false, - incremental: true, - max: null, - min: null, - numberformat: null, - page: 10, - step: null, - value: null -}; - -commonWidgetTests('spinner', { defaults: spinner_defaults }); + // callbacks + create: null + } +}); diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index 0750094e4..52b6f8a71 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -10,6 +10,7 @@ commonWidgetTests( "tabs", { activate: null, beforeActivate: null, beforeLoad: null, + create: null, load: null } }); diff --git a/tests/unit/tabs/tabs_defaults_deprecated.js b/tests/unit/tabs/tabs_defaults_deprecated.js index 84f7de073..1a56297e9 100644 --- a/tests/unit/tabs/tabs_defaults_deprecated.js +++ b/tests/unit/tabs/tabs_defaults_deprecated.js @@ -18,6 +18,7 @@ commonWidgetTests( "tabs", { add: null, beforeActivate: null, beforeLoad: null, + create: null, disable: null, enable: null, load: null, diff --git a/tests/unit/tooltip/tooltip_defaults.js b/tests/unit/tooltip/tooltip_defaults.js index 419d7a085..c1fc49f1a 100644 --- a/tests/unit/tooltip/tooltip_defaults.js +++ b/tests/unit/tooltip/tooltip_defaults.js @@ -1,16 +1,15 @@ -/* - * tooltip_defaults.js - */ +commonWidgetTests( "tooltip", { + defaults: { + disabled: false, + items: "[title]", + content: $.ui.tooltip.prototype.options.content, + position: { + my: "left center", + at: "right center", + offset: "15 0" + }, -var tooltip_defaults = { - disabled: false, - items: "[title]", - content: $.ui.tooltip.prototype.options.content, - position: { - my: "left center", - at: "right center", - offset: "15 0" + // callbacks + create: null } -}; - -commonWidgetTests('tooltip', { defaults: tooltip_defaults }); +}); diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 5a6717560..b1c27b104 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -202,6 +202,7 @@ test( "merge multiple option arguments", function() { $.widget( "ui.testWidget", { _create: function() { same( this.options, { + create: null, disabled: false, option1: "value1", option2: "value2", @@ -249,6 +250,7 @@ test( "._getCreateOptions()", function() { }, _create: function() { same( this.options, { + create: null, disabled: false, option1: "override1", option2: "value2", @@ -418,6 +420,7 @@ test( ".option() - getter", function() { var options = div.testWidget( "option" ); same( options, { + create: null, disabled: false, foo: "bar", baz: 5, diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 27d08ccd2..55b9f7984 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -155,7 +155,10 @@ $.Widget.prototype = { widgetEventPrefix: "", defaultElement: "
                              ", options: { - disabled: false + disabled: false, + + // callbacks + create: null }, _createWidget: function( options, element ) { element = $( element || this.defaultElement || this )[ 0 ]; -- cgit v1.2.3 From 60d4e0ae42efd780e6147f981c55bdfeafdfaa54 Mon Sep 17 00:00:00 2001 From: Scott González Date: Wed, 27 Apr 2011 10:42:21 -0400 Subject: Class Animation: Use .attr( "class" ) instead of .attr( "className" ) and adjust the queueing logic for jQuery 1.6 compatibility. Fixes #7275 - $.effects.animateClass broken in jQuery 1.6." --- ui/jquery.effects.core.js | 49 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/ui/jquery.effects.core.js b/ui/jquery.effects.core.js index 573cb2554..581fb0861 100644 --- a/ui/jquery.effects.core.js +++ b/ui/jquery.effects.core.js @@ -234,12 +234,12 @@ $.effects.animateClass = function( value, duration, easing, callback ) { easing = null; } - return this.queue( 'fx', function() { + return this.queue(function() { var that = $( this ), originalStyleAttr = that.attr( 'style' ) || ' ', originalStyle = filterStyles( getElementStyles.call( this ) ), newStyle, - className = that.attr( 'className' ); + className = that.attr( 'class' ); $.each( classAnimationActions, function(i, action) { if ( value[ action ] ) { @@ -247,32 +247,31 @@ $.effects.animateClass = function( value, duration, easing, callback ) { } }); newStyle = filterStyles( getElementStyles.call( this ) ); - that.attr( 'className', className ); - - that.animate( styleDifference( originalStyle, newStyle ), duration, easing, function() { - $.each( classAnimationActions, function( i, action ) { - if ( value[ action ] ) { - that[ action + 'Class' ]( value[ action ] ); + that.attr( 'class', className ); + + that.animate( styleDifference( originalStyle, newStyle ), { + queue: false, + duration: duration, + easing: easing, + complete: function() { + $.each( classAnimationActions, function( i, action ) { + if ( value[ action ] ) { + that[ action + 'Class' ]( value[ action ] ); + } + }); + // work around bug in IE by clearing the cssText before setting it + if ( typeof that.attr( 'style' ) == 'object' ) { + that.attr( 'style' ).cssText = ''; + that.attr( 'style' ).cssText = originalStyleAttr; + } else { + that.attr( 'style', originalStyleAttr ); } - }); - // work around bug in IE by clearing the cssText before setting it - if ( typeof that.attr( 'style' ) == 'object' ) { - that.attr( 'style' ).cssText = ''; - that.attr( 'style' ).cssText = originalStyleAttr; - } else { - that.attr( 'style', originalStyleAttr ); - } - if ( callback ) { - callback.apply( this, arguments ); + if ( callback ) { + callback.apply( this, arguments ); + } + $.dequeue( this ); } }); - - // $.animate adds a function to the end of the queue - // but we want it at the front - var queue = $.queue( this ), - anim = queue.splice( queue.length - 1, 1 )[ 0 ]; - queue.splice( 1, 0, anim ); - $.dequeue( this ); }); }; -- cgit v1.2.3 From a1473042b44e2fb1415ad4d996397d315ddb462c Mon Sep 17 00:00:00 2001 From: David Petersen Date: Thu, 28 Apr 2011 09:07:54 -0400 Subject: Tabs: Make sure prototype.url is defined before trying to shim it --- ui/jquery.ui.tabs.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 82d3f186d..d4ee9984f 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -628,6 +628,14 @@ $.extend( $.ui.tabs, { // DEPRECATED if ( $.uiBackCompat !== false ) { + + // url method + (function( $, prototype ) { + prototype.url = function( index, url ) { + this.anchors.eq( index ).attr( "href", url ); + }; + }( jQuery, jQuery.ui.tabs.prototype ) ); + // ajaxOptions and cache options (function( $, prototype ) { $.extend( prototype.options, { @@ -638,7 +646,7 @@ if ( $.uiBackCompat !== false ) { var _create = prototype._create, _setOption = prototype._setOption, _destroy = prototype._destroy, - oldurl = prototype._url; + oldurl = prototype.url || $.noop; $.extend( prototype, { _create: function() { @@ -864,13 +872,6 @@ if ( $.uiBackCompat !== false ) { }; }( jQuery, jQuery.ui.tabs.prototype ) ); - // url method - (function( $, prototype ) { - prototype.url = function( index, url ) { - this.anchors.eq( index ).attr( "href", url ); - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); - // panel ids (idPrefix option + title attribute) (function( $, prototype ) { $.extend( prototype.options, { -- cgit v1.2.3 From abe4c37748628d17627493070abddbd8084b3b36 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sun, 17 Apr 2011 19:51:45 -0400 Subject: Tabs: simplify disabled logic --- ui/jquery.ui.tabs.js | 86 ++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index d4ee9984f..f73799f02 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -181,14 +181,7 @@ $.widget( "ui.tabs", { this.lis.addClass( "ui-state-default ui-corner-top" ); this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); - if ( !options.disabled.length ) { - options.disabled = false; - } - - // disable tabs - for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { - $( li ).toggleClass( "ui-state-disabled", $.inArray( i, options.disabled ) !== -1 ); - } + this._setupDisabled( options.disabled ); this._setupEvents( options.event ); @@ -260,6 +253,23 @@ $.widget( "ui.tabs", { .data( "destroy.tabs", true ); }, + _setupDisabled: function( disabled ) { + if ( $.isArray( disabled ) ) { + if ( !disabled.length ) { + disabled = false; + } else if ( disabled.length === this.anchors.length ) { + disabled = true; + } + } + + // disable tabs + for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { + $( li ).toggleClass( "ui-state-disabled", ( disabled === true || $.inArray( i, disabled ) !== -1 ) ); + } + + this.options.disabled = disabled; + }, + _setupFx: function( fx ) { // set up animations if ( fx ) { @@ -502,53 +512,37 @@ $.widget( "ui.tabs", { }, enable: function( index ) { + var disabled = this.options.disabled; + if ( index === undefined ) { - for ( var i = 0, len = this.lis.length; i < len; i++ ) { - this.enable( i ); + disabled = false; + } else { + index = this._getIndex( index ); + if ( $.isArray( disabled ) ) { + disabled = $.map( disabled, function( num ) { + return num !== index ? num : null; + }); + } else { + disabled = [ index ]; } - return this; } - index = this._getIndex( index ); - var o = this.options; - if ( !o.disabled || ($.isArray( o.disabled ) && $.inArray( index, o.disabled ) == -1 ) ) { - return; - } - - this.lis.eq( index ).removeClass( "ui-state-disabled" ); - o.disabled = this.lis.map( function( i ) { - return $(this).is( ".ui-state-disabled" ) ? i : null; - }).get(); - - if ( !o.disabled.length ) { - o.disabled = false; - } - - return this; + this._setupDisabled( disabled ); }, disable: function( index ) { + var disabled = this.options.disabled; + if ( index === undefined ) { - for ( var i = 0, len = this.lis.length; i < len; i++ ) { - this.disable( i ); - } - return this; - } - index = this._getIndex( index ); - var o = this.options; - if ( !o.disabled || ($.isArray( o.disabled ) && $.inArray( index, o.disabled ) == -1 ) ) { - this.lis.eq( index ).addClass( "ui-state-disabled" ); - - o.disabled = this.lis.map( function( i ) { - return $(this).is( ".ui-state-disabled" ) ? i : null; - }).get(); - - if ( o.disabled.length === this.anchors.length ) { - o.disabled = true; + disabled = true; + } else { + index = this._getIndex( index ); + if ( $.isArray( disabled ) ) { + disabled = $.merge( [ index ], disabled ).sort(); + } else { + disabled = [ index ]; } - } - - return this; + this._setupDisabled( disabled ); }, load: function( index, event ) { -- cgit v1.2.3 From 0e7769c66958a0f86ffda0209caa4039d96c79b2 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Sun, 17 Apr 2011 21:09:47 -0400 Subject: Tabs: enable/disable handle when current state already matches, fix error when disabled = true and enable gets called --- tests/unit/tabs/tabs_methods.js | 22 ++++++++++++++++++++-- ui/jquery.ui.tabs.js | 10 +++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index 7c72cd26d..bd28316c5 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -18,7 +18,7 @@ test('destroy', function() { }); test('enable', function() { - expect(8); + expect(12); el = $('#tabs1').tabs({ disabled: [ 0, 1 ] }); el.tabs("enable", 1); @@ -31,6 +31,18 @@ test('enable', function() { ok( !$('li.ui-state-disabled', el).length, 'enable all'); same(el.tabs('option', 'disabled'), false, 'update property'); + // enable one tab + el.tabs({ disabled: true }); + el.tabs("enable", 1); + ok( $('li:eq(1)', el).is(':not(.ui-state-disabled)'), 'remove class from li'); + same(el.tabs('option', 'disabled'), [ 0, 2 ], 'update property'); + + // all tabs already enabled + el.tabs({ disabled: false }); + el.tabs("enable", 1); + ok( !$('li.ui-state-disabled', el).length, 'enable all'); + same(el.tabs('option', 'disabled'), false, 'update property'); + el.tabs('destroy'); // enable all tabs one by one el.tabs({ disabled: [ 1, 2 ] }); @@ -43,7 +55,7 @@ test('enable', function() { }); test('disable', function() { - expect(12); + expect(14); // normal el = $('#tabs1').tabs(); @@ -61,6 +73,12 @@ test('disable', function() { same( $('li.ui-state-disabled', el).length, 3, 'disable all'); same(el.tabs('option', 'disabled'), true, 'set to true'); + // all tabs already disabled + el.tabs({ disabled: true }); + el.tabs("disable", 1); + ok( $('li.ui-state-disabled', el).length, 'disable all'); + same(el.tabs('option', 'disabled'), true, 'set to true'); + el.tabs("destroy"); // disable all tabs one by one el.tabs(); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index f73799f02..5c525b34a 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -513,6 +513,9 @@ $.widget( "ui.tabs", { enable: function( index ) { var disabled = this.options.disabled; + if ( disabled === false ) { + return; + } if ( index === undefined ) { disabled = false; @@ -523,7 +526,9 @@ $.widget( "ui.tabs", { return num !== index ? num : null; }); } else { - disabled = [ index ]; + disabled = $.map( this.lis, function( li, num ) { + return num !== index ? num : null; + }); } } this._setupDisabled( disabled ); @@ -531,6 +536,9 @@ $.widget( "ui.tabs", { disable: function( index ) { var disabled = this.options.disabled; + if ( disabled === true ) { + return; + } if ( index === undefined ) { disabled = true; -- cgit v1.2.3 From d819cdd3a92d9d152a33ce6aecbd5cd9737a3ade Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 28 Apr 2011 12:04:08 -0400 Subject: Tabs: Fixed disable method and cleaned up tests for enable and disable methods. --- tests/unit/tabs/tabs.html | 35 +++++++++ tests/unit/tabs/tabs_deprecated.html | 35 +++++++++ tests/unit/tabs/tabs_methods.js | 134 ++++++++++++++++------------------- ui/jquery.ui.tabs.js | 3 + 4 files changed, 136 insertions(+), 71 deletions(-) diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index bba0e8a58..3e38f5f25 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -46,6 +46,41 @@ }).get(); same( actual, expected ); } + + function tabs_disabled( tabs, state ) { + var expected = $.map( new Array( tabs.find ( ".ui-tabs-nav li" ).length ), function( _, index ) { + if ( typeof state === "boolean" ) { + return state ? 1 : 0; + } else { + return $.inArray( index, state ) !== -1 ? 1 : 0; + } + }); + + var internalState = tabs.tabs( "option", "disabled" ); + if ( internalState === false ) { + internalState = []; + } + if ( internalState === true ) { + internalState = $.map( new Array( tabs.find( ".ui-tabs-nav li" ).length ), function( _, index ) { + return index; + }); + } + + var actual = tabs.find( ".ui-tabs-nav li" ).map(function( index ) { + var tab = $( this ), + tabIsDisabled = tab.hasClass( "ui-state-disabled" ); + + if ( tabIsDisabled && $.inArray( index, internalState ) !== -1 ) { + return 1; + } + if ( !tabIsDisabled && $.inArray( index, internalState ) === -1 ) { + return 0; + } + return -1; // mixed state - invalid + }).get(); + same( tabs.tabs( "option", "disabled" ), state ); + same( actual, expected ); + } -- cgit v1.2.3 From 1bacdec6be7e9d543224c69344041aaccde059c0 Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 28 Apr 2011 21:35:04 -0400 Subject: Tabs: Cleaned up add and remove methods. --- tests/unit/tabs/tabs.html | 2 +- tests/unit/tabs/tabs_deprecated.html | 2 +- tests/unit/tabs/tabs_deprecated.js | 103 ++++++++++++++++++++++------------- ui/jquery.ui.tabs.js | 54 ++++++++++-------- 4 files changed, 96 insertions(+), 65 deletions(-) diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 3e38f5f25..565a0b427 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -34,7 +34,7 @@ panel = $( $.ui.tabs.prototype._sanitizeSelector( "#" + tab.find( "a" ).attr( "aria-controls" ) ) ), tabIsActive = tab.hasClass( "ui-state-active" ), - panelIsActive = panel.is( ":visible" ); + panelIsActive = panel.css( "display" ) !== "none"; if ( tabIsActive && panelIsActive ) { return 1; diff --git a/tests/unit/tabs/tabs_deprecated.html b/tests/unit/tabs/tabs_deprecated.html index aae11c33d..e71fea3d4 100644 --- a/tests/unit/tabs/tabs_deprecated.html +++ b/tests/unit/tabs/tabs_deprecated.html @@ -33,7 +33,7 @@ panel = $( $.ui.tabs.prototype._sanitizeSelector( "#" + tab.find( "a" ).attr( "aria-controls" ) ) ), tabIsActive = tab.hasClass( "ui-state-active" ), - panelIsActive = panel.is( ":visible" ); + panelIsActive = panel.css( "display" ) !== "none"; if ( tabIsActive && panelIsActive ) { return 1; diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index c221868fc..359847d14 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -247,42 +247,78 @@ test('select', function() { equals( evenObj.originalEvent.type, "click", "select triggered by click" ); }); -module("tabs (deprecated): methods"); - -test('add', function() { - expect(4); - - el = $('#tabs1').tabs(); - el.tabs('add', '#new', 'New'); - - var added = $('li:last', el).simulate('mouseover'); - ok(added.is('.ui-state-hover'), 'should add mouseover handler to added tab'); - added.simulate('mouseout'); - var other = $('li:first', el).simulate('mouseover'); - ok(other.is('.ui-state-hover'), 'should not remove mouseover handler from existing tab'); - other.simulate('mouseout'); +module( "tabs (deprecated): methods" ); + +test( "add", function() { + expect( 18 ); + + var element = $( "#tabs1" ).tabs(); + tabs_state( element, 1, 0, 0 ); + + // add without index + element.tabs( "add", "#new", "New" ); + tabs_state( element, 1, 0, 0, 0 ); + var tab = element.find( ".ui-tabs-nav li" ).last(), + anchor = tab.find( "a" ); + equals( tab.text(), "New", "label" ); + equals( anchor.attr( "href" ), "#new", "href" ); + equals( anchor.attr( "aria-controls" ), "new", "aria-controls" ); + ok( !tab.hasClass( "ui-state-hover" ), "not hovered" ); + anchor.simulate( "mouseover" ); + ok( tab.hasClass( "ui-state-hover" ), "hovered" ); + anchor.simulate( "click" ); + tabs_state( element, 0, 0, 0, 1 ); + + // add remote tab with index + element.tabs( "add", "data/test.html", "New Remote", 1 ); + tabs_state( element, 0, 0, 0, 0, 1 ); + tab = element.find( ".ui-tabs-nav li" ).eq( 1 ); + anchor = tab.find( "a" ); + equals( tab.text(), "New Remote", "label" ); + equals( anchor.attr( "href" ), "data/test.html", "href" ); + ok( /^ui-tabs-\d+$/.test( anchor.attr( "aria-controls" ) ), "aria controls" ); + ok( !tab.hasClass( "ui-state-hover" ), "not hovered" ); + anchor.simulate( "mouseover" ); + ok( tab.hasClass( "ui-state-hover" ), "hovered" ); + anchor.simulate( "click" ); + tabs_state( element, 0, 1, 0, 0, 0 ); + + // add to empty tab set + element = $( "
                                " ).tabs(); + equals( element.tabs( "option", "active" ), false, "active: false on init" ); + element.tabs( "add", "#first", "First" ); + tabs_state( element, 1 ); + equals( element.tabs( "option", "active" ), 0, "active: 0 after add" ); +}); - equals($('a', added).attr('href'), '#new', 'should not expand href to full url of current page'); +test( "#5069 - ui.tabs.add creates two tab panels when using a full URL", function() { + expect( 2 ); - ok(false, "missing test - untested code is broken code."); + var element = $( "#tabs2" ).tabs(); + equals( element.children( "div" ).length, element.find( ".ui-tabs-nav li" ).length ); + element.tabs( "add", "/new", "New" ); + equals( element.children( "div" ).length, element.find( ".ui-tabs-nav li" ).length ); }); -test('remove', function() { - expect(4); +test( "remove", function() { + expect( 8 ); - el = $('#tabs1').tabs(); + var element = $( "#tabs1" ).tabs({ active: 1 }); + tabs_state( element, 0, 1, 0 ); - el.tabs('remove', 0); - equals(el.tabs('length'), 2, 'remove tab'); - equals($('li a[href$="fragment-1"]', el).length, 0, 'remove associated list item'); - equals($('#fragment-1').length, 0, 'remove associated panel'); + element.tabs( "remove", 1 ); + tabs_state( element, 0, 1 ); + equals( element.tabs( "option", "active" ), 1 ); + equals( element.find( ".ui-tabs-nav li a[href$='fragment-2']" ).length, 0, + "remove correct list item" ); + equals( element.find( "#fragment-2" ).length, 0, "remove correct panel" ); - // TODO delete tab -> focus tab to right - // TODO delete last tab -> focus tab to left + element.tabs( "remove", 1 ); + tabs_state( element, 1 ); + equals( element.tabs( "option", "active"), 0 ); - el.tabs('select', 1); - el.tabs('remove', 1); - equals(el.tabs('option', 'selected'), 0, 'update selected property'); + element.tabs( "remove", 0 ); + equals( element.tabs( "option", "active" ), false ); }); test('select', function() { @@ -314,17 +350,6 @@ test('select', function() { equals(el.tabs('option', 'active'), 1, 'should select tab by id'); }); - -test('#5069 - ui.tabs.add creates two tab panels when using a full URL', function() { - // http://dev.jqueryui.com/ticket/5069 - expect(2); - - el = $('#tabs2').tabs(); - equals(el.children('div').length, el.find('> ul > li').length, 'After creation, number of panels should be equal to number of tabs'); - el.tabs('add', '/ajax_html_echo', 'Test'); - equals(el.children('div').length, el.find('> ul > li').length, 'After add, number of panels should be equal to number of tabs'); -}); - test( "length", function() { expect( 2 ); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 490ca71a3..7946cc667 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -826,33 +826,39 @@ if ( $.uiBackCompat !== false ) { index = this.anchors.length; } - var self = this, - o = this.options, - $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), - id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); + var options = this.options, + li = $( options.tabTemplate + .replace( /#\{href\}/g, url ) + .replace( /#\{label\}/g, label ) ), + id = !url.indexOf( "#" ) ? + url.replace( "#", "" ) : + this._tabId( li.find( "a" )[ 0 ] ); - $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); + li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); + li.find( "a" ).attr( "aria-controls", id ); // try to find an existing element before creating a new one - var $panel = self.element.find( "#" + id ); - if ( !$panel.length ) { - $panel = self._createPanel( id ); + var panel = this.element.find( "#" + id ); + if ( !panel.length ) { + panel = this._createPanel( id ); } - $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide(); + panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide(); if ( index >= this.lis.length ) { - $li.appendTo( this.list ); - $panel.appendTo( this.list[ 0 ].parentNode ); + li.appendTo( this.list ); + panel.appendTo( this.list[ 0 ].parentNode ); } else { - $li.insertBefore( this.lis[ index ] ); - $panel.insertBefore( this.panels[ index ] ); + li.insertBefore( this.lis[ index ] ); + panel.insertBefore( this.panels[ index ] ); } - - o.disabled = $.map( o.disabled, function( n, i ) { + options.disabled = $.map( options.disabled, function( n ) { return n >= index ? ++n : n; }); this.refresh(); + if ( this.lis.length === 1 && options.active === false ) { + this.option( "active", 0 ); + } this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); return this; @@ -860,27 +866,27 @@ if ( $.uiBackCompat !== false ) { prototype.remove = function( index ) { index = this._getIndex( index ); - var o = this.options, - $li = this.lis.eq( index ).remove(), - $panel = this.panels.eq( index ).remove(); + var options = this.options, + tab = this.lis.eq( index ).remove(), + panel = this.panels.eq( index ).remove(); // If selected tab was removed focus tab to the right or // in case the last tab was removed the tab to the left. - if ( $li.hasClass( "ui-tabs-active" ) && this.anchors.length > 1) { + if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 1) { this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); } - o.disabled = $.map( - $.grep( o.disabled, function(n, i) { - return n != index; + options.disabled = $.map( + $.grep( options.disabled, function( n ) { + return n !== index; }), - function( n, i ) { + function( n ) { return n >= index ? --n : n; }); this.refresh(); - this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); + this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) ); return this; }; }( jQuery, jQuery.ui.tabs.prototype ) ); -- cgit v1.2.3 From 468e66ae62026a4a8c2be9c06222decbbcde4285 Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 28 Apr 2011 22:12:59 -0400 Subject: Tabs: Added tests for add and remove events. --- tests/unit/tabs/tabs_deprecated.js | 53 +++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 359847d14..25877e69c 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -187,25 +187,6 @@ test('disable', function() { equals(uiObj.index, 1, 'contain index'); }); -test('add', function() { - - // TODO move to methods, not at all event related... - - var el = $('
                                  ').tabs(); - equals(el.tabs('option', 'selected'), -1, 'Initially empty, no selected tab'); - - el.tabs('add', '#test1', 'Test 1'); - equals(el.tabs('option', 'selected'), 0, 'First tab added should be auto selected'); - - el.tabs('add', '#test2', 'Test 2'); - equals(el.tabs('option', 'selected'), 0, 'Second tab added should not be auto selected'); - -}); - -test('remove', function() { - ok(false, "missing test - untested code is broken code."); -}); - test('show', function() { expect(5); @@ -250,12 +231,17 @@ test('select', function() { module( "tabs (deprecated): methods" ); test( "add", function() { - expect( 18 ); + expect( 27 ); var element = $( "#tabs1" ).tabs(); tabs_state( element, 1, 0, 0 ); // add without index + element.one( "tabsadd", function( event, ui ) { + equal( ui.index, 3, "ui.index" ); + equal( $( ui.tab ).text(), "New", "ui.tab" ); + equal( ui.panel.id, "new", "ui.panel" ); + }); element.tabs( "add", "#new", "New" ); tabs_state( element, 1, 0, 0, 0 ); var tab = element.find( ".ui-tabs-nav li" ).last(), @@ -270,6 +256,11 @@ test( "add", function() { tabs_state( element, 0, 0, 0, 1 ); // add remote tab with index + element.one( "tabsadd", function( event, ui ) { + equal( ui.index, 1, "ui.index" ); + equal( $( ui.tab ).text(), "New Remote", "ui.tab" ); + equal( ui.panel.id, $( ui.tab ).attr( "aria-controls" ), "ui.panel" ); + }); element.tabs( "add", "data/test.html", "New Remote", 1 ); tabs_state( element, 0, 0, 0, 0, 1 ); tab = element.find( ".ui-tabs-nav li" ).eq( 1 ); @@ -286,6 +277,11 @@ test( "add", function() { // add to empty tab set element = $( "
                                    " ).tabs(); equals( element.tabs( "option", "active" ), false, "active: false on init" ); + element.one( "tabsadd", function( event, ui ) { + equal( ui.index, 0, "ui.index" ); + equal( $( ui.tab ).text(), "First", "ui.tab" ); + equal( ui.panel.id, "first", "ui.panel" ); + }); element.tabs( "add", "#first", "First" ); tabs_state( element, 1 ); equals( element.tabs( "option", "active" ), 0, "active: 0 after add" ); @@ -301,11 +297,16 @@ test( "#5069 - ui.tabs.add creates two tab panels when using a full URL", functi }); test( "remove", function() { - expect( 8 ); + expect( 17 ); var element = $( "#tabs1" ).tabs({ active: 1 }); tabs_state( element, 0, 1, 0 ); + element.one( "tabsremove", function( event, ui ) { + equal( ui.index, -1, "ui.index" ); + equal( $( ui.tab ).text(), "2", "ui.tab" ); + equal( ui.panel.id, "fragment-2", "ui.panel" ); + }); element.tabs( "remove", 1 ); tabs_state( element, 0, 1 ); equals( element.tabs( "option", "active" ), 1 ); @@ -313,10 +314,20 @@ test( "remove", function() { "remove correct list item" ); equals( element.find( "#fragment-2" ).length, 0, "remove correct panel" ); + element.one( "tabsremove", function( event, ui ) { + equal( ui.index, -1, "ui.index" ); + equal( $( ui.tab ).text(), "3", "ui.tab" ); + equal( ui.panel.id, "fragment-3", "ui.panel" ); + }); element.tabs( "remove", 1 ); tabs_state( element, 1 ); equals( element.tabs( "option", "active"), 0 ); + element.one( "tabsremove", function( event, ui ) { + equal( ui.index, -1, "ui.index" ); + equal( $( ui.tab ).text(), "1", "ui.tab" ); + equal( ui.panel.id, "fragment-1", "ui.panel" ); + }); element.tabs( "remove", 0 ); equals( element.tabs( "option", "active" ), false ); }); -- cgit v1.2.3 From 5058ac3ce7a45c5823f4c108b0ae3ae45346d0f8 Mon Sep 17 00:00:00 2001 From: Richard Worth Date: Fri, 29 Apr 2011 07:00:58 -0400 Subject: Resizable: switch data: background image to valid image file, small 1px transparent gif. Fixed #7293 - Resizable: Chrome dev tools console shows GET data: undefined (undefined) --- themes/base/jquery.ui.resizable.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.resizable.css b/themes/base/jquery.ui.resizable.css index 05f855a71..2c1de870e 100644 --- a/themes/base/jquery.ui.resizable.css +++ b/themes/base/jquery.ui.resizable.css @@ -12,7 +12,7 @@ /* http://bugs.jqueryui.com/ticket/7233 - Resizable: resizable handles fail to work in IE if transparent and content overlaps */ - background-image:url(data:); + background-image:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=); } .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } -- cgit v1.2.3 From fe3b36b8efcabf3d1f1d60523cae87c69a882f27 Mon Sep 17 00:00:00 2001 From: adambaratz Date: Fri, 15 Apr 2011 07:51:56 -0700 Subject: Core: reuse tabindex value. Fixed #7257 - optimize :tabbable. --- ui/jquery.ui.core.js | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/ui/jquery.ui.core.js b/ui/jquery.ui.core.js index 51f6b71d7..8bcc4c441 100644 --- a/ui/jquery.ui.core.js +++ b/ui/jquery.ui.core.js @@ -174,6 +174,27 @@ $.each( [ "Width", "Height" ], function( i, name ) { }); // selectors +function focusable( element, isTabIndexNotNaN ) { + var nodeName = element.nodeName.toLowerCase(); + if ( "area" === nodeName ) { + var map = element.parentNode, + mapName = map.name, + img; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap=#" + mapName + "]" )[0]; + return !!img && visible( img ); + } + return ( /input|select|textarea|button|object/.test( nodeName ) + ? !element.disabled + : "a" == nodeName + ? element.href || isTabIndexNotNaN + : isTabIndexNotNaN) + // the element and all of its ancestors must be visible + && visible( element ); +} + function visible( element ) { return !$( element ).parents().andSelf().filter(function() { return $.curCSS( this, "visibility" ) === "hidden" || @@ -187,30 +208,13 @@ $.extend( $.expr[ ":" ], { }, focusable: function( element ) { - var nodeName = element.nodeName.toLowerCase(), - tabIndex = $.attr( element, "tabindex" ); - if ( "area" === nodeName ) { - var map = element.parentNode, - mapName = map.name, - img; - if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { - return false; - } - img = $( "img[usemap=#" + mapName + "]" )[0]; - return !!img && visible( img ); - } - return ( /input|select|textarea|button|object/.test( nodeName ) - ? !element.disabled - : "a" == nodeName - ? element.href || !isNaN( tabIndex ) - : !isNaN( tabIndex )) - // the element and all of its ancestors must be visible - && visible( element ); + return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); }, tabbable: function( element ) { - var tabIndex = $.attr( element, "tabindex" ); - return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" ); + var tabIndex = $.attr( element, "tabindex" ), + isTabIndexNaN = isNaN( tabIndex ); + return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); } }); -- cgit v1.2.3