[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/js/jquery/ui/ -> tooltip.js (source)

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


Generated: Thu Nov 21 01:00:03 2024 Cross-referenced by PHPXref 0.7.1