[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /*! 2 * jQuery UI Tooltip 1.13.3 3 * https://jqueryui.com 4 * 5 * Copyright OpenJS Foundation and other contributors 6 * Released under the MIT license. 7 * https://jquery.org/license 8 */ 9 10 //>>label: Tooltip 11 //>>group: Widgets 12 //>>description: Shows additional information for any element on hover or focus. 13 //>>docs: https://api.jqueryui.com/tooltip/ 14 //>>demos: https://jqueryui.com/tooltip/ 15 //>>css.structure: ../../themes/base/core.css 16 //>>css.structure: ../../themes/base/tooltip.css 17 //>>css.theme: ../../themes/base/theme.css 18 19 ( function( factory ) { 20 "use strict"; 21 22 if ( typeof define === "function" && define.amd ) { 23 24 // AMD. Register as an anonymous module. 25 define( [ 26 "jquery", 27 "../keycode", 28 "../position", 29 "../unique-id", 30 "../version", 31 "../widget" 32 ], factory ); 33 } else { 34 35 // Browser globals 36 factory( jQuery ); 37 } 38 } )( function( $ ) { 39 "use strict"; 40 41 $.widget( "ui.tooltip", { 42 version: "1.13.3", 43 options: { 44 classes: { 45 "ui-tooltip": "ui-corner-all ui-widget-shadow" 46 }, 47 content: function() { 48 var title = $( this ).attr( "title" ); 49 50 // Escape title, since we're going from an attribute to raw HTML 51 return $( "<a>" ).text( title ).html(); 52 }, 53 hide: true, 54 55 // Disabled elements have inconsistent behavior across browsers (#8661) 56 items: "[title]:not([disabled])", 57 position: { 58 my: "left top+15", 59 at: "left bottom", 60 collision: "flipfit flip" 61 }, 62 show: true, 63 track: false, 64 65 // Callbacks 66 close: null, 67 open: null 68 }, 69 70 _addDescribedBy: function( elem, id ) { 71 var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ); 72 describedby.push( id ); 73 elem 74 .data( "ui-tooltip-id", id ) 75 .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) ); 76 }, 77 78 _removeDescribedBy: function( elem ) { 79 var id = elem.data( "ui-tooltip-id" ), 80 describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ), 81 index = $.inArray( id, describedby ); 82 83 if ( index !== -1 ) { 84 describedby.splice( index, 1 ); 85 } 86 87 elem.removeData( "ui-tooltip-id" ); 88 describedby = String.prototype.trim.call( describedby.join( " " ) ); 89 if ( describedby ) { 90 elem.attr( "aria-describedby", describedby ); 91 } else { 92 elem.removeAttr( "aria-describedby" ); 93 } 94 }, 95 96 _create: function() { 97 this._on( { 98 mouseover: "open", 99 focusin: "open" 100 } ); 101 102 // IDs of generated tooltips, needed for destroy 103 this.tooltips = {}; 104 105 // IDs of parent tooltips where we removed the title attribute 106 this.parents = {}; 107 108 // Append the aria-live region so tooltips announce correctly 109 this.liveRegion = $( "<div>" ) 110 .attr( { 111 role: "log", 112 "aria-live": "assertive", 113 "aria-relevant": "additions" 114 } ) 115 .appendTo( this.document[ 0 ].body ); 116 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 117 118 this.disabledTitles = $( [] ); 119 }, 120 121 _setOption: function( key, value ) { 122 var that = this; 123 124 this._super( key, value ); 125 126 if ( key === "content" ) { 127 $.each( this.tooltips, function( id, tooltipData ) { 128 that._updateContent( tooltipData.element ); 129 } ); 130 } 131 }, 132 133 _setOptionDisabled: function( value ) { 134 this[ value ? "_disable" : "_enable" ](); 135 }, 136 137 _disable: function() { 138 var that = this; 139 140 // Close open tooltips 141 $.each( this.tooltips, function( id, tooltipData ) { 142 var event = $.Event( "blur" ); 143 event.target = event.currentTarget = tooltipData.element[ 0 ]; 144 that.close( event, true ); 145 } ); 146 147 // Remove title attributes to prevent native tooltips 148 this.disabledTitles = this.disabledTitles.add( 149 this.element.find( this.options.items ).addBack() 150 .filter( function() { 151 var element = $( this ); 152 if ( element.is( "[title]" ) ) { 153 return element 154 .data( "ui-tooltip-title", element.attr( "title" ) ) 155 .removeAttr( "title" ); 156 } 157 } ) 158 ); 159 }, 160 161 _enable: function() { 162 163 // restore title attributes 164 this.disabledTitles.each( function() { 165 var element = $( this ); 166 if ( element.data( "ui-tooltip-title" ) ) { 167 element.attr( "title", element.data( "ui-tooltip-title" ) ); 168 } 169 } ); 170 this.disabledTitles = $( [] ); 171 }, 172 173 open: function( event ) { 174 var that = this, 175 target = $( event ? event.target : this.element ) 176 177 // we need closest here due to mouseover bubbling, 178 // but always pointing at the same event target 179 .closest( this.options.items ); 180 181 // No element to show a tooltip for or the tooltip is already open 182 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 183 return; 184 } 185 186 if ( target.attr( "title" ) ) { 187 target.data( "ui-tooltip-title", target.attr( "title" ) ); 188 } 189 190 target.data( "ui-tooltip-open", true ); 191 192 // Kill parent tooltips, custom or native, for hover 193 if ( event && event.type === "mouseover" ) { 194 target.parents().each( function() { 195 var parent = $( this ), 196 blurEvent; 197 if ( parent.data( "ui-tooltip-open" ) ) { 198 blurEvent = $.Event( "blur" ); 199 blurEvent.target = blurEvent.currentTarget = this; 200 that.close( blurEvent, true ); 201 } 202 if ( parent.attr( "title" ) ) { 203 parent.uniqueId(); 204 that.parents[ this.id ] = { 205 element: this, 206 title: parent.attr( "title" ) 207 }; 208 parent.attr( "title", "" ); 209 } 210 } ); 211 } 212 213 this._registerCloseHandlers( event, target ); 214 this._updateContent( target, event ); 215 }, 216 217 _updateContent: function( target, event ) { 218 var content, 219 contentOption = this.options.content, 220 that = this, 221 eventType = event ? event.type : null; 222 223 if ( typeof contentOption === "string" || contentOption.nodeType || 224 contentOption.jquery ) { 225 return this._open( event, target, contentOption ); 226 } 227 228 content = contentOption.call( target[ 0 ], function( response ) { 229 230 // IE may instantly serve a cached response for ajax requests 231 // delay this call to _open so the other call to _open runs first 232 that._delay( function() { 233 234 // Ignore async response if tooltip was closed already 235 if ( !target.data( "ui-tooltip-open" ) ) { 236 return; 237 } 238 239 // JQuery creates a special event for focusin when it doesn't 240 // exist natively. To improve performance, the native event 241 // object is reused and the type is changed. Therefore, we can't 242 // rely on the type being correct after the event finished 243 // bubbling, so we set it back to the previous value. (#8740) 244 if ( event ) { 245 event.type = eventType; 246 } 247 this._open( event, target, response ); 248 } ); 249 } ); 250 if ( content ) { 251 this._open( event, target, content ); 252 } 253 }, 254 255 _open: function( event, target, content ) { 256 var tooltipData, tooltip, delayedShow, a11yContent, 257 positionOption = $.extend( {}, this.options.position ); 258 259 if ( !content ) { 260 return; 261 } 262 263 // Content can be updated multiple times. If the tooltip already 264 // exists, then just update the content and bail. 265 tooltipData = this._find( target ); 266 if ( tooltipData ) { 267 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content ); 268 return; 269 } 270 271 // If we have a title, clear it to prevent the native tooltip 272 // we have to check first to avoid defining a title if none exists 273 // (we don't want to cause an element to start matching [title]) 274 // 275 // We use removeAttr only for key events, to allow IE to export the correct 276 // accessible attributes. For mouse events, set to empty string to avoid 277 // native tooltip showing up (happens only when removing inside mouseover). 278 if ( target.is( "[title]" ) ) { 279 if ( event && event.type === "mouseover" ) { 280 target.attr( "title", "" ); 281 } else { 282 target.removeAttr( "title" ); 283 } 284 } 285 286 tooltipData = this._tooltip( target ); 287 tooltip = tooltipData.tooltip; 288 this._addDescribedBy( target, tooltip.attr( "id" ) ); 289 tooltip.find( ".ui-tooltip-content" ).html( content ); 290 291 // Support: Voiceover on OS X, JAWS on IE <= 9 292 // JAWS announces deletions even when aria-relevant="additions" 293 // Voiceover will sometimes re-read the entire log region's contents from the beginning 294 this.liveRegion.children().hide(); 295 a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() ); 296 a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" ); 297 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" ); 298 a11yContent.appendTo( this.liveRegion ); 299 300 function position( event ) { 301 positionOption.of = event; 302 if ( tooltip.is( ":hidden" ) ) { 303 return; 304 } 305 tooltip.position( positionOption ); 306 } 307 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 308 this._on( this.document, { 309 mousemove: position 310 } ); 311 312 // trigger once to override element-relative positioning 313 position( event ); 314 } else { 315 tooltip.position( $.extend( { 316 of: target 317 }, this.options.position ) ); 318 } 319 320 tooltip.hide(); 321 322 this._show( tooltip, this.options.show ); 323 324 // Handle tracking tooltips that are shown with a delay (#8644). As soon 325 // as the tooltip is visible, position the tooltip using the most recent 326 // event. 327 // Adds the check to add the timers only when both delay and track options are set (#14682) 328 if ( this.options.track && this.options.show && this.options.show.delay ) { 329 delayedShow = this.delayedShow = setInterval( function() { 330 if ( tooltip.is( ":visible" ) ) { 331 position( positionOption.of ); 332 clearInterval( delayedShow ); 333 } 334 }, 13 ); 335 } 336 337 this._trigger( "open", event, { tooltip: tooltip } ); 338 }, 339 340 _registerCloseHandlers: function( event, target ) { 341 var events = { 342 keyup: function( event ) { 343 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 344 var fakeEvent = $.Event( event ); 345 fakeEvent.currentTarget = target[ 0 ]; 346 this.close( fakeEvent, true ); 347 } 348 } 349 }; 350 351 // Only bind remove handler for delegated targets. Non-delegated 352 // tooltips will handle this in destroy. 353 if ( target[ 0 ] !== this.element[ 0 ] ) { 354 events.remove = function() { 355 var targetElement = this._find( target ); 356 if ( targetElement ) { 357 this._removeTooltip( targetElement.tooltip ); 358 } 359 }; 360 } 361 362 if ( !event || event.type === "mouseover" ) { 363 events.mouseleave = "close"; 364 } 365 if ( !event || event.type === "focusin" ) { 366 events.focusout = "close"; 367 } 368 this._on( true, target, events ); 369 }, 370 371 close: function( event ) { 372 var tooltip, 373 that = this, 374 target = $( event ? event.currentTarget : this.element ), 375 tooltipData = this._find( target ); 376 377 // The tooltip may already be closed 378 if ( !tooltipData ) { 379 380 // We set ui-tooltip-open immediately upon open (in open()), but only set the 381 // additional data once there's actually content to show (in _open()). So even if the 382 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in 383 // the period between open() and _open(). 384 target.removeData( "ui-tooltip-open" ); 385 return; 386 } 387 388 tooltip = tooltipData.tooltip; 389 390 // Disabling closes the tooltip, so we need to track when we're closing 391 // to avoid an infinite loop in case the tooltip becomes disabled on close 392 if ( tooltipData.closing ) { 393 return; 394 } 395 396 // Clear the interval for delayed tracking tooltips 397 clearInterval( this.delayedShow ); 398 399 // Only set title if we had one before (see comment in _open()) 400 // If the title attribute has changed since open(), don't restore 401 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) { 402 target.attr( "title", target.data( "ui-tooltip-title" ) ); 403 } 404 405 this._removeDescribedBy( target ); 406 407 tooltipData.hiding = true; 408 tooltip.stop( true ); 409 this._hide( tooltip, this.options.hide, function() { 410 that._removeTooltip( $( this ) ); 411 } ); 412 413 target.removeData( "ui-tooltip-open" ); 414 this._off( target, "mouseleave focusout keyup" ); 415 416 // Remove 'remove' binding only on delegated targets 417 if ( target[ 0 ] !== this.element[ 0 ] ) { 418 this._off( target, "remove" ); 419 } 420 this._off( this.document, "mousemove" ); 421 422 if ( event && event.type === "mouseleave" ) { 423 $.each( this.parents, function( id, parent ) { 424 $( parent.element ).attr( "title", parent.title ); 425 delete that.parents[ id ]; 426 } ); 427 } 428 429 tooltipData.closing = true; 430 this._trigger( "close", event, { tooltip: tooltip } ); 431 if ( !tooltipData.hiding ) { 432 tooltipData.closing = false; 433 } 434 }, 435 436 _tooltip: function( element ) { 437 var tooltip = $( "<div>" ).attr( "role", "tooltip" ), 438 content = $( "<div>" ).appendTo( tooltip ), 439 id = tooltip.uniqueId().attr( "id" ); 440 441 this._addClass( content, "ui-tooltip-content" ); 442 this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" ); 443 444 tooltip.appendTo( this._appendTo( element ) ); 445 446 return this.tooltips[ id ] = { 447 element: element, 448 tooltip: tooltip 449 }; 450 }, 451 452 _find: function( target ) { 453 var id = target.data( "ui-tooltip-id" ); 454 return id ? this.tooltips[ id ] : null; 455 }, 456 457 _removeTooltip: function( tooltip ) { 458 459 // Clear the interval for delayed tracking tooltips 460 clearInterval( this.delayedShow ); 461 462 tooltip.remove(); 463 delete this.tooltips[ tooltip.attr( "id" ) ]; 464 }, 465 466 _appendTo: function( target ) { 467 var element = target.closest( ".ui-front, dialog" ); 468 469 if ( !element.length ) { 470 element = this.document[ 0 ].body; 471 } 472 473 return element; 474 }, 475 476 _destroy: function() { 477 var that = this; 478 479 // Close open tooltips 480 $.each( this.tooltips, function( id, tooltipData ) { 481 482 // Delegate to close method to handle common cleanup 483 var event = $.Event( "blur" ), 484 element = tooltipData.element; 485 event.target = event.currentTarget = element[ 0 ]; 486 that.close( event, true ); 487 488 // Remove immediately; destroying an open tooltip doesn't use the 489 // hide animation 490 $( "#" + id ).remove(); 491 492 // Restore the title 493 if ( element.data( "ui-tooltip-title" ) ) { 494 495 // If the title attribute has changed since open(), don't restore 496 if ( !element.attr( "title" ) ) { 497 element.attr( "title", element.data( "ui-tooltip-title" ) ); 498 } 499 element.removeData( "ui-tooltip-title" ); 500 } 501 } ); 502 this.liveRegion.remove(); 503 } 504 } ); 505 506 // DEPRECATED 507 // TODO: Switch return back to widget declaration at top of file when this is removed 508 if ( $.uiBackCompat !== false ) { 509 510 // Backcompat for tooltipClass option 511 $.widget( "ui.tooltip", $.ui.tooltip, { 512 options: { 513 tooltipClass: null 514 }, 515 _tooltip: function() { 516 var tooltipData = this._superApply( arguments ); 517 if ( this.options.tooltipClass ) { 518 tooltipData.tooltip.addClass( this.options.tooltipClass ); 519 } 520 return tooltipData; 521 } 522 } ); 523 } 524 525 return $.ui.tooltip; 526 527 } );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Nov 21 08:20:01 2024 | Cross-referenced by PHPXref |