diff options
author | Felix Nagel <info@felixnagel.com> | 2012-05-24 18:34:32 +0200 |
---|---|---|
committer | Felix Nagel <info@felixnagel.com> | 2012-05-24 18:34:32 +0200 |
commit | b30184d885329317b9dbd70835d2c4d154f98475 (patch) | |
tree | 445acc2481e8456211c3e893e7789fe4b5978791 /ui | |
parent | ec6d88fae464ffb432df6c8d2ed06ee9fa5b4dae (diff) | |
parent | a1f604eb453208c80ec17c42c7bb4e3a1c624102 (diff) | |
download | jquery-ui-b30184d885329317b9dbd70835d2c4d154f98475.tar.gz jquery-ui-b30184d885329317b9dbd70835d2c4d154f98475.zip |
Merge with master
Diffstat (limited to 'ui')
-rw-r--r-- | ui/i18n/jquery.ui.datepicker-eu.js | 18 | ||||
-rw-r--r-- | ui/jquery.effects.core.js | 12 | ||||
-rw-r--r-- | ui/jquery.ui.accordion.js | 14 | ||||
-rw-r--r-- | ui/jquery.ui.autocomplete.js | 112 | ||||
-rw-r--r-- | ui/jquery.ui.button.js | 11 | ||||
-rw-r--r-- | ui/jquery.ui.core.js | 79 | ||||
-rw-r--r-- | ui/jquery.ui.dialog.js | 24 | ||||
-rw-r--r-- | ui/jquery.ui.menu.js | 85 | ||||
-rw-r--r-- | ui/jquery.ui.mouse.js | 2 | ||||
-rw-r--r-- | ui/jquery.ui.resizable.js | 6 | ||||
-rw-r--r-- | ui/jquery.ui.slider.js | 5 | ||||
-rw-r--r-- | ui/jquery.ui.sortable.js | 3 | ||||
-rw-r--r-- | ui/jquery.ui.tabs.js | 267 | ||||
-rw-r--r-- | ui/jquery.ui.tooltip.js | 38 |
14 files changed, 425 insertions, 251 deletions
diff --git a/ui/i18n/jquery.ui.datepicker-eu.js b/ui/i18n/jquery.ui.datepicker-eu.js index 4c40eebec..846ce3abc 100644 --- a/ui/i18n/jquery.ui.datepicker-eu.js +++ b/ui/i18n/jquery.ui.datepicker-eu.js @@ -6,15 +6,15 @@ jQuery(function($){ prevText: '<Aur', nextText: 'Hur>', currentText: 'Gaur', - monthNames: ['Urtarrila','Otsaila','Martxoa','Apirila','Maiatza','Ekaina', - 'Uztaila','Abuztua','Iraila','Urria','Azaroa','Abendua'], - monthNamesShort: ['Urt','Ots','Mar','Api','Mai','Eka', - 'Uzt','Abu','Ira','Urr','Aza','Abe'], - dayNames: ['Igandea','Astelehena','Asteartea','Asteazkena','Osteguna','Ostirala','Larunbata'], - dayNamesShort: ['Iga','Ast','Ast','Ast','Ost','Ost','Lar'], - dayNamesMin: ['Ig','As','As','As','Os','Os','La'], - weekHeader: 'Wk', - dateFormat: 'yy/mm/dd', + monthNames: ['urtarrila','otsaila','martxoa','apirila','maiatza','ekaina', + 'uztaila','abuztua','iraila','urria','azaroa','abendua'], + monthNamesShort: ['urt.','ots.','mar.','api.','mai.','eka.', + 'uzt.','abu.','ira.','urr.','aza.','abe.'], + dayNames: ['igandea','astelehena','asteartea','asteazkena','osteguna','ostirala','larunbata'], + dayNamesShort: ['ig.','al.','ar.','az.','og.','ol.','lr.'], + dayNamesMin: ['ig','al','ar','az','og','ol','lr'], + weekHeader: 'As', + dateFormat: 'yy-mm-dd', firstDay: 1, isRTL: false, showMonthAfterYear: false, diff --git a/ui/jquery.effects.core.js b/ui/jquery.effects.core.js index fe2bf298d..1bb1415a9 100644 --- a/ui/jquery.effects.core.js +++ b/ui/jquery.effects.core.js @@ -54,27 +54,27 @@ function getRGB(color) { } // Look for rgb(num,num,num) - if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) { + if ( (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) ) { return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)]; } // Look for rgb(num%,num%,num%) - if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) { + if ( (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) ) { return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; } // Look for #a0b1c2 - if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) { + if ( (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) ) { return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; } // Look for #fff - if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) { + if ( (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) ) { return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; } // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 - if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) { + if ( (result = /rgba\(0, 0, 0, 0\)/.exec(color)) ) { return colors.transparent; } @@ -94,7 +94,7 @@ function getColor(elem, attr) { } attr = "backgroundColor"; - } while ( elem = elem.parentNode ); + } while ( (elem = elem.parentNode) ); return getRGB(color); } diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index fe1771bc8..f713d25b8 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -63,7 +63,8 @@ $.widget( "ui.accordion", { this._focusable( this.headers ); this.headers.next() - .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); + .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) + .hide(); // don't allow collapsible: false and active: false if ( !options.collapsible && options.active === false ) { @@ -76,7 +77,9 @@ $.widget( "ui.accordion", { this.active = this._findActive( options.active ) .addClass( "ui-accordion-header-active ui-state-active" ) .toggleClass( "ui-corner-all ui-corner-top" ); - this.active.next().addClass( "ui-accordion-content-active" ); + this.active.next() + .addClass( "ui-accordion-content-active" ) + .show(); this._createIcons(); this.originalHeight = this.element[0].style.height; @@ -290,10 +293,9 @@ $.widget( "ui.accordion", { }, refresh: function() { - var heightStyle = this.options.heightStyle, - parent = this.element.parent(), - maxHeight, - overflow; + var maxHeight, overflow, + heightStyle = this.options.heightStyle, + parent = this.element.parent(); this.element.css( "height", this.originalHeight ); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index fab9691a3..e5cc9e693 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -57,16 +57,11 @@ $.widget( "ui.autocomplete", { this.isMultiLine = this.element.is( "textarea,[contenteditable]" ); this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ]; + this.isNewMenu = true; this.element .addClass( "ui-autocomplete-input" ) - .attr( "autocomplete", "off" ) - // TODO verify these actually work as intended - .attr({ - role: "textbox", - "aria-autocomplete": "list", - "aria-haspopup": "true" - }); + .attr( "autocomplete", "off" ); this._bind({ keydown: function( event ) { @@ -115,7 +110,7 @@ $.widget( "ui.autocomplete", { } break; case keyCode.ESCAPE: - if ( this.menu.element.is(":visible") ) { + if ( this.menu.element.is( ":visible" ) ) { this._value( this.term ); this.close( event ); // Different browsers have different default behavior for escape @@ -183,12 +178,14 @@ $.widget( "ui.autocomplete", { }); this._initSource(); - this.menu = $( "<ul></ul>" ) + this.menu = $( "<ul>" ) .addClass( "ui-autocomplete" ) - .appendTo( this.document.find( this.options.appendTo || "body" )[0] ) + .appendTo( this.document.find( this.options.appendTo || "body" )[ 0 ] ) .menu({ // custom key handling for now - input: $() + input: $(), + // disable ARIA support, the live region takes care of that + role: null }) .zIndex( this.element.zIndex() + 1 ) .hide() @@ -213,7 +210,7 @@ $.widget( "ui.autocomplete", { if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { this._delay(function() { var that = this; - this.document.one( 'mousedown', function( event ) { + this.document.one( "mousedown", function( event ) { if ( event.target !== that.element[ 0 ] && event.target !== menuElement && !$.contains( menuElement, event.target ) ) { @@ -224,14 +221,35 @@ $.widget( "ui.autocomplete", { } }, menufocus: function( event, ui ) { + // #7024 - Prevent accidental activation of menu items in Firefox + if ( this.isNewMenu ) { + this.isNewMenu = false; + if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { + this.menu.blur(); + + this.document.one( "mousemove", function() { + $( event.target ).trigger( event.originalEvent ); + }); + + return; + } + } + // back compat for _renderItem using item.autocomplete, via #7810 // TODO remove the fallback, see #8156 var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ); if ( false !== this._trigger( "focus", event, { item: item } ) ) { // use value to match what will end up in the input, if it was a key event - if ( /^key/.test(event.originalEvent.type) ) { + if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { this._value( item.value ); } + } else { + // Normally the input is populated with the item's value as the + // menu is navigated, causing screen readers to notice a change and + // announce the item. Since the focus event was canceled, this doesn't + // happen, so we update the live region so that screen readers can + // still notice the change and announce it. + this.liveRegion.text( item.value ); } }, menuselect: function( event, ui ) { @@ -265,6 +283,13 @@ $.widget( "ui.autocomplete", { } }); + this.liveRegion = $( "<span>", { + role: "status", + "aria-live": "polite" + }) + .addClass( "ui-helper-hidden-accessible" ) + .insertAfter( this.element ); + if ( $.fn.bgiframe ) { this.menu.element.bgiframe(); } @@ -283,11 +308,9 @@ $.widget( "ui.autocomplete", { clearTimeout( this.searching ); this.element .removeClass( "ui-autocomplete-input" ) - .removeAttr( "autocomplete" ) - .removeAttr( "role" ) - .removeAttr( "aria-autocomplete" ) - .removeAttr( "aria-haspopup" ); + .removeAttr( "autocomplete" ); this.menu.element.remove(); + this.liveRegion.remove(); }, _setOption: function( key, value ) { @@ -304,13 +327,12 @@ $.widget( "ui.autocomplete", { }, _initSource: function() { - var that = this, - array, - url; + var array, url, + that = this; if ( $.isArray(this.options.source) ) { array = this.options.source; this.source = function( request, response ) { - response( $.ui.autocomplete.filter(array, request.term) ); + response( $.ui.autocomplete.filter( array, request.term ) ); }; } else if ( typeof this.options.source === "string" ) { url = this.options.source; @@ -408,9 +430,10 @@ $.widget( "ui.autocomplete", { _close: function( event ) { clearTimeout( this.closing ); - if ( this.menu.element.is(":visible") ) { + if ( this.menu.element.is( ":visible" ) ) { this.menu.element.hide(); this.menu.blur(); + this.isNewMenu = true; this._trigger( "close", event ); } }, @@ -426,7 +449,7 @@ $.widget( "ui.autocomplete", { if ( items.length && items[0].label && items[0].value ) { return items; } - return $.map( items, function(item) { + return $.map( items, function( item ) { if ( typeof item === "string" ) { return { label: item, @@ -457,7 +480,7 @@ $.widget( "ui.autocomplete", { }, this.options.position )); if ( this.options.autoFocus ) { - this.menu.next( new $.Event("mouseover") ); + this.menu.next(); } }, @@ -483,18 +506,18 @@ $.widget( "ui.autocomplete", { }, _renderItem: function( ul, item ) { - return $( "<li></li>" ) - .append( $( "<a></a>" ).text( item.label ) ) + return $( "<li>" ) + .append( $( "<a>" ).text( item.label ) ) .appendTo( ul ); }, _move: function( direction, event ) { - if ( !this.menu.element.is(":visible") ) { + if ( !this.menu.element.is( ":visible" ) ) { this.search( null, event ); return; } - if ( this.menu.isFirstItem() && /^previous/.test(direction) || - this.menu.isLastItem() && /^next/.test(direction) ) { + if ( this.menu.isFirstItem() && /^previous/.test( direction ) || + this.menu.isLastItem() && /^next/.test( direction ) ) { this._value( this.term ); this.menu.blur(); return; @@ -532,4 +555,35 @@ $.extend( $.ui.autocomplete, { } }); + +// live region extension, adding a `messages` option +// NOTE: This is an experimental API. We are still investigating +// a full solution for string manipulation and internationalization. +$.widget( "ui.autocomplete", $.ui.autocomplete, { + options: { + messages: { + noResults: "No search results.", + results: function(amount) { + return amount + ( amount > 1 ? " results are" : " result is" ) + + " available, use up and down arrow keys to navigate."; + } + } + }, + + __response: function( content ) { + var message; + this._superApply( arguments ); + if ( this.options.disabled || this.cancelSearch) { + return; + } + if ( content && content.length ) { + message = this.options.messages.results( content.length ); + } else { + message = this.options.messages.noResults; + } + this.liveRegion.text( message ); + } +}); + + }( jQuery )); diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index f84d748cf..810191775 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -73,7 +73,7 @@ $.widget( "ui.button", { focusClass = "ui-state-focus"; if ( options.label === null ) { - options.label = this.buttonElement.html(); + options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); } this.buttonElement @@ -214,9 +214,9 @@ $.widget( "ui.button", { _determineButtonType: function() { var ancestor, labelSelector, checked; - if ( this.element.is(":checkbox") ) { + if ( this.element.is("[type=checkbox]") ) { this.type = "checkbox"; - } else if ( this.element.is(":radio") ) { + } else if ( this.element.is("[type=radio]") ) { this.type = "radio"; } else if ( this.element.is("input") ) { this.type = "input"; @@ -354,11 +354,10 @@ $.widget( "ui.button", { } }); -$.ui.button.version = "@VERSION"; - $.widget( "ui.buttonset", { + version: "@VERSION", options: { - items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" + items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)" }, _create: function() { diff --git a/ui/jquery.ui.core.js b/ui/jquery.ui.core.js index 93353996e..d8fff91e1 100644 --- a/ui/jquery.ui.core.js +++ b/ui/jquery.ui.core.js @@ -119,49 +119,52 @@ $.fn.extend({ } }); -$.each( [ "Width", "Height" ], function( i, name ) { - var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], - type = name.toLowerCase(), - orig = { - innerWidth: $.fn.innerWidth, - innerHeight: $.fn.innerHeight, - outerWidth: $.fn.outerWidth, - outerHeight: $.fn.outerHeight - }; +// support: jQuery <1.8 +if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { + $.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; + if ( border ) { + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; + } + }); + return size; + } - function reduce( elem, size, border, margin ) { - $.each( side, function() { - size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; - if ( border ) { - size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); } - if ( margin ) { - size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; - } - }); - return size; - } - - $.fn[ "inner" + name ] = function( size ) { - if ( size === undefined ) { - return orig[ "inner" + name ].call( this ); - } - return this.each(function() { - $( this ).css( type, reduce( this, size ) + "px" ); - }); - }; + return this.each(function() { + $( this ).css( type, reduce( this, size ) + "px" ); + }); + }; - $.fn[ "outer" + name] = function( size, margin ) { - if ( typeof size !== "number" ) { - return orig[ "outer" + name ].call( this, size ); - } + $.fn[ "outer" + name] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } - return this.each(function() { - $( this).css( type, reduce( this, size, true, margin ) + "px" ); - }); - }; -}); + return this.each(function() { + $( this).css( type, reduce( this, size, true, margin ) + "px" ); + }); + }; + }); +} // selectors function focusable( element, isTabIndexNotNaN ) { diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index f60a1f78d..e48c26400 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -143,7 +143,14 @@ $.widget("ui.dialog", { .addClass( "ui-dialog-title" ) .attr( "id", titleId ) .html( title ) - .prependTo( uiDialogTitlebar ); + .prependTo( uiDialogTitlebar ), + + uiDialogButtonPane = ( this.uiDialogButtonPane = $( "<div>" ) ) + .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ), + + uiButtonSet = ( this.uiButtonSet = $( "<div>" ) ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection(); this._hoverable( uiDialogTitlebarClose ); @@ -326,7 +333,7 @@ $.widget("ui.dialog", { // if there are no tabbable elements, set focus on the dialog itself hasFocus = this.element.find( ":tabbable" ); if ( !hasFocus.length ) { - hasFocus = uiDialog.find( ".ui-dialog-buttonpane :tabbable" ); + hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); if ( !hasFocus.length ) { hasFocus = uiDialog; } @@ -345,7 +352,8 @@ $.widget("ui.dialog", { hasButtons = false; // if we already have a button pane, remove it - this.uiDialog.find( ".ui-dialog-buttonpane" ).remove(); + this.uiDialogButtonPane.remove(); + this.uiButtonSet.empty(); if ( typeof buttons === "object" && buttons !== null ) { $.each( buttons, function() { @@ -353,12 +361,6 @@ $.widget("ui.dialog", { }); } if ( hasButtons ) { - uiDialogButtonPane = $( "<div>" ) - .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); - uiButtonSet = $( "<div>" ) - .addClass( "ui-dialog-buttonset" ) - .appendTo( uiDialogButtonPane ); - $.each( buttons, function( name, props ) { props = $.isFunction( props ) ? { click: props, text: name } : @@ -369,13 +371,13 @@ $.widget("ui.dialog", { .click(function() { props.click.apply( that.element[0], arguments ); }) - .appendTo( uiButtonSet ); + .appendTo( that.uiButtonSet ); if ( $.fn.button ) { button.button(); } }); this.uiDialog.addClass( "ui-dialog-buttons" ); - uiDialogButtonPane.appendTo( this.uiDialog ); + this.uiDialogButtonPane.appendTo( this.uiDialog ); } else { this.uiDialog.removeClass( "ui-dialog-buttons" ); } diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 99df2e629..1bfd76716 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -26,6 +26,7 @@ $.widget( "ui.menu", { my: "left top", at: "right top" }, + role: "menu", // callbacks blur: null, @@ -42,7 +43,7 @@ $.widget( "ui.menu", { .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) .attr({ id: this.menuId, - role: "menu", + role: this.options.role, tabIndex: 0 }) // need to catch all clicks on disabled menu @@ -201,13 +202,11 @@ $.widget( "ui.menu", { event.preventDefault(); break; case $.ui.keyCode.ENTER: - if ( !this.active.is( ".ui-state-disabled" ) ) { - if ( this.active.children( "a[aria-haspopup='true']" ).length ) { - this.expand( event ); - } else { - this.select( event ); - } - } + this._activate( event ); + event.preventDefault(); + break; + case $.ui.keyCode.SPACE: + this._activate( event ); event.preventDefault(); break; case $.ui.keyCode.ESCAPE: @@ -259,6 +258,16 @@ $.widget( "ui.menu", { } }, + _activate: function( event ) { + if ( !this.active.is( ".ui-state-disabled" ) ) { + if ( this.active.children( "a[aria-haspopup='true']" ).length ) { + this.expand( event ); + } else { + this.select( event ); + } + } + }, + refresh: function() { // initialize nested menus var menus, @@ -267,7 +276,7 @@ $.widget( "ui.menu", { .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) .hide() .attr({ - role: "menu", + role: this.options.role, "aria-hidden": "true", "aria-expanded": "false" }); @@ -281,7 +290,7 @@ $.widget( "ui.menu", { .children( "a" ) .addClass( "ui-corner-all" ) .attr( "tabIndex", -1 ) - .attr( "role", "menuitem" ) + .attr( "role", this._itemRole() ) .attr( "id", function( i ) { return menuId + "-" + i; }); @@ -302,30 +311,26 @@ $.widget( "ui.menu", { }); }, + _itemRole: function() { + return { + menu: "menuitem", + listbox: "option" + }[ this.options.role ]; + }, + focus: function( event, item ) { - var nested, borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; + var nested, focused; this.blur( event, event && event.type === "focus" ); - if ( this._hasScroll() ) { - borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; - paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; - offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; - scroll = this.activeMenu.scrollTop(); - elementHeight = this.activeMenu.height(); - itemHeight = item.height(); - - if ( offset < 0 ) { - this.activeMenu.scrollTop( scroll + offset ); - } else if ( offset + itemHeight > elementHeight ) { - this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); - } - } + this._scrollIntoView( item ); this.active = item.first(); - this.element.attr( "aria-activedescendant", - this.active.children( "a" ) - .addClass( "ui-state-focus" ) - .attr( "id" ) ); + focused = this.active.children( "a" ).addClass( "ui-state-focus" ); + // only update aria-activedescendant if there's a role + // otherwise we assume focus is managed elsewhere + if ( this.options.role ) { + this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); + } // highlight active parent menu item, if any this.active.parent().closest( ".ui-menu-item" ).children( "a:first" ).addClass( "ui-state-active" ); @@ -347,6 +352,24 @@ $.widget( "ui.menu", { this._trigger( "focus", event, { item: item } ); }, + _scrollIntoView: function( item ) { + var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; + if ( this._hasScroll() ) { + borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; + paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; + offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; + scroll = this.activeMenu.scrollTop(); + elementHeight = this.activeMenu.height(); + itemHeight = item.height(); + + if ( offset < 0 ) { + this.activeMenu.scrollTop( scroll + offset ); + } else if ( offset + itemHeight > elementHeight ) { + this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); + } + } + }, + blur: function( event, fromFocus ) { if ( !fromFocus ) { clearTimeout( this.timer ); @@ -385,8 +408,8 @@ $.widget( "ui.menu", { var position = $.extend( {}, { of: this.active - }, $.type(this.options.position) === "function" ? - this.options.position(this.active) : + }, $.type( this.options.position ) === "function" ? + this.options.position( this.active ) : this.options.position ); diff --git a/ui/jquery.ui.mouse.js b/ui/jquery.ui.mouse.js index eaa953ad0..e2e06897c 100644 --- a/ui/jquery.ui.mouse.js +++ b/ui/jquery.ui.mouse.js @@ -20,7 +20,7 @@ $( document ).mouseup( function( e ) { $.widget("ui.mouse", { version: "@VERSION", options: { - cancel: ':input,option', + cancel: 'input,textarea,button,select,option', distance: 1, delay: 0 }, diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index b4433b618..6039cf648 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -171,12 +171,12 @@ $.widget("ui.resizable", $.ui.mouse, { this._handles.hide(); $(this.element) .addClass("ui-resizable-autohide") - .hover(function() { + .mouseenter(function() { if (o.disabled) return; $(this).removeClass("ui-resizable-autohide"); that._handles.show(); - }, - function(){ + }) + .mouseleave(function(){ if (o.disabled) return; if (!that.resizing) { $(this).addClass("ui-resizable-autohide"); diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js index accd3e189..c302bfe8b 100644 --- a/ui/jquery.ui.slider.js +++ b/ui/jquery.ui.slider.js @@ -90,11 +90,12 @@ $.widget( "ui.slider", $.ui.mouse, { .click(function( event ) { event.preventDefault(); }) - .hover(function() { + .mouseenter(function() { if ( !o.disabled ) { $( this ).addClass( "ui-state-hover" ); } - }, function() { + }) + .mouseleave(function() { $( this ).removeClass( "ui-state-hover" ); }) .focus(function() { diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index 55a64590b..88c8aa374 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -731,9 +731,10 @@ $.widget("ui.sortable", $.ui.mouse, { var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; for (var j = this.items.length - 1; j >= 0; j--) { if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; - var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; + var cur = this.containers[innermostIndex].floating ? this.items[j].item.offset().left : this.items[j].item.offset().top; if(Math.abs(cur - base) < dist) { dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + this.direction = (cur - base > 0) ? 'down' : 'up'; } } diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 026c50993..a693899da 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -25,7 +25,7 @@ function isLocal( anchor ) { // if it's manually set, i.e., a.href = "#foo" kills the normalization anchor = anchor.cloneNode( false ); return anchor.hash.length > 1 && - anchor.href.replace( rhash, "" ) === location.href.replace( rhash, "" ); + anchor.href.replace( rhash, "" ) === location.href.replace( rhash, "" ); } $.widget( "ui.tabs", { @@ -34,7 +34,8 @@ $.widget( "ui.tabs", { active: null, collapsible: false, event: "click", - fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } + hide: null, + show: null, // callbacks activate: null, @@ -46,20 +47,20 @@ $.widget( "ui.tabs", { _create: function() { var panel, that = this, - options = that.options, + options = this.options, active = options.active; - that.running = false; + this.running = false; - that.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); + this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); - that._processTabs(); + this._processTabs(); if ( active === null ) { // check the fragment identifier in the URL if ( location.hash ) { - that.anchors.each(function( i, tab ) { - if ( tab.hash === location.hash ) { + this.anchors.each(function( i, anchor ) { + if ( anchor.hash === location.hash ) { active = i; return false; } @@ -68,12 +69,12 @@ $.widget( "ui.tabs", { // check for a tab marked active via a class if ( active === null ) { - active = that.lis.filter( ".ui-tabs-active" ).index(); + active = this.lis.filter( ".ui-tabs-active" ).index(); } // no active tab, set to false if ( active === null || active === -1 ) { - active = that.lis.length ? 0 : false; + active = this.lis.length ? 0 : false; } } @@ -101,8 +102,6 @@ $.widget( "ui.tabs", { ) ).sort(); } - this._setupFx( options.fx ); - this._refresh(); // highlight selected tab @@ -111,7 +110,7 @@ $.widget( "ui.tabs", { // check for length avoids error when initializing empty list if ( options.active !== false && this.anchors.length ) { this.active = this._findActive( options.active ); - panel = that._getPanelForTab( this.active ); + panel = this._getPanelForTab( this.active ); panel.show(); this.lis.eq( options.active ).addClass( "ui-tabs-active ui-state-active" ); @@ -151,14 +150,10 @@ $.widget( "ui.tabs", { if ( key === "event" ) { this._setupEvents( value ); } - - if ( key === "fx" ) { - this._setupFx( value ); - } }, - _tabId: function( a ) { - return $( a ).attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); + _tabId: function( tab ) { + return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); }, _sanitizeSelector: function( hash ) { @@ -192,7 +187,7 @@ $.widget( "ui.tabs", { // was active, active tab still exists } else { // make sure active index is correct - options.active = this.anchors.index( this.active ); + options.active = this.lis.index( this.active ); } }, @@ -202,6 +197,7 @@ $.widget( "ui.tabs", { this.element.toggleClass( "ui-tabs-collapsible", options.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.anchors.addClass( "ui-tabs-anchor" ); this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); this._setupDisabled( options.disabled ); @@ -224,7 +220,8 @@ $.widget( "ui.tabs", { this.panels = $(); this.anchors.each(function( i, a ) { - var selector, panel, id; + var selector, panel, id, + tab = $( a ).closest( "li" ); // inline tab if ( isLocal( a ) ) { @@ -232,7 +229,7 @@ $.widget( "ui.tabs", { panel = that.element.find( that._sanitizeSelector( selector ) ); // remote tab } else { - id = that._tabId( a ); + id = that._tabId( tab ); selector = "#" + id; panel = that.element.find( selector ); if ( !panel.length ) { @@ -244,7 +241,7 @@ $.widget( "ui.tabs", { if ( panel.length) { that.panels = that.panels.add( panel ); } - $( a ).attr( "aria-controls", selector.substring( 1 ) ); + tab.attr( "aria-controls", selector.substring( 1 ) ); }); }, @@ -278,49 +275,34 @@ $.widget( "ui.tabs", { this.options.disabled = disabled; }, - _setupFx: function( fx ) { - // set up animations - if ( fx ) { - if ( $.isArray( fx ) ) { - this.hideFx = fx[ 0 ]; - this.showFx = fx[ 1 ]; - } else { - this.hideFx = this.showFx = fx; - } - } - }, - _setupEvents: function( event ) { - // attach tab event handler, unbind to avoid duplicates from former tabifying... - this.anchors.unbind( ".tabs" ); - - // TODO: use event delegation via _bind() + var events = { + click: function( event ) { + event.preventDefault(); + } + }; if ( event ) { - this.anchors.bind( event.split( " " ).join( ".tabs " ) + ".tabs", - $.proxy( this, "_eventHandler" ) ); + $.each( event.split(" "), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + }); } - - // TODO: use event delegation via _bind() - // disable click in any case - this.anchors.bind( "click.tabs", function( event ){ - event.preventDefault(); - }); + this.anchors.unbind( ".tabs" ); + this._bind( this.anchors, events ); }, _eventHandler: function( event ) { - var that = this, - options = that.options, - active = that.active, - clicked = $( event.currentTarget ), - clickedIsActive = clicked[ 0 ] === active[ 0 ], + var options = this.options, + active = this.active, + anchor = $( event.currentTarget ), + tab = anchor.closest( "li" ), + clickedIsActive = tab[ 0 ] === active[ 0 ], collapsing = clickedIsActive && options.collapsible, - toShow = collapsing ? $() : that._getPanelForTab( clicked ), - toHide = !active.length ? $() : that._getPanelForTab( active ), - tab = clicked.closest( "li" ), + toShow = collapsing ? $() : this._getPanelForTab( tab ), + toHide = !active.length ? $() : this._getPanelForTab( active ), eventData = { oldTab: active, oldPanel: toHide, - newTab: collapsing ? $() : clicked, + newTab: collapsing ? $() : tab, newPanel: toShow }; @@ -330,32 +312,30 @@ $.widget( "ui.tabs", { // tab is already loading tab.hasClass( "ui-tabs-loading" ) || // can't switch durning an animation - that.running || + this.running || // click on active header, but not collapsible ( clickedIsActive && !options.collapsible ) || // allow canceling activation - ( that._trigger( "beforeActivate", event, eventData ) === false ) ) { - clicked[ 0 ].blur(); + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { return; } - options.active = collapsing ? false : that.anchors.index( clicked ); + options.active = collapsing ? false : this.lis.index( tab ); - that.active = clickedIsActive ? $() : clicked; - if ( that.xhr ) { - that.xhr.abort(); + this.active = clickedIsActive ? $() : tab; + if ( this.xhr ) { + this.xhr.abort(); } if ( !toHide.length && !toShow.length ) { - jQuery.error( "jQuery UI Tabs: Mismatching fragment identifier." ); + $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); } if ( toShow.length ) { // TODO make passing in node possible - that.load( that.anchors.index( clicked ), event ); - clicked[ 0 ].blur(); + this.load( this.lis.index( tab ), event ); } - that._toggle( event, eventData ); + this._toggle( event, eventData ); }, // handles show/hide for selecting tabs @@ -364,7 +344,7 @@ $.widget( "ui.tabs", { toShow = eventData.newPanel, toHide = eventData.oldPanel; - that.running = true; + this.running = true; function complete() { that.running = false; @@ -374,11 +354,8 @@ $.widget( "ui.tabs", { function show() { eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); - if ( toShow.length && that.showFx ) { - toShow - .animate( that.showFx, that.showFx.duration || "normal", function() { - complete(); - }); + if ( toShow.length && that.options.show ) { + that._show( toShow, that.options.show, complete ); } else { toShow.show(); complete(); @@ -386,8 +363,8 @@ $.widget( "ui.tabs", { } // start out by hiding, then showing, then completing - if ( toHide.length && that.hideFx ) { - toHide.animate( that.hideFx, that.hideFx.duration || "normal", function() { + if ( toHide.length && this.options.hide ) { + this._hide( toHide, this.options.hide, function() { eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); show(); }); @@ -399,31 +376,39 @@ $.widget( "ui.tabs", { }, _activate: function( index ) { - var active = this._findActive( index )[ 0 ]; + var anchor, + active = this._findActive( index ); // trying to activate the already active panel - if ( active === this.active[ 0 ] ) { + if ( active[ 0 ] === this.active[ 0 ] ) { return; } // trying to collapse, simulate a click on the current active header - active = active || this.active[ 0 ]; + if ( !active.length ) { + active = this.active; + } + anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; this._eventHandler({ - target: active, - currentTarget: active, + target: anchor, + currentTarget: anchor, preventDefault: $.noop }); }, _findActive: function( selector ) { - return typeof selector === "number" ? this.anchors.eq( selector ) : - typeof selector === "string" ? this.anchors.filter( "[href$='" + selector + "']" ) : $(); + if ( typeof selector === "number" ) { + return this.lis.eq( selector ); + } + if ( typeof selector === "string" ) { + return this.anchors.filter( "[href$='" + selector + "']" ).closest( "li" ); + } + return $(); }, _getIndex: function( index ) { // meta-function to give users option to provide a href string instead of a numerical index. - // also sanitizes numerical indexes to valid values. if ( typeof index === "string" ) { index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); } @@ -441,6 +426,7 @@ $.widget( "ui.tabs", { this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); this.anchors + .removeClass( "ui-tabs-anchor" ) .unbind( ".tabs" ) .removeData( "href.tabs" ) .removeData( "load.tabs" ); @@ -513,10 +499,11 @@ $.widget( "ui.tabs", { load: function( index, event ) { index = this._getIndex( index ); var that = this, - anchor = this.anchors.eq( index ), - panel = that._getPanelForTab( anchor ), + tab = this.lis.eq( index ), + anchor = tab.find( ".ui-tabs-anchor" ), + panel = this._getPanelForTab( tab ), eventData = { - tab: anchor, + tab: tab, panel: panel }; @@ -533,27 +520,30 @@ $.widget( "ui.tabs", { } }); - if ( this.xhr ) { - this.lis.eq( index ).addClass( "ui-tabs-loading" ); + // support: jQuery <1.8 + // jQuery <1.8 returns false if the request is canceled in beforeSend, + // but as of 1.8, $.ajax() always returns a jqXHR object. + if ( this.xhr && this.xhr.statusText !== "canceled" ) { + tab.addClass( "ui-tabs-loading" ); this.xhr .success(function( response ) { - // TODO: IE resolves cached XHRs immediately - // remove when core #10467 is fixed + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 setTimeout(function() { panel.html( response ); that._trigger( "load", event, eventData ); }, 1 ); }) .complete(function( jqXHR, status ) { - // TODO: IE resolves cached XHRs immediately - // remove when core #10467 is fixed + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 setTimeout(function() { if ( status === "abort" ) { that.panels.stop( false, true ); } - that.lis.eq( index ).removeClass( "ui-tabs-loading" ); + tab.removeClass( "ui-tabs-loading" ); if ( jqXHR === that.xhr ) { delete that.xhr; @@ -740,10 +730,10 @@ if ( $.uiBackCompat !== false ) { .replace( /#\{label\}/g, label ) ), id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : - this._tabId( li.find( "a" )[ 0 ] ); + this._tabId( li ); li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true ); - li.find( "a" ).attr( "aria-controls", id ); + li.attr( "aria-controls", id ); doInsertAfter = index >= this.lis.length; @@ -786,7 +776,7 @@ if ( $.uiBackCompat !== false ) { index = this._getIndex( index ); var options = this.options, tab = this.lis.eq( index ).remove(), - panel = this._getPanelForTab( tab.find( "a[aria-controls]" ) ).remove(); + panel = this._getPanelForTab( tab ).remove(); // If selected tab was removed focus tab to the right or // in case the last tab was removed the tab to the left. @@ -825,8 +815,10 @@ if ( $.uiBackCompat !== false ) { idPrefix: "ui-tabs-" }, - _tabId: function( a ) { - return $( a ).attr( "aria-controls" ) || + _tabId: function( tab ) { + var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab; + a = a[0]; + return $( a ).closest( "li" ).attr( "aria-controls" ) || a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) || this.options.idPrefix + getNextTabId(); } @@ -892,7 +884,8 @@ if ( $.uiBackCompat !== false ) { this._super(); if ( this.options.active !== false ) { this._trigger( "show", null, this._ui( - this.active[ 0 ], this._getPanelForTab( this.active )[ 0 ] ) ); + this.active.find( ".ui-tabs-anchor" )[ 0 ], + this._getPanelForTab( this.active )[ 0 ] ) ); } }, _trigger: function( type, event, data ) { @@ -902,13 +895,13 @@ if ( $.uiBackCompat !== false ) { } if ( type === "beforeActivate" && data.newTab.length ) { ret = this._super( "select", event, { - tab: data.newTab[ 0], + tab: data.newTab.find( ".ui-tabs-anchor" )[ 0], panel: data.newPanel[ 0 ], index: data.newTab.closest( "li" ).index() }); } else if ( type === "activate" && data.newTab.length ) { ret = this._super( "show", event, { - tab: data.newTab[ 0 ], + tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ], panel: data.newPanel[ 0 ], index: data.newTab.closest( "li" ).index() }); @@ -990,11 +983,81 @@ if ( $.uiBackCompat !== false ) { var _data = $.extend( {}, data ); if ( type === "load" ) { _data.panel = _data.panel[ 0 ]; - _data.tab = _data.tab[ 0 ]; + _data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ]; } return this._super( type, event, _data ); } }); + + // fx option + // The new animation options (show, hide) conflict with the old show callback. + // The old fx option wins over show/hide anyway (always favor back-compat). + // If a user wants to use the new animation API, they must give up the old API. + $.widget( "ui.tabs", $.ui.tabs, { + options: { + fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 } + }, + + _getFx: function() { + var hide, show, + fx = this.options.fx; + + if ( fx ) { + if ( $.isArray( fx ) ) { + hide = fx[ 0 ]; + show = fx[ 1 ]; + } else { + hide = show = fx; + } + } + + return fx ? { show: show, hide: hide } : null; + }, + + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel, + fx = this._getFx(); + + if ( !fx ) { + return this._super( event, eventData ); + } + + that.running = true; + + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + + if ( toShow.length && fx.show ) { + toShow + .animate( fx.show, fx.show.duration, function() { + complete(); + }); + } else { + toShow.show(); + complete(); + } + } + + // start out by hiding, then showing, then completing + if ( toHide.length && fx.hide ) { + toHide.animate( fx.hide, fx.hide.duration, function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + show(); + }); + } else { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); + } + } + }); } })( jQuery ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 47a377bfd..1892d6555 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -14,6 +14,31 @@ var increments = 0; +function addDescribedBy( elem, id ) { + var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); + describedby.push( id ); + elem + .data( "ui-tooltip-id", id ) + .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); +} + +function removeDescribedBy( elem ) { + var id = elem.data( "ui-tooltip-id" ), + describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), + index = $.inArray( id, describedby ); + if ( index !== -1 ) { + describedby.splice( index, 1 ); + } + + elem.removeData( "ui-tooltip-id" ); + describedby = $.trim( describedby.join( " " ) ); + if ( describedby ) { + elem.attr( "aria-describedby", describedby ); + } else { + elem.removeAttr( "aria-describedby" ); + } +} + $.widget( "ui.tooltip", { version: "@VERSION", options: { @@ -92,8 +117,8 @@ $.widget( "ui.tooltip", { target = $( event ? event.target : this.element ) .closest( this.options.items ); - // if aria-describedby exists, then the tooltip is already open - if ( !target.length || target.attr( "aria-describedby" ) ) { + // if ui-tooltip-id exists, then the tooltip is already open + if ( !target.length || target.data( "ui-tooltip-id" ) ) { return; } @@ -127,7 +152,7 @@ $.widget( "ui.tooltip", { // if we have a title, clear it to prevent the native tooltip // we have to check first to avoid defining a title if none exists // (we don't want to cause an element to start matching [title]) - + // // We use removeAttr only for key events, to allow IE to export the correct // accessible attributes. For mouse events, set to empty string to avoid // native tooltip showing up (happens only when removing inside mouseover). @@ -143,7 +168,7 @@ $.widget( "ui.tooltip", { var tooltip = this._find( target ); if ( !tooltip.length ) { tooltip = this._tooltip( target ); - target.attr( "aria-describedby", tooltip.attr( "id" ) ); + addDescribedBy( target, tooltip.attr( "id" ) ); } tooltip.find( ".ui-tooltip-content" ).html( content ); tooltip @@ -183,6 +208,7 @@ $.widget( "ui.tooltip", { // don't close if the element has focus // this prevents the tooltip from closing if you hover while focused + // // we have to check the event type because tabbing out of the document // may leave the element as the activeElement if ( !force && event && event.type !== "focusout" && @@ -195,7 +221,7 @@ $.widget( "ui.tooltip", { target.attr( "title", target.data( "ui-tooltip-title" ) ); } - target.removeAttr( "aria-describedby" ); + removeDescribedBy( target ); tooltip.stop( true ); this._hide( tooltip, this.options.hide, function() { @@ -232,7 +258,7 @@ $.widget( "ui.tooltip", { }, _find: function( target ) { - var id = target.attr( "aria-describedby" ); + var id = target.data( "ui-tooltip-id" ); return id ? $( "#" + id ) : $(); }, |