]> source.dussan.org Git - jquery-ui.git/commitdiff
Tooltip: Move tooltip into widgets directory
authorAlexander Schmitz <arschmitz@gmail.com>
Wed, 15 Jul 2015 02:12:14 +0000 (22:12 -0400)
committerAlexander Schmitz <arschmitz@gmail.com>
Sat, 8 Aug 2015 04:29:39 +0000 (00:29 -0400)
Ref #13885

demos/bootstrap.js
tests/unit/tooltip/common-deprecated.js
tests/unit/tooltip/common.js
tests/unit/tooltip/core.js
tests/unit/tooltip/deprecated.js
tests/unit/tooltip/events.js
tests/unit/tooltip/methods.js
tests/unit/tooltip/options.js
ui/tooltip.js [deleted file]
ui/widgets/tooltip.js [new file with mode: 0644]

index 7407de3e4120e7cf83a8732686a2cb9e69032d30..1b28a4dc6595951b89a17bc1febdf0f2d6dbf04e 100644 (file)
@@ -41,7 +41,8 @@ var widgets = [
        "slider",
        "sortable",
        "spinner",
-       "tabs"
+       "tabs",
+       "tooltip"
 ];
 
 function getPath( module ) {
index d32e7656d3d52e97a3c25c525cb2e195fc5f1bc8..9e3c5ef593031726275d0a63acf56804eede3802 100644 (file)
@@ -1,6 +1,6 @@
 define( [
        "lib/common",
-       "ui/tooltip"
+       "ui/widgets/tooltip"
 ], function( common ) {
 
 common.testWidget( "tooltip", {
index f8045fc334080fe543bb9150bdf98be7b9413300..77e3f02b8f0e9918fe83bda4d2a7e1d19b0485b8 100644 (file)
@@ -1,6 +1,6 @@
 define( [
        "lib/common",
-       "ui/tooltip"
+       "ui/widgets/tooltip"
 ], function( common ) {
 
 common.testWidget( "tooltip", {
index de0b9022493f481d5f45a3512997edcd376b00b5..e7e22b0e65181295b088b5093c17006381251b37 100644 (file)
@@ -1,6 +1,6 @@
 define( [
        "jquery",
-       "ui/tooltip"
+       "ui/widgets/tooltip"
 ], function( $ ) {
 
 module( "tooltip: core" );
index 057171ee26223fd5715d9652321691094040383e..b1325057bfa4e9fc729d3d3218ea9cb0bf372b79 100644 (file)
@@ -1,6 +1,6 @@
 define( [
        "jquery",
-       "ui/tooltip"
+       "ui/widgets/tooltip"
 ], function( $ ) {
 
 module( "tooltip: (deprecated) options" );
index d8e9fa2a9288df6986d353ee3975510edc2f3519..7ad36dc08ba409ccbfdae91fe95c28cd16cb5625 100644 (file)
@@ -1,6 +1,6 @@
 define( [
        "jquery",
-       "ui/tooltip"
+       "ui/widgets/tooltip"
 ], function( $ ) {
 
 module( "tooltip: events" );
index 3db7b8f7c069ae45b19fe8fdee6b11dbc9eb7cd2..b5b6ca6e9f3ca59547191301be0e7f2c760a9fe4 100644 (file)
@@ -1,6 +1,6 @@
 define( [
        "jquery",
-       "ui/tooltip"
+       "ui/widgets/tooltip"
 ], function( $ ) {
 
 module( "tooltip: methods" );
index a0730414e81ec51c8f8676220b6158db65a561e5..6aa576583bda555321ffeffd3c93228ec0d40f6b 100644 (file)
@@ -1,6 +1,6 @@
 define( [
        "jquery",
-       "ui/tooltip"
+       "ui/widgets/tooltip"
 ], function( $ ) {
 
 module( "tooltip: options" );
diff --git a/ui/tooltip.js b/ui/tooltip.js
deleted file mode 100644 (file)
index 58cc438..0000000
+++ /dev/null
@@ -1,511 +0,0 @@
-/*!
- * jQuery UI Tooltip @VERSION
- * http://jqueryui.com
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- */
-
-//>>label: Tooltip
-//>>group: Widgets
-//>>description: Shows additional information for any element on hover or focus.
-//>>docs: http://api.jqueryui.com/tooltip/
-//>>demos: http://jqueryui.com/tooltip/
-//>>css.structure: ../themes/base/core.css
-//>>css.structure: ../themes/base/tooltip.css
-//>>css.theme: ../themes/base/theme.css
-
-( function( factory ) {
-       if ( typeof define === "function" && define.amd ) {
-
-               // AMD. Register as an anonymous module.
-               define( [
-                       "jquery",
-                       "./keycode",
-                       "./position",
-                       "./unique-id",
-                       "./version",
-                       "./widget"
-               ], factory );
-       } else {
-
-               // Browser globals
-               factory( jQuery );
-       }
-}( function( $ ) {
-
-$.widget( "ui.tooltip", {
-       version: "@VERSION",
-       options: {
-               classes: {
-                       "ui-tooltip": "ui-corner-all ui-widget-shadow"
-               },
-               content: function() {
-                       // support: IE<9, Opera in jQuery <1.7
-                       // .text() can't accept undefined, so coerce to a string
-                       var title = $( this ).attr( "title" ) || "";
-                       // Escape title, since we're going from an attribute to raw HTML
-                       return $( "<a>" ).text( title ).html();
-               },
-               hide: true,
-               // Disabled elements have inconsistent behavior across browsers (#8661)
-               items: "[title]:not([disabled])",
-               position: {
-                       my: "left top+15",
-                       at: "left bottom",
-                       collision: "flipfit flip"
-               },
-               show: true,
-               track: false,
-
-               // callbacks
-               close: null,
-               open: null
-       },
-
-       _addDescribedBy: function( 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( " " ) ) );
-       },
-
-       _removeDescribedBy: function( 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" );
-               }
-       },
-
-       _create: function() {
-               this._on( {
-                       mouseover: "open",
-                       focusin: "open"
-               } );
-
-               // IDs of generated tooltips, needed for destroy
-               this.tooltips = {};
-
-               // IDs of parent tooltips where we removed the title attribute
-               this.parents = {};
-
-               if ( this.options.disabled ) {
-                       this._disable();
-               }
-
-               // Append the aria-live region so tooltips announce correctly
-               this.liveRegion = $( "<div>" )
-                       .attr( {
-                               role: "log",
-                               "aria-live": "assertive",
-                               "aria-relevant": "additions"
-                       } )
-                       .appendTo( this.document[ 0 ].body );
-               this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
-       },
-
-       _setOption: function( key, value ) {
-               var that = this;
-
-               if ( key === "disabled" ) {
-                       this[ value ? "_disable" : "_enable" ]();
-                       this.options[ key ] = value;
-                       // disable element style changes
-                       return;
-               }
-
-               this._super( key, value );
-
-               if ( key === "content" ) {
-                       $.each( this.tooltips, function( id, tooltipData ) {
-                               that._updateContent( tooltipData.element );
-                       } );
-               }
-       },
-
-       _disable: function() {
-               var that = this;
-
-               // close open tooltips
-               $.each( this.tooltips, function( id, tooltipData ) {
-                       var event = $.Event( "blur" );
-                       event.target = event.currentTarget = tooltipData.element[ 0 ];
-                       that.close( event, true );
-               } );
-
-               // remove title attributes to prevent native tooltips
-               this.element.find( this.options.items ).addBack().each( function() {
-                       var element = $( this );
-                       if ( element.is( "[title]" ) ) {
-                               element
-                                       .data( "ui-tooltip-title", element.attr( "title" ) )
-                                       .removeAttr( "title" );
-                       }
-               } );
-       },
-
-       _enable: function() {
-               // restore title attributes
-               this.element.find( this.options.items ).addBack().each( function() {
-                       var element = $( this );
-                       if ( element.data( "ui-tooltip-title" ) ) {
-                               element.attr( "title", element.data( "ui-tooltip-title" ) );
-                       }
-               } );
-       },
-
-       open: function( event ) {
-               var that = this,
-                       target = $( event ? event.target : this.element )
-                               // we need closest here due to mouseover bubbling,
-                               // but always pointing at the same event target
-                               .closest( this.options.items );
-
-               // No element to show a tooltip for or the tooltip is already open
-               if ( !target.length || target.data( "ui-tooltip-id" ) ) {
-                       return;
-               }
-
-               if ( target.attr( "title" ) ) {
-                       target.data( "ui-tooltip-title", target.attr( "title" ) );
-               }
-
-               target.data( "ui-tooltip-open", true );
-
-               // kill parent tooltips, custom or native, for hover
-               if ( event && event.type === "mouseover" ) {
-                       target.parents().each( function() {
-                               var parent = $( this ),
-                                       blurEvent;
-                               if ( parent.data( "ui-tooltip-open" ) ) {
-                                       blurEvent = $.Event( "blur" );
-                                       blurEvent.target = blurEvent.currentTarget = this;
-                                       that.close( blurEvent, true );
-                               }
-                               if ( parent.attr( "title" ) ) {
-                                       parent.uniqueId();
-                                       that.parents[ this.id ] = {
-                                               element: this,
-                                               title: parent.attr( "title" )
-                                       };
-                                       parent.attr( "title", "" );
-                               }
-                       } );
-               }
-
-               this._registerCloseHandlers( event, target );
-               this._updateContent( target, event );
-       },
-
-       _updateContent: function( target, event ) {
-               var content,
-                       contentOption = this.options.content,
-                       that = this,
-                       eventType = event ? event.type : null;
-
-               if ( typeof contentOption === "string" || contentOption.nodeType ||
-                               contentOption.jquery ) {
-                       return this._open( event, target, contentOption );
-               }
-
-               content = contentOption.call( target[ 0 ], function( response ) {
-
-                       // IE may instantly serve a cached response for ajax requests
-                       // delay this call to _open so the other call to _open runs first
-                       that._delay( function() {
-
-                               // Ignore async response if tooltip was closed already
-                               if ( !target.data( "ui-tooltip-open" ) ) {
-                                       return;
-                               }
-
-                               // jQuery creates a special event for focusin when it doesn't
-                               // exist natively. To improve performance, the native event
-                               // object is reused and the type is changed. Therefore, we can't
-                               // rely on the type being correct after the event finished
-                               // bubbling, so we set it back to the previous value. (#8740)
-                               if ( event ) {
-                                       event.type = eventType;
-                               }
-                               this._open( event, target, response );
-                       } );
-               } );
-               if ( content ) {
-                       this._open( event, target, content );
-               }
-       },
-
-       _open: function( event, target, content ) {
-               var tooltipData, tooltip, delayedShow, a11yContent,
-                       positionOption = $.extend( {}, this.options.position );
-
-               if ( !content ) {
-                       return;
-               }
-
-               // Content can be updated multiple times. If the tooltip already
-               // exists, then just update the content and bail.
-               tooltipData = this._find( target );
-               if ( tooltipData ) {
-                       tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
-                       return;
-               }
-
-               // 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).
-               if ( target.is( "[title]" ) ) {
-                       if ( event && event.type === "mouseover" ) {
-                               target.attr( "title", "" );
-                       } else {
-                               target.removeAttr( "title" );
-                       }
-               }
-
-               tooltipData = this._tooltip( target );
-               tooltip = tooltipData.tooltip;
-               this._addDescribedBy( target, tooltip.attr( "id" ) );
-               tooltip.find( ".ui-tooltip-content" ).html( content );
-
-               // Support: Voiceover on OS X, JAWS on IE <= 9
-               // JAWS announces deletions even when aria-relevant="additions"
-               // Voiceover will sometimes re-read the entire log region's contents from the beginning
-               this.liveRegion.children().hide();
-               a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
-               a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
-               a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
-               a11yContent.appendTo( this.liveRegion );
-
-               function position( event ) {
-                       positionOption.of = event;
-                       if ( tooltip.is( ":hidden" ) ) {
-                               return;
-                       }
-                       tooltip.position( positionOption );
-               }
-               if ( this.options.track && event && /^mouse/.test( event.type ) ) {
-                       this._on( this.document, {
-                               mousemove: position
-                       } );
-                       // trigger once to override element-relative positioning
-                       position( event );
-               } else {
-                       tooltip.position( $.extend( {
-                               of: target
-                       }, this.options.position ) );
-               }
-
-               tooltip.hide();
-
-               this._show( tooltip, this.options.show );
-               // Handle tracking tooltips that are shown with a delay (#8644). As soon
-               // as the tooltip is visible, position the tooltip using the most recent
-               // event.
-               if ( this.options.show && this.options.show.delay ) {
-                       delayedShow = this.delayedShow = setInterval( function() {
-                               if ( tooltip.is( ":visible" ) ) {
-                                       position( positionOption.of );
-                                       clearInterval( delayedShow );
-                               }
-                       }, $.fx.interval );
-               }
-
-               this._trigger( "open", event, { tooltip: tooltip } );
-       },
-
-       _registerCloseHandlers: function( event, target ) {
-               var events = {
-                       keyup: function( event ) {
-                               if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
-                                       var fakeEvent = $.Event( event );
-                                       fakeEvent.currentTarget = target[ 0 ];
-                                       this.close( fakeEvent, true );
-                               }
-                       }
-               };
-
-               // Only bind remove handler for delegated targets. Non-delegated
-               // tooltips will handle this in destroy.
-               if ( target[ 0 ] !== this.element[ 0 ] ) {
-                       events.remove = function() {
-                               this._removeTooltip( this._find( target ).tooltip );
-                       };
-               }
-
-               if ( !event || event.type === "mouseover" ) {
-                       events.mouseleave = "close";
-               }
-               if ( !event || event.type === "focusin" ) {
-                       events.focusout = "close";
-               }
-               this._on( true, target, events );
-       },
-
-       close: function( event ) {
-               var tooltip,
-                       that = this,
-                       target = $( event ? event.currentTarget : this.element ),
-                       tooltipData = this._find( target );
-
-               // The tooltip may already be closed
-               if ( !tooltipData ) {
-
-                       // We set ui-tooltip-open immediately upon open (in open()), but only set the
-                       // additional data once there's actually content to show (in _open()). So even if the
-                       // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
-                       // the period between open() and _open().
-                       target.removeData( "ui-tooltip-open" );
-                       return;
-               }
-
-               tooltip = tooltipData.tooltip;
-
-               // disabling closes the tooltip, so we need to track when we're closing
-               // to avoid an infinite loop in case the tooltip becomes disabled on close
-               if ( tooltipData.closing ) {
-                       return;
-               }
-
-               // Clear the interval for delayed tracking tooltips
-               clearInterval( this.delayedShow );
-
-               // only set title if we had one before (see comment in _open())
-               // If the title attribute has changed since open(), don't restore
-               if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
-                       target.attr( "title", target.data( "ui-tooltip-title" ) );
-               }
-
-               this._removeDescribedBy( target );
-
-               tooltipData.hiding = true;
-               tooltip.stop( true );
-               this._hide( tooltip, this.options.hide, function() {
-                       that._removeTooltip( $( this ) );
-               } );
-
-               target.removeData( "ui-tooltip-open" );
-               this._off( target, "mouseleave focusout keyup" );
-
-               // Remove 'remove' binding only on delegated targets
-               if ( target[ 0 ] !== this.element[ 0 ] ) {
-                       this._off( target, "remove" );
-               }
-               this._off( this.document, "mousemove" );
-
-               if ( event && event.type === "mouseleave" ) {
-                       $.each( this.parents, function( id, parent ) {
-                               $( parent.element ).attr( "title", parent.title );
-                               delete that.parents[ id ];
-                       } );
-               }
-
-               tooltipData.closing = true;
-               this._trigger( "close", event, { tooltip: tooltip } );
-               if ( !tooltipData.hiding ) {
-                       tooltipData.closing = false;
-               }
-       },
-
-       _tooltip: function( element ) {
-               var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
-                       content = $( "<div>" ).appendTo( tooltip ),
-                       id = tooltip.uniqueId().attr( "id" );
-
-               this._addClass( content, "ui-tooltip-content" );
-               this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
-
-               tooltip.appendTo( this._appendTo( element ) );
-
-               return this.tooltips[ id ] = {
-                       element: element,
-                       tooltip: tooltip
-               };
-       },
-
-       _find: function( target ) {
-               var id = target.data( "ui-tooltip-id" );
-               return id ? this.tooltips[ id ] : null;
-       },
-
-       _removeTooltip: function( tooltip ) {
-               tooltip.remove();
-               delete this.tooltips[ tooltip.attr( "id" ) ];
-       },
-
-       _appendTo: function( target ) {
-               var element = target.closest( ".ui-front, dialog" );
-
-               if ( !element.length ) {
-                       element = this.document[ 0 ].body;
-               }
-
-               return element;
-       },
-
-       _destroy: function() {
-               var that = this;
-
-               // close open tooltips
-               $.each( this.tooltips, function( id, tooltipData ) {
-                       // Delegate to close method to handle common cleanup
-                       var event = $.Event( "blur" ),
-                               element = tooltipData.element;
-                       event.target = event.currentTarget = element[ 0 ];
-                       that.close( event, true );
-
-                       // Remove immediately; destroying an open tooltip doesn't use the
-                       // hide animation
-                       $( "#" + id ).remove();
-
-                       // Restore the title
-                       if ( element.data( "ui-tooltip-title" ) ) {
-                               // If the title attribute has changed since open(), don't restore
-                               if ( !element.attr( "title" ) ) {
-                                       element.attr( "title", element.data( "ui-tooltip-title" ) );
-                               }
-                               element.removeData( "ui-tooltip-title" );
-                       }
-               } );
-               this.liveRegion.remove();
-       }
-} );
-
-// DEPRECATED
-// TODO: Switch return back to widget declaration at top of file when this is removed
-if ( $.uiBackCompat !== false ) {
-
-       // Backcompat for tooltipClass option
-       $.widget( "ui.tooltip", $.ui.tooltip, {
-               options: {
-                       tooltipClass: null
-               },
-               _tooltip: function() {
-                       var tooltipData = this._superApply( arguments );
-                       if ( this.options.tooltipClass ) {
-                               tooltipData.tooltip.addClass( this.options.tooltipClass );
-                       }
-                       return tooltipData;
-               }
-       } );
-}
-
-return $.ui.tooltip;
-
-} ) );
diff --git a/ui/widgets/tooltip.js b/ui/widgets/tooltip.js
new file mode 100644 (file)
index 0000000..1c91958
--- /dev/null
@@ -0,0 +1,511 @@
+/*!
+ * jQuery UI Tooltip @VERSION
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: Tooltip
+//>>group: Widgets
+//>>description: Shows additional information for any element on hover or focus.
+//>>docs: http://api.jqueryui.com/tooltip/
+//>>demos: http://jqueryui.com/tooltip/
+//>>css.structure: ../themes/base/core.css
+//>>css.structure: ../themes/base/tooltip.css
+//>>css.theme: ../themes/base/theme.css
+
+( function( factory ) {
+       if ( typeof define === "function" && define.amd ) {
+
+               // AMD. Register as an anonymous module.
+               define( [
+                       "jquery",
+                       "../keycode",
+                       "../position",
+                       "../unique-id",
+                       "../version",
+                       "../widget"
+               ], factory );
+       } else {
+
+               // Browser globals
+               factory( jQuery );
+       }
+}( function( $ ) {
+
+$.widget( "ui.tooltip", {
+       version: "@VERSION",
+       options: {
+               classes: {
+                       "ui-tooltip": "ui-corner-all ui-widget-shadow"
+               },
+               content: function() {
+                       // support: IE<9, Opera in jQuery <1.7
+                       // .text() can't accept undefined, so coerce to a string
+                       var title = $( this ).attr( "title" ) || "";
+                       // Escape title, since we're going from an attribute to raw HTML
+                       return $( "<a>" ).text( title ).html();
+               },
+               hide: true,
+               // Disabled elements have inconsistent behavior across browsers (#8661)
+               items: "[title]:not([disabled])",
+               position: {
+                       my: "left top+15",
+                       at: "left bottom",
+                       collision: "flipfit flip"
+               },
+               show: true,
+               track: false,
+
+               // callbacks
+               close: null,
+               open: null
+       },
+
+       _addDescribedBy: function( 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( " " ) ) );
+       },
+
+       _removeDescribedBy: function( 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" );
+               }
+       },
+
+       _create: function() {
+               this._on( {
+                       mouseover: "open",
+                       focusin: "open"
+               } );
+
+               // IDs of generated tooltips, needed for destroy
+               this.tooltips = {};
+
+               // IDs of parent tooltips where we removed the title attribute
+               this.parents = {};
+
+               if ( this.options.disabled ) {
+                       this._disable();
+               }
+
+               // Append the aria-live region so tooltips announce correctly
+               this.liveRegion = $( "<div>" )
+                       .attr( {
+                               role: "log",
+                               "aria-live": "assertive",
+                               "aria-relevant": "additions"
+                       } )
+                       .appendTo( this.document[ 0 ].body );
+               this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
+       },
+
+       _setOption: function( key, value ) {
+               var that = this;
+
+               if ( key === "disabled" ) {
+                       this[ value ? "_disable" : "_enable" ]();
+                       this.options[ key ] = value;
+                       // disable element style changes
+                       return;
+               }
+
+               this._super( key, value );
+
+               if ( key === "content" ) {
+                       $.each( this.tooltips, function( id, tooltipData ) {
+                               that._updateContent( tooltipData.element );
+                       } );
+               }
+       },
+
+       _disable: function() {
+               var that = this;
+
+               // close open tooltips
+               $.each( this.tooltips, function( id, tooltipData ) {
+                       var event = $.Event( "blur" );
+                       event.target = event.currentTarget = tooltipData.element[ 0 ];
+                       that.close( event, true );
+               } );
+
+               // remove title attributes to prevent native tooltips
+               this.element.find( this.options.items ).addBack().each( function() {
+                       var element = $( this );
+                       if ( element.is( "[title]" ) ) {
+                               element
+                                       .data( "ui-tooltip-title", element.attr( "title" ) )
+                                       .removeAttr( "title" );
+                       }
+               } );
+       },
+
+       _enable: function() {
+               // restore title attributes
+               this.element.find( this.options.items ).addBack().each( function() {
+                       var element = $( this );
+                       if ( element.data( "ui-tooltip-title" ) ) {
+                               element.attr( "title", element.data( "ui-tooltip-title" ) );
+                       }
+               } );
+       },
+
+       open: function( event ) {
+               var that = this,
+                       target = $( event ? event.target : this.element )
+                               // we need closest here due to mouseover bubbling,
+                               // but always pointing at the same event target
+                               .closest( this.options.items );
+
+               // No element to show a tooltip for or the tooltip is already open
+               if ( !target.length || target.data( "ui-tooltip-id" ) ) {
+                       return;
+               }
+
+               if ( target.attr( "title" ) ) {
+                       target.data( "ui-tooltip-title", target.attr( "title" ) );
+               }
+
+               target.data( "ui-tooltip-open", true );
+
+               // kill parent tooltips, custom or native, for hover
+               if ( event && event.type === "mouseover" ) {
+                       target.parents().each( function() {
+                               var parent = $( this ),
+                                       blurEvent;
+                               if ( parent.data( "ui-tooltip-open" ) ) {
+                                       blurEvent = $.Event( "blur" );
+                                       blurEvent.target = blurEvent.currentTarget = this;
+                                       that.close( blurEvent, true );
+                               }
+                               if ( parent.attr( "title" ) ) {
+                                       parent.uniqueId();
+                                       that.parents[ this.id ] = {
+                                               element: this,
+                                               title: parent.attr( "title" )
+                                       };
+                                       parent.attr( "title", "" );
+                               }
+                       } );
+               }
+
+               this._registerCloseHandlers( event, target );
+               this._updateContent( target, event );
+       },
+
+       _updateContent: function( target, event ) {
+               var content,
+                       contentOption = this.options.content,
+                       that = this,
+                       eventType = event ? event.type : null;
+
+               if ( typeof contentOption === "string" || contentOption.nodeType ||
+                               contentOption.jquery ) {
+                       return this._open( event, target, contentOption );
+               }
+
+               content = contentOption.call( target[ 0 ], function( response ) {
+
+                       // IE may instantly serve a cached response for ajax requests
+                       // delay this call to _open so the other call to _open runs first
+                       that._delay( function() {
+
+                               // Ignore async response if tooltip was closed already
+                               if ( !target.data( "ui-tooltip-open" ) ) {
+                                       return;
+                               }
+
+                               // jQuery creates a special event for focusin when it doesn't
+                               // exist natively. To improve performance, the native event
+                               // object is reused and the type is changed. Therefore, we can't
+                               // rely on the type being correct after the event finished
+                               // bubbling, so we set it back to the previous value. (#8740)
+                               if ( event ) {
+                                       event.type = eventType;
+                               }
+                               this._open( event, target, response );
+                       } );
+               } );
+               if ( content ) {
+                       this._open( event, target, content );
+               }
+       },
+
+       _open: function( event, target, content ) {
+               var tooltipData, tooltip, delayedShow, a11yContent,
+                       positionOption = $.extend( {}, this.options.position );
+
+               if ( !content ) {
+                       return;
+               }
+
+               // Content can be updated multiple times. If the tooltip already
+               // exists, then just update the content and bail.
+               tooltipData = this._find( target );
+               if ( tooltipData ) {
+                       tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
+                       return;
+               }
+
+               // 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).
+               if ( target.is( "[title]" ) ) {
+                       if ( event && event.type === "mouseover" ) {
+                               target.attr( "title", "" );
+                       } else {
+                               target.removeAttr( "title" );
+                       }
+               }
+
+               tooltipData = this._tooltip( target );
+               tooltip = tooltipData.tooltip;
+               this._addDescribedBy( target, tooltip.attr( "id" ) );
+               tooltip.find( ".ui-tooltip-content" ).html( content );
+
+               // Support: Voiceover on OS X, JAWS on IE <= 9
+               // JAWS announces deletions even when aria-relevant="additions"
+               // Voiceover will sometimes re-read the entire log region's contents from the beginning
+               this.liveRegion.children().hide();
+               a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
+               a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
+               a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
+               a11yContent.appendTo( this.liveRegion );
+
+               function position( event ) {
+                       positionOption.of = event;
+                       if ( tooltip.is( ":hidden" ) ) {
+                               return;
+                       }
+                       tooltip.position( positionOption );
+               }
+               if ( this.options.track && event && /^mouse/.test( event.type ) ) {
+                       this._on( this.document, {
+                               mousemove: position
+                       } );
+                       // trigger once to override element-relative positioning
+                       position( event );
+               } else {
+                       tooltip.position( $.extend( {
+                               of: target
+                       }, this.options.position ) );
+               }
+
+               tooltip.hide();
+
+               this._show( tooltip, this.options.show );
+               // Handle tracking tooltips that are shown with a delay (#8644). As soon
+               // as the tooltip is visible, position the tooltip using the most recent
+               // event.
+               if ( this.options.show && this.options.show.delay ) {
+                       delayedShow = this.delayedShow = setInterval( function() {
+                               if ( tooltip.is( ":visible" ) ) {
+                                       position( positionOption.of );
+                                       clearInterval( delayedShow );
+                               }
+                       }, $.fx.interval );
+               }
+
+               this._trigger( "open", event, { tooltip: tooltip } );
+       },
+
+       _registerCloseHandlers: function( event, target ) {
+               var events = {
+                       keyup: function( event ) {
+                               if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
+                                       var fakeEvent = $.Event( event );
+                                       fakeEvent.currentTarget = target[ 0 ];
+                                       this.close( fakeEvent, true );
+                               }
+                       }
+               };
+
+               // Only bind remove handler for delegated targets. Non-delegated
+               // tooltips will handle this in destroy.
+               if ( target[ 0 ] !== this.element[ 0 ] ) {
+                       events.remove = function() {
+                               this._removeTooltip( this._find( target ).tooltip );
+                       };
+               }
+
+               if ( !event || event.type === "mouseover" ) {
+                       events.mouseleave = "close";
+               }
+               if ( !event || event.type === "focusin" ) {
+                       events.focusout = "close";
+               }
+               this._on( true, target, events );
+       },
+
+       close: function( event ) {
+               var tooltip,
+                       that = this,
+                       target = $( event ? event.currentTarget : this.element ),
+                       tooltipData = this._find( target );
+
+               // The tooltip may already be closed
+               if ( !tooltipData ) {
+
+                       // We set ui-tooltip-open immediately upon open (in open()), but only set the
+                       // additional data once there's actually content to show (in _open()). So even if the
+                       // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
+                       // the period between open() and _open().
+                       target.removeData( "ui-tooltip-open" );
+                       return;
+               }
+
+               tooltip = tooltipData.tooltip;
+
+               // disabling closes the tooltip, so we need to track when we're closing
+               // to avoid an infinite loop in case the tooltip becomes disabled on close
+               if ( tooltipData.closing ) {
+                       return;
+               }
+
+               // Clear the interval for delayed tracking tooltips
+               clearInterval( this.delayedShow );
+
+               // only set title if we had one before (see comment in _open())
+               // If the title attribute has changed since open(), don't restore
+               if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
+                       target.attr( "title", target.data( "ui-tooltip-title" ) );
+               }
+
+               this._removeDescribedBy( target );
+
+               tooltipData.hiding = true;
+               tooltip.stop( true );
+               this._hide( tooltip, this.options.hide, function() {
+                       that._removeTooltip( $( this ) );
+               } );
+
+               target.removeData( "ui-tooltip-open" );
+               this._off( target, "mouseleave focusout keyup" );
+
+               // Remove 'remove' binding only on delegated targets
+               if ( target[ 0 ] !== this.element[ 0 ] ) {
+                       this._off( target, "remove" );
+               }
+               this._off( this.document, "mousemove" );
+
+               if ( event && event.type === "mouseleave" ) {
+                       $.each( this.parents, function( id, parent ) {
+                               $( parent.element ).attr( "title", parent.title );
+                               delete that.parents[ id ];
+                       } );
+               }
+
+               tooltipData.closing = true;
+               this._trigger( "close", event, { tooltip: tooltip } );
+               if ( !tooltipData.hiding ) {
+                       tooltipData.closing = false;
+               }
+       },
+
+       _tooltip: function( element ) {
+               var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
+                       content = $( "<div>" ).appendTo( tooltip ),
+                       id = tooltip.uniqueId().attr( "id" );
+
+               this._addClass( content, "ui-tooltip-content" );
+               this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
+
+               tooltip.appendTo( this._appendTo( element ) );
+
+               return this.tooltips[ id ] = {
+                       element: element,
+                       tooltip: tooltip
+               };
+       },
+
+       _find: function( target ) {
+               var id = target.data( "ui-tooltip-id" );
+               return id ? this.tooltips[ id ] : null;
+       },
+
+       _removeTooltip: function( tooltip ) {
+               tooltip.remove();
+               delete this.tooltips[ tooltip.attr( "id" ) ];
+       },
+
+       _appendTo: function( target ) {
+               var element = target.closest( ".ui-front, dialog" );
+
+               if ( !element.length ) {
+                       element = this.document[ 0 ].body;
+               }
+
+               return element;
+       },
+
+       _destroy: function() {
+               var that = this;
+
+               // close open tooltips
+               $.each( this.tooltips, function( id, tooltipData ) {
+                       // Delegate to close method to handle common cleanup
+                       var event = $.Event( "blur" ),
+                               element = tooltipData.element;
+                       event.target = event.currentTarget = element[ 0 ];
+                       that.close( event, true );
+
+                       // Remove immediately; destroying an open tooltip doesn't use the
+                       // hide animation
+                       $( "#" + id ).remove();
+
+                       // Restore the title
+                       if ( element.data( "ui-tooltip-title" ) ) {
+                               // If the title attribute has changed since open(), don't restore
+                               if ( !element.attr( "title" ) ) {
+                                       element.attr( "title", element.data( "ui-tooltip-title" ) );
+                               }
+                               element.removeData( "ui-tooltip-title" );
+                       }
+               } );
+               this.liveRegion.remove();
+       }
+} );
+
+// DEPRECATED
+// TODO: Switch return back to widget declaration at top of file when this is removed
+if ( $.uiBackCompat !== false ) {
+
+       // Backcompat for tooltipClass option
+       $.widget( "ui.tooltip", $.ui.tooltip, {
+               options: {
+                       tooltipClass: null
+               },
+               _tooltip: function() {
+                       var tooltipData = this._superApply( arguments );
+                       if ( this.options.tooltipClass ) {
+                               tooltipData.tooltip.addClass( this.options.tooltipClass );
+                       }
+                       return tooltipData;
+               }
+       } );
+}
+
+return $.ui.tooltip;
+
+} ) );