aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Petersen <public@petersendidit.com>2011-03-26 22:14:17 -0400
committerDavid Petersen <public@petersendidit.com>2011-03-27 14:56:20 -0400
commit1e2d3145fff7cdeca61e62f95eb1e30c37e664c5 (patch)
tree2ffd09f0bfb1a18b01b89c08123ad8d84a0e89cd
parentf6e7b6c9f6b49e4c7ab648bd617fe724ce0fb417 (diff)
downloadjquery-ui-1e2d3145fff7cdeca61e62f95eb1e30c37e664c5.tar.gz
jquery-ui-1e2d3145fff7cdeca61e62f95eb1e30c37e664c5.zip
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
-rw-r--r--demos/tabs/ajax.html3
-rw-r--r--tests/unit/tabs/tabs_deprecated.js24
-rw-r--r--tests/unit/tabs/tabs_methods.js4
-rw-r--r--tests/unit/tabs/tabs_tickets.js37
-rwxr-xr-xui/jquery.ui.tabs.js87
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 = $('<div><ul><li><a href="#tab">Tab</a></li></ul><div id="tab"></div></div>')
- .appendTo('#main').tabs();
+ el = $('<div><ul><li><a href="#tab">Tab</a></li></ul><div id="tab"></div></div>');
+ 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" ) {
@@ -610,12 +611,8 @@ $.widget( "ui.tabs", {
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 );