[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

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

   1  /*! jQuery UI - v1.12.1 - 2020-09-25
   2  * http://jqueryui.com
   3  * Includes: data.js, disable-selection.js, escape-selector.js, focusable.js, form-reset-mixin.js, form.js, ie.js, jquery-1-7.js, keycode.js, labels.js, plugin.js, position.js, safe-active-element.js, safe-blur.js, scroll-parent.js, tabbable.js, unique-id.js, version.js, widget.js
   4  * Copyright jQuery Foundation and other contributors; Licensed  */
   5  ( function( factory ) {
   6      if ( typeof define === "function" && define.amd ) {
   7  
   8          // AMD. Register as an anonymous module.
   9          define( [ "jquery" ], factory );
  10      } else {
  11  
  12          // Browser globals
  13          factory( jQuery );
  14      }
  15  } ( function( $ ) {
  16  
  17  // Source: version.js
  18  $.ui = $.ui || {};
  19  
  20  $.ui.version = "1.12.1";
  21  
  22  // Source: data.js
  23  /*!
  24   * jQuery UI :data 1.12.1
  25   * http://jqueryui.com
  26   *
  27   * Copyright jQuery Foundation and other contributors
  28   * Released under the MIT license.
  29   * http://jquery.org/license
  30   */
  31  
  32  //>>label: :data Selector
  33  //>>group: Core
  34  //>>description: Selects elements which have data stored under the specified key.
  35  //>>docs: http://api.jqueryui.com/data-selector/
  36  
  37  $.extend( $.expr[ ":" ], {
  38      data: $.expr.createPseudo ?
  39          $.expr.createPseudo( function( dataName ) {
  40              return function( elem ) {
  41                  return !!$.data( elem, dataName );
  42              };
  43          } ) :
  44  
  45          // Support: jQuery <1.8
  46          function( elem, i, match ) {
  47              return !!$.data( elem, match[ 3 ] );
  48          }
  49  } );
  50  
  51  
  52  // Source: disable-selection.js
  53  /*!
  54   * jQuery UI Disable Selection 1.12.1
  55   * http://jqueryui.com
  56   *
  57   * Copyright jQuery Foundation and other contributors
  58   * Released under the MIT license.
  59   * http://jquery.org/license
  60   */
  61  
  62  //>>label: disableSelection
  63  //>>group: Core
  64  //>>description: Disable selection of text content within the set of matched elements.
  65  //>>docs: http://api.jqueryui.com/disableSelection/
  66  
  67  // This file is deprecated
  68  $.fn.extend( {
  69      disableSelection: ( function() {
  70          var eventType = "onselectstart" in document.createElement( "div" ) ?
  71              "selectstart" :
  72              "mousedown";
  73  
  74          return function() {
  75              return this.on( eventType + ".ui-disableSelection", function( event ) {
  76                  event.preventDefault();
  77              } );
  78          };
  79      } )(),
  80  
  81      enableSelection: function() {
  82          return this.off( ".ui-disableSelection" );
  83      }
  84  } );
  85  
  86  // Source: escape-selector.js
  87  // Internal use only
  88  $.ui.escapeSelector = ( function() {
  89      var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
  90      return function( selector ) {
  91          return selector.replace( selectorEscape, "\\$1" );
  92      };
  93  } )();
  94  
  95  // Source: focusable.js
  96  /*!
  97   * jQuery UI Focusable 1.12.1
  98   * http://jqueryui.com
  99   *
 100   * Copyright jQuery Foundation and other contributors
 101   * Released under the MIT license.
 102   * http://jquery.org/license
 103   */
 104  
 105  //>>label: :focusable Selector
 106  //>>group: Core
 107  //>>description: Selects elements which can be focused.
 108  //>>docs: http://api.jqueryui.com/focusable-selector/
 109  
 110  // Selectors
 111  $.ui.focusable = function( element, hasTabindex ) {
 112      var map, mapName, img, focusableIfVisible, fieldset,
 113          nodeName = element.nodeName.toLowerCase();
 114  
 115      if ( "area" === nodeName ) {
 116          map = element.parentNode;
 117          mapName = map.name;
 118          if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
 119              return false;
 120          }
 121          img = $( "img[usemap='#" + mapName + "']" );
 122          return img.length > 0 && img.is( ":visible" );
 123      }
 124  
 125      if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
 126          focusableIfVisible = !element.disabled;
 127  
 128          if ( focusableIfVisible ) {
 129  
 130              // Form controls within a disabled fieldset are disabled.
 131              // However, controls within the fieldset's legend do not get disabled.
 132              // Since controls generally aren't placed inside legends, we skip
 133              // this portion of the check.
 134              fieldset = $( element ).closest( "fieldset" )[ 0 ];
 135              if ( fieldset ) {
 136                  focusableIfVisible = !fieldset.disabled;
 137              }
 138          }
 139      } else if ( "a" === nodeName ) {
 140          focusableIfVisible = element.href || hasTabindex;
 141      } else {
 142          focusableIfVisible = hasTabindex;
 143      }
 144  
 145      return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
 146  };
 147  
 148  // Support: IE 8 only
 149  // IE 8 doesn't resolve inherit to visible/hidden for computed values
 150  function visible( element ) {
 151      var visibility = element.css( "visibility" );
 152      while ( visibility === "inherit" ) {
 153          element = element.parent();
 154          visibility = element.css( "visibility" );
 155      }
 156      return visibility !== "hidden";
 157  }
 158  
 159  $.extend( $.expr[ ":" ], {
 160      focusable: function( element ) {
 161          return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
 162      }
 163  } );
 164  
 165  // Source: form.js
 166  // Support: IE8 Only
 167  // IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
 168  // with a string, so we need to find the proper form.
 169  $.fn.form = function() {
 170      return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
 171  };
 172  
 173  // Source: form-reset-mixin.js
 174  /*!
 175   * jQuery UI Form Reset Mixin 1.12.1
 176   * http://jqueryui.com
 177   *
 178   * Copyright jQuery Foundation and other contributors
 179   * Released under the MIT license.
 180   * http://jquery.org/license
 181   */
 182  
 183  //>>label: Form Reset Mixin
 184  //>>group: Core
 185  //>>description: Refresh input widgets when their form is reset
 186  //>>docs: http://api.jqueryui.com/form-reset-mixin/
 187  
 188  $.ui.formResetMixin = {
 189      _formResetHandler: function() {
 190          var form = $( this );
 191  
 192          // Wait for the form reset to actually happen before refreshing
 193          setTimeout( function() {
 194              var instances = form.data( "ui-form-reset-instances" );
 195              $.each( instances, function() {
 196                  this.refresh();
 197              } );
 198          } );
 199      },
 200  
 201      _bindFormResetHandler: function() {
 202          this.form = this.element.form();
 203          if ( !this.form.length ) {
 204              return;
 205          }
 206  
 207          var instances = this.form.data( "ui-form-reset-instances" ) || [];
 208          if ( !instances.length ) {
 209  
 210              // We don't use _on() here because we use a single event handler per form
 211              this.form.on( "reset.ui-form-reset", this._formResetHandler );
 212          }
 213          instances.push( this );
 214          this.form.data( "ui-form-reset-instances", instances );
 215      },
 216  
 217      _unbindFormResetHandler: function() {
 218          if ( !this.form.length ) {
 219              return;
 220          }
 221  
 222          var instances = this.form.data( "ui-form-reset-instances" );
 223          instances.splice( $.inArray( this, instances ), 1 );
 224          if ( instances.length ) {
 225              this.form.data( "ui-form-reset-instances", instances );
 226          } else {
 227              this.form
 228                  .removeData( "ui-form-reset-instances" )
 229                  .off( "reset.ui-form-reset" );
 230          }
 231      }
 232  };
 233  
 234  // Source: ie.js
 235  // This file is deprecated
 236  $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
 237  
 238  // Source: jquery-1-7.js
 239  /*!
 240   * jQuery UI Support for jQuery core 1.7.x 1.12.1
 241   * http://jqueryui.com
 242   *
 243   * Copyright jQuery Foundation and other contributors
 244   * Released under the MIT license.
 245   * http://jquery.org/license
 246   *
 247   */
 248  
 249  //>>label: jQuery 1.7 Support
 250  //>>group: Core
 251  //>>description: Support version 1.7.x of jQuery core
 252  
 253  // Support: jQuery 1.7 only
 254  // Not a great way to check versions, but since we only support 1.7+ and only
 255  // need to detect <1.8, this is a simple check that should suffice. Checking
 256  // for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0
 257  // and we'll never reach 1.70.0 (if we do, we certainly won't be supporting
 258  // 1.7 anymore). See #11197 for why we're not using feature detection.
 259  if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
 260  
 261      // Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()
 262      // Unlike jQuery Core 1.8+, these only support numeric values to set the
 263      // dimensions in pixels
 264      $.each( [ "Width", "Height" ], function( i, name ) {
 265          var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
 266              type = name.toLowerCase(),
 267              orig = {
 268                  innerWidth: $.fn.innerWidth,
 269                  innerHeight: $.fn.innerHeight,
 270                  outerWidth: $.fn.outerWidth,
 271                  outerHeight: $.fn.outerHeight
 272              };
 273  
 274  		function reduce( elem, size, border, margin ) {
 275              $.each( side, function() {
 276                  size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
 277                  if ( border ) {
 278                      size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
 279                  }
 280                  if ( margin ) {
 281                      size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
 282                  }
 283              } );
 284              return size;
 285          }
 286  
 287          $.fn[ "inner" + name ] = function( size ) {
 288              if ( size === undefined ) {
 289                  return orig[ "inner" + name ].call( this );
 290              }
 291  
 292              return this.each( function() {
 293                  $( this ).css( type, reduce( this, size ) + "px" );
 294              } );
 295          };
 296  
 297          $.fn[ "outer" + name ] = function( size, margin ) {
 298              if ( typeof size !== "number" ) {
 299                  return orig[ "outer" + name ].call( this, size );
 300              }
 301  
 302              return this.each( function() {
 303                  $( this ).css( type, reduce( this, size, true, margin ) + "px" );
 304              } );
 305          };
 306      } );
 307  
 308      $.fn.addBack = function( selector ) {
 309          return this.add( selector == null ?
 310              this.prevObject : this.prevObject.filter( selector )
 311          );
 312      };
 313  }
 314  
 315  // Source: keycode.js
 316  /*!
 317   * jQuery UI Keycode 1.12.1
 318   * http://jqueryui.com
 319   *
 320   * Copyright jQuery Foundation and other contributors
 321   * Released under the MIT license.
 322   * http://jquery.org/license
 323   */
 324  
 325  //>>label: Keycode
 326  //>>group: Core
 327  //>>description: Provide keycodes as keynames
 328  //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
 329  
 330  $.ui.keyCode = {
 331      BACKSPACE: 8,
 332      COMMA: 188,
 333      DELETE: 46,
 334      DOWN: 40,
 335      END: 35,
 336      ENTER: 13,
 337      ESCAPE: 27,
 338      HOME: 36,
 339      LEFT: 37,
 340      PAGE_DOWN: 34,
 341      PAGE_UP: 33,
 342      PERIOD: 190,
 343      RIGHT: 39,
 344      SPACE: 32,
 345      TAB: 9,
 346      UP: 38
 347  };
 348  
 349  // Source: labels.js
 350  /*!
 351   * jQuery UI Labels 1.12.1
 352   * http://jqueryui.com
 353   *
 354   * Copyright jQuery Foundation and other contributors
 355   * Released under the MIT license.
 356   * http://jquery.org/license
 357   */
 358  
 359  //>>label: labels
 360  //>>group: Core
 361  //>>description: Find all the labels associated with a given input
 362  //>>docs: http://api.jqueryui.com/labels/
 363  
 364  $.fn.labels = function() {
 365      var ancestor, selector, id, labels, ancestors;
 366  
 367      // Check control.labels first
 368      if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
 369          return this.pushStack( this[ 0 ].labels );
 370      }
 371  
 372      // Support: IE <= 11, FF <= 37, Android <= 2.3 only
 373      // Above browsers do not support control.labels. Everything below is to support them
 374      // as well as document fragments. control.labels does not work on document fragments
 375      labels = this.eq( 0 ).parents( "label" );
 376  
 377      // Look for the label based on the id
 378      id = this.attr( "id" );
 379      if ( id ) {
 380  
 381          // We don't search against the document in case the element
 382          // is disconnected from the DOM
 383          ancestor = this.eq( 0 ).parents().last();
 384  
 385          // Get a full set of top level ancestors
 386          ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
 387  
 388          // Create a selector for the label based on the id
 389          selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
 390  
 391          labels = labels.add( ancestors.find( selector ).addBack( selector ) );
 392  
 393      }
 394  
 395      // Return whatever we have found for labels
 396      return this.pushStack( labels );
 397  };
 398  
 399  // Source: plugin.js
 400  // $.ui.plugin is deprecated. Use $.widget() extensions instead.
 401  $.ui.plugin = {
 402      add: function( module, option, set ) {
 403          var i,
 404              proto = $.ui[ module ].prototype;
 405          for ( i in set ) {
 406              proto.plugins[ i ] = proto.plugins[ i ] || [];
 407              proto.plugins[ i ].push( [ option, set[ i ] ] );
 408          }
 409      },
 410      call: function( instance, name, args, allowDisconnected ) {
 411          var i,
 412              set = instance.plugins[ name ];
 413  
 414          if ( !set ) {
 415              return;
 416          }
 417  
 418          if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
 419                  instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
 420              return;
 421          }
 422  
 423          for ( i = 0; i < set.length; i++ ) {
 424              if ( instance.options[ set[ i ][ 0 ] ] ) {
 425                  set[ i ][ 1 ].apply( instance.element, args );
 426              }
 427          }
 428      }
 429  };
 430  
 431  // Source: position.js
 432  /*!
 433   * jQuery UI Position 1.12.1
 434   * http://jqueryui.com
 435   *
 436   * Copyright jQuery Foundation and other contributors
 437   * Released under the MIT license.
 438   * http://jquery.org/license
 439   *
 440   * http://api.jqueryui.com/position/
 441   */
 442  
 443  //>>label: Position
 444  //>>group: Core
 445  //>>description: Positions elements relative to other elements.
 446  //>>docs: http://api.jqueryui.com/position/
 447  //>>demos: http://jqueryui.com/position/
 448  
 449  ( function() {
 450  var cachedScrollbarWidth,
 451      max = Math.max,
 452      abs = Math.abs,
 453      rhorizontal = /left|center|right/,
 454      rvertical = /top|center|bottom/,
 455      roffset = /[\+\-]\d+(\.[\d]+)?%?/,
 456      rposition = /^\w+/,
 457      rpercent = /%$/,
 458      _position = $.fn.position;
 459  
 460  function getOffsets( offsets, width, height ) {
 461      return [
 462          parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
 463          parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
 464      ];
 465  }
 466  
 467  function parseCss( element, property ) {
 468      return parseInt( $.css( element, property ), 10 ) || 0;
 469  }
 470  
 471  function getDimensions( elem ) {
 472      var raw = elem[ 0 ];
 473      if ( raw.nodeType === 9 ) {
 474          return {
 475              width: elem.width(),
 476              height: elem.height(),
 477              offset: { top: 0, left: 0 }
 478          };
 479      }
 480      if ( $.isWindow( raw ) ) {
 481          return {
 482              width: elem.width(),
 483              height: elem.height(),
 484              offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
 485          };
 486      }
 487      if ( raw.preventDefault ) {
 488          return {
 489              width: 0,
 490              height: 0,
 491              offset: { top: raw.pageY, left: raw.pageX }
 492          };
 493      }
 494      return {
 495          width: elem.outerWidth(),
 496          height: elem.outerHeight(),
 497          offset: elem.offset()
 498      };
 499  }
 500  
 501  $.position = {
 502      scrollbarWidth: function() {
 503          if ( cachedScrollbarWidth !== undefined ) {
 504              return cachedScrollbarWidth;
 505          }
 506          var w1, w2,
 507              div = $( "<div " +
 508                  "style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
 509                  "<div style='height:100px;width:auto;'></div></div>" ),
 510              innerDiv = div.children()[ 0 ];
 511  
 512          $( "body" ).append( div );
 513          w1 = innerDiv.offsetWidth;
 514          div.css( "overflow", "scroll" );
 515  
 516          w2 = innerDiv.offsetWidth;
 517  
 518          if ( w1 === w2 ) {
 519              w2 = div[ 0 ].clientWidth;
 520          }
 521  
 522          div.remove();
 523  
 524          return ( cachedScrollbarWidth = w1 - w2 );
 525      },
 526      getScrollInfo: function( within ) {
 527          var overflowX = within.isWindow || within.isDocument ? "" :
 528                  within.element.css( "overflow-x" ),
 529              overflowY = within.isWindow || within.isDocument ? "" :
 530                  within.element.css( "overflow-y" ),
 531              hasOverflowX = overflowX === "scroll" ||
 532                  ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
 533              hasOverflowY = overflowY === "scroll" ||
 534                  ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
 535          return {
 536              width: hasOverflowY ? $.position.scrollbarWidth() : 0,
 537              height: hasOverflowX ? $.position.scrollbarWidth() : 0
 538          };
 539      },
 540      getWithinInfo: function( element ) {
 541          var withinElement = $( element || window ),
 542              isWindow = $.isWindow( withinElement[ 0 ] ),
 543              isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
 544              hasOffset = !isWindow && !isDocument;
 545          return {
 546              element: withinElement,
 547              isWindow: isWindow,
 548              isDocument: isDocument,
 549              offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
 550              scrollLeft: withinElement.scrollLeft(),
 551              scrollTop: withinElement.scrollTop(),
 552              width: withinElement.outerWidth(),
 553              height: withinElement.outerHeight()
 554          };
 555      }
 556  };
 557  
 558  $.fn.position = function( options ) {
 559      if ( !options || !options.of ) {
 560          return _position.apply( this, arguments );
 561      }
 562  
 563      // Make a copy, we don't want to modify arguments
 564      options = $.extend( {}, options );
 565  
 566      var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
 567          target = $( options.of ),
 568          within = $.position.getWithinInfo( options.within ),
 569          scrollInfo = $.position.getScrollInfo( within ),
 570          collision = ( options.collision || "flip" ).split( " " ),
 571          offsets = {};
 572  
 573      dimensions = getDimensions( target );
 574      if ( target[ 0 ].preventDefault ) {
 575  
 576          // Force left top to allow flipping
 577          options.at = "left top";
 578      }
 579      targetWidth = dimensions.width;
 580      targetHeight = dimensions.height;
 581      targetOffset = dimensions.offset;
 582  
 583      // Clone to reuse original targetOffset later
 584      basePosition = $.extend( {}, targetOffset );
 585  
 586      // Force my and at to have valid horizontal and vertical positions
 587      // if a value is missing or invalid, it will be converted to center
 588      $.each( [ "my", "at" ], function() {
 589          var pos = ( options[ this ] || "" ).split( " " ),
 590              horizontalOffset,
 591              verticalOffset;
 592  
 593          if ( pos.length === 1 ) {
 594              pos = rhorizontal.test( pos[ 0 ] ) ?
 595                  pos.concat( [ "center" ] ) :
 596                  rvertical.test( pos[ 0 ] ) ?
 597                      [ "center" ].concat( pos ) :
 598                      [ "center", "center" ];
 599          }
 600          pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
 601          pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
 602  
 603          // Calculate offsets
 604          horizontalOffset = roffset.exec( pos[ 0 ] );
 605          verticalOffset = roffset.exec( pos[ 1 ] );
 606          offsets[ this ] = [
 607              horizontalOffset ? horizontalOffset[ 0 ] : 0,
 608              verticalOffset ? verticalOffset[ 0 ] : 0
 609          ];
 610  
 611          // Reduce to just the positions without the offsets
 612          options[ this ] = [
 613              rposition.exec( pos[ 0 ] )[ 0 ],
 614              rposition.exec( pos[ 1 ] )[ 0 ]
 615          ];
 616      } );
 617  
 618      // Normalize collision option
 619      if ( collision.length === 1 ) {
 620          collision[ 1 ] = collision[ 0 ];
 621      }
 622  
 623      if ( options.at[ 0 ] === "right" ) {
 624          basePosition.left += targetWidth;
 625      } else if ( options.at[ 0 ] === "center" ) {
 626          basePosition.left += targetWidth / 2;
 627      }
 628  
 629      if ( options.at[ 1 ] === "bottom" ) {
 630          basePosition.top += targetHeight;
 631      } else if ( options.at[ 1 ] === "center" ) {
 632          basePosition.top += targetHeight / 2;
 633      }
 634  
 635      atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
 636      basePosition.left += atOffset[ 0 ];
 637      basePosition.top += atOffset[ 1 ];
 638  
 639      return this.each( function() {
 640          var collisionPosition, using,
 641              elem = $( this ),
 642              elemWidth = elem.outerWidth(),
 643              elemHeight = elem.outerHeight(),
 644              marginLeft = parseCss( this, "marginLeft" ),
 645              marginTop = parseCss( this, "marginTop" ),
 646              collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
 647                  scrollInfo.width,
 648              collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
 649                  scrollInfo.height,
 650              position = $.extend( {}, basePosition ),
 651              myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
 652  
 653          if ( options.my[ 0 ] === "right" ) {
 654              position.left -= elemWidth;
 655          } else if ( options.my[ 0 ] === "center" ) {
 656              position.left -= elemWidth / 2;
 657          }
 658  
 659          if ( options.my[ 1 ] === "bottom" ) {
 660              position.top -= elemHeight;
 661          } else if ( options.my[ 1 ] === "center" ) {
 662              position.top -= elemHeight / 2;
 663          }
 664  
 665          position.left += myOffset[ 0 ];
 666          position.top += myOffset[ 1 ];
 667  
 668          collisionPosition = {
 669              marginLeft: marginLeft,
 670              marginTop: marginTop
 671          };
 672  
 673          $.each( [ "left", "top" ], function( i, dir ) {
 674              if ( $.ui.position[ collision[ i ] ] ) {
 675                  $.ui.position[ collision[ i ] ][ dir ]( position, {
 676                      targetWidth: targetWidth,
 677                      targetHeight: targetHeight,
 678                      elemWidth: elemWidth,
 679                      elemHeight: elemHeight,
 680                      collisionPosition: collisionPosition,
 681                      collisionWidth: collisionWidth,
 682                      collisionHeight: collisionHeight,
 683                      offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
 684                      my: options.my,
 685                      at: options.at,
 686                      within: within,
 687                      elem: elem
 688                  } );
 689              }
 690          } );
 691  
 692          if ( options.using ) {
 693  
 694              // Adds feedback as second argument to using callback, if present
 695              using = function( props ) {
 696                  var left = targetOffset.left - position.left,
 697                      right = left + targetWidth - elemWidth,
 698                      top = targetOffset.top - position.top,
 699                      bottom = top + targetHeight - elemHeight,
 700                      feedback = {
 701                          target: {
 702                              element: target,
 703                              left: targetOffset.left,
 704                              top: targetOffset.top,
 705                              width: targetWidth,
 706                              height: targetHeight
 707                          },
 708                          element: {
 709                              element: elem,
 710                              left: position.left,
 711                              top: position.top,
 712                              width: elemWidth,
 713                              height: elemHeight
 714                          },
 715                          horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
 716                          vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
 717                      };
 718                  if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
 719                      feedback.horizontal = "center";
 720                  }
 721                  if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
 722                      feedback.vertical = "middle";
 723                  }
 724                  if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
 725                      feedback.important = "horizontal";
 726                  } else {
 727                      feedback.important = "vertical";
 728                  }
 729                  options.using.call( this, props, feedback );
 730              };
 731          }
 732  
 733          elem.offset( $.extend( position, { using: using } ) );
 734      } );
 735  };
 736  
 737  $.ui.position = {
 738      fit: {
 739          left: function( position, data ) {
 740              var within = data.within,
 741                  withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
 742                  outerWidth = within.width,
 743                  collisionPosLeft = position.left - data.collisionPosition.marginLeft,
 744                  overLeft = withinOffset - collisionPosLeft,
 745                  overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
 746                  newOverRight;
 747  
 748              // Element is wider than within
 749              if ( data.collisionWidth > outerWidth ) {
 750  
 751                  // Element is initially over the left side of within
 752                  if ( overLeft > 0 && overRight <= 0 ) {
 753                      newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
 754                          withinOffset;
 755                      position.left += overLeft - newOverRight;
 756  
 757                  // Element is initially over right side of within
 758                  } else if ( overRight > 0 && overLeft <= 0 ) {
 759                      position.left = withinOffset;
 760  
 761                  // Element is initially over both left and right sides of within
 762                  } else {
 763                      if ( overLeft > overRight ) {
 764                          position.left = withinOffset + outerWidth - data.collisionWidth;
 765                      } else {
 766                          position.left = withinOffset;
 767                      }
 768                  }
 769  
 770              // Too far left -> align with left edge
 771              } else if ( overLeft > 0 ) {
 772                  position.left += overLeft;
 773  
 774              // Too far right -> align with right edge
 775              } else if ( overRight > 0 ) {
 776                  position.left -= overRight;
 777  
 778              // Adjust based on position and margin
 779              } else {
 780                  position.left = max( position.left - collisionPosLeft, position.left );
 781              }
 782          },
 783          top: function( position, data ) {
 784              var within = data.within,
 785                  withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
 786                  outerHeight = data.within.height,
 787                  collisionPosTop = position.top - data.collisionPosition.marginTop,
 788                  overTop = withinOffset - collisionPosTop,
 789                  overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
 790                  newOverBottom;
 791  
 792              // Element is taller than within
 793              if ( data.collisionHeight > outerHeight ) {
 794  
 795                  // Element is initially over the top of within
 796                  if ( overTop > 0 && overBottom <= 0 ) {
 797                      newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
 798                          withinOffset;
 799                      position.top += overTop - newOverBottom;
 800  
 801                  // Element is initially over bottom of within
 802                  } else if ( overBottom > 0 && overTop <= 0 ) {
 803                      position.top = withinOffset;
 804  
 805                  // Element is initially over both top and bottom of within
 806                  } else {
 807                      if ( overTop > overBottom ) {
 808                          position.top = withinOffset + outerHeight - data.collisionHeight;
 809                      } else {
 810                          position.top = withinOffset;
 811                      }
 812                  }
 813  
 814              // Too far up -> align with top
 815              } else if ( overTop > 0 ) {
 816                  position.top += overTop;
 817  
 818              // Too far down -> align with bottom edge
 819              } else if ( overBottom > 0 ) {
 820                  position.top -= overBottom;
 821  
 822              // Adjust based on position and margin
 823              } else {
 824                  position.top = max( position.top - collisionPosTop, position.top );
 825              }
 826          }
 827      },
 828      flip: {
 829          left: function( position, data ) {
 830              var within = data.within,
 831                  withinOffset = within.offset.left + within.scrollLeft,
 832                  outerWidth = within.width,
 833                  offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
 834                  collisionPosLeft = position.left - data.collisionPosition.marginLeft,
 835                  overLeft = collisionPosLeft - offsetLeft,
 836                  overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
 837                  myOffset = data.my[ 0 ] === "left" ?
 838                      -data.elemWidth :
 839                      data.my[ 0 ] === "right" ?
 840                          data.elemWidth :
 841                          0,
 842                  atOffset = data.at[ 0 ] === "left" ?
 843                      data.targetWidth :
 844                      data.at[ 0 ] === "right" ?
 845                          -data.targetWidth :
 846                          0,
 847                  offset = -2 * data.offset[ 0 ],
 848                  newOverRight,
 849                  newOverLeft;
 850  
 851              if ( overLeft < 0 ) {
 852                  newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
 853                      outerWidth - withinOffset;
 854                  if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
 855                      position.left += myOffset + atOffset + offset;
 856                  }
 857              } else if ( overRight > 0 ) {
 858                  newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
 859                      atOffset + offset - offsetLeft;
 860                  if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
 861                      position.left += myOffset + atOffset + offset;
 862                  }
 863              }
 864          },
 865          top: function( position, data ) {
 866              var within = data.within,
 867                  withinOffset = within.offset.top + within.scrollTop,
 868                  outerHeight = within.height,
 869                  offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
 870                  collisionPosTop = position.top - data.collisionPosition.marginTop,
 871                  overTop = collisionPosTop - offsetTop,
 872                  overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
 873                  top = data.my[ 1 ] === "top",
 874                  myOffset = top ?
 875                      -data.elemHeight :
 876                      data.my[ 1 ] === "bottom" ?
 877                          data.elemHeight :
 878                          0,
 879                  atOffset = data.at[ 1 ] === "top" ?
 880                      data.targetHeight :
 881                      data.at[ 1 ] === "bottom" ?
 882                          -data.targetHeight :
 883                          0,
 884                  offset = -2 * data.offset[ 1 ],
 885                  newOverTop,
 886                  newOverBottom;
 887              if ( overTop < 0 ) {
 888                  newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
 889                      outerHeight - withinOffset;
 890                  if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
 891                      position.top += myOffset + atOffset + offset;
 892                  }
 893              } else if ( overBottom > 0 ) {
 894                  newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
 895                      offset - offsetTop;
 896                  if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
 897                      position.top += myOffset + atOffset + offset;
 898                  }
 899              }
 900          }
 901      },
 902      flipfit: {
 903          left: function() {
 904              $.ui.position.flip.left.apply( this, arguments );
 905              $.ui.position.fit.left.apply( this, arguments );
 906          },
 907          top: function() {
 908              $.ui.position.flip.top.apply( this, arguments );
 909              $.ui.position.fit.top.apply( this, arguments );
 910          }
 911      }
 912  };
 913  
 914  } )();
 915  
 916  // Source: safe-active-element.js
 917  $.ui.safeActiveElement = function( document ) {
 918      var activeElement;
 919  
 920      // Support: IE 9 only
 921      // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
 922      try {
 923          activeElement = document.activeElement;
 924      } catch ( error ) {
 925          activeElement = document.body;
 926      }
 927  
 928      // Support: IE 9 - 11 only
 929      // IE may return null instead of an element
 930      // Interestingly, this only seems to occur when NOT in an iframe
 931      if ( !activeElement ) {
 932          activeElement = document.body;
 933      }
 934  
 935      // Support: IE 11 only
 936      // IE11 returns a seemingly empty object in some cases when accessing
 937      // document.activeElement from an <iframe>
 938      if ( !activeElement.nodeName ) {
 939          activeElement = document.body;
 940      }
 941  
 942      return activeElement;
 943  };
 944  
 945  // Source: safe-blur.js
 946  $.ui.safeBlur = function( element ) {
 947  
 948      // Support: IE9 - 10 only
 949      // If the <body> is blurred, IE will switch windows, see #9420
 950      if ( element && element.nodeName.toLowerCase() !== "body" ) {
 951          $( element ).trigger( "blur" );
 952      }
 953  };
 954  
 955  // Source: scroll-parent.js
 956  /*!
 957   * jQuery UI Scroll Parent 1.12.1
 958   * http://jqueryui.com
 959   *
 960   * Copyright jQuery Foundation and other contributors
 961   * Released under the MIT license.
 962   * http://jquery.org/license
 963   */
 964  
 965  //>>label: scrollParent
 966  //>>group: Core
 967  //>>description: Get the closest ancestor element that is scrollable.
 968  //>>docs: http://api.jqueryui.com/scrollParent/
 969  
 970  $.fn.scrollParent = function( includeHidden ) {
 971      var position = this.css( "position" ),
 972          excludeStaticParent = position === "absolute",
 973          overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
 974          scrollParent = this.parents().filter( function() {
 975              var parent = $( this );
 976              if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
 977                  return false;
 978              }
 979              return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
 980                  parent.css( "overflow-x" ) );
 981          } ).eq( 0 );
 982  
 983      return position === "fixed" || !scrollParent.length ?
 984          $( this[ 0 ].ownerDocument || document ) :
 985          scrollParent;
 986  };
 987  
 988  // Source: tabbable.js
 989  /*!
 990   * jQuery UI Tabbable 1.12.1
 991   * http://jqueryui.com
 992   *
 993   * Copyright jQuery Foundation and other contributors
 994   * Released under the MIT license.
 995   * http://jquery.org/license
 996   */
 997  
 998  //>>label: :tabbable Selector
 999  //>>group: Core
1000  //>>description: Selects elements which can be tabbed to.
1001  //>>docs: http://api.jqueryui.com/tabbable-selector/
1002  
1003  $.extend( $.expr[ ":" ], {
1004      tabbable: function( element ) {
1005          var tabIndex = $.attr( element, "tabindex" ),
1006              hasTabindex = tabIndex != null;
1007          return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
1008      }
1009  } );
1010  
1011  // Source: unique-id.js
1012  /*!
1013   * jQuery UI Unique ID 1.12.1
1014   * http://jqueryui.com
1015   *
1016   * Copyright jQuery Foundation and other contributors
1017   * Released under the MIT license.
1018   * http://jquery.org/license
1019   */
1020  
1021  //>>label: uniqueId
1022  //>>group: Core
1023  //>>description: Functions to generate and remove uniqueId's
1024  //>>docs: http://api.jqueryui.com/uniqueId/
1025  
1026  $.fn.extend( {
1027      uniqueId: ( function() {
1028          var uuid = 0;
1029  
1030          return function() {
1031              return this.each( function() {
1032                  if ( !this.id ) {
1033                      this.id = "ui-id-" + ( ++uuid );
1034                  }
1035              } );
1036          };
1037      } )(),
1038  
1039      removeUniqueId: function() {
1040          return this.each( function() {
1041              if ( /^ui-id-\d+$/.test( this.id ) ) {
1042                  $( this ).removeAttr( "id" );
1043              }
1044          } );
1045      }
1046  } );
1047  
1048  // Source: widget.js
1049  /*!
1050   * jQuery UI Widget 1.12.1
1051   * http://jqueryui.com
1052   *
1053   * Copyright jQuery Foundation and other contributors
1054   * Released under the MIT license.
1055   * http://jquery.org/license
1056   */
1057  
1058  //>>label: Widget
1059  //>>group: Core
1060  //>>description: Provides a factory for creating stateful widgets with a common API.
1061  //>>docs: http://api.jqueryui.com/jQuery.widget/
1062  //>>demos: http://jqueryui.com/widget/
1063  
1064  var widgetUuid = 0;
1065  var widgetSlice = Array.prototype.slice;
1066  
1067  $.cleanData = ( function( orig ) {
1068      return function( elems ) {
1069          var events, elem, i;
1070          for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
1071              try {
1072  
1073                  // Only trigger remove when necessary to save time
1074                  events = $._data( elem, "events" );
1075                  if ( events && events.remove ) {
1076                      $( elem ).triggerHandler( "remove" );
1077                  }
1078  
1079              // Http://bugs.jquery.com/ticket/8235
1080              } catch ( e ) {}
1081          }
1082          orig( elems );
1083      };
1084  } )( $.cleanData );
1085  
1086  $.widget = function( name, base, prototype ) {
1087      var existingConstructor, constructor, basePrototype;
1088  
1089      // ProxiedPrototype allows the provided prototype to remain unmodified
1090      // so that it can be used as a mixin for multiple widgets (#8876)
1091      var proxiedPrototype = {};
1092  
1093      var namespace = name.split( "." )[ 0 ];
1094      name = name.split( "." )[ 1 ];
1095      var fullName = namespace + "-" + name;
1096  
1097      if ( !prototype ) {
1098          prototype = base;
1099          base = $.Widget;
1100      }
1101  
1102      if ( $.isArray( prototype ) ) {
1103          prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
1104      }
1105  
1106      // Create selector for plugin
1107      $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
1108          return !!$.data( elem, fullName );
1109      };
1110  
1111      $[ namespace ] = $[ namespace ] || {};
1112      existingConstructor = $[ namespace ][ name ];
1113      constructor = $[ namespace ][ name ] = function( options, element ) {
1114  
1115          // Allow instantiation without "new" keyword
1116          if ( !this._createWidget ) {
1117              return new constructor( options, element );
1118          }
1119  
1120          // Allow instantiation without initializing for simple inheritance
1121          // must use "new" keyword (the code above always passes args)
1122          if ( arguments.length ) {
1123              this._createWidget( options, element );
1124          }
1125      };
1126  
1127      // Extend with the existing constructor to carry over any static properties
1128      $.extend( constructor, existingConstructor, {
1129          version: prototype.version,
1130  
1131          // Copy the object used to create the prototype in case we need to
1132          // redefine the widget later
1133          _proto: $.extend( {}, prototype ),
1134  
1135          // Track widgets that inherit from this widget in case this widget is
1136          // redefined after a widget inherits from it
1137          _childConstructors: []
1138      } );
1139  
1140      basePrototype = new base();
1141  
1142      // We need to make the options hash a property directly on the new instance
1143      // otherwise we'll modify the options hash on the prototype that we're
1144      // inheriting from
1145      basePrototype.options = $.widget.extend( {}, basePrototype.options );
1146      $.each( prototype, function( prop, value ) {
1147          if ( !$.isFunction( value ) ) {
1148              proxiedPrototype[ prop ] = value;
1149              return;
1150          }
1151          proxiedPrototype[ prop ] = ( function() {
1152  			function _super() {
1153                  return base.prototype[ prop ].apply( this, arguments );
1154              }
1155  
1156  			function _superApply( args ) {
1157                  return base.prototype[ prop ].apply( this, args );
1158              }
1159  
1160              return function() {
1161                  var __super = this._super;
1162                  var __superApply = this._superApply;
1163                  var returnValue;
1164  
1165                  this._super = _super;
1166                  this._superApply = _superApply;
1167  
1168                  returnValue = value.apply( this, arguments );
1169  
1170                  this._super = __super;
1171                  this._superApply = __superApply;
1172  
1173                  return returnValue;
1174              };
1175          } )();
1176      } );
1177      constructor.prototype = $.widget.extend( basePrototype, {
1178  
1179          // TODO: remove support for widgetEventPrefix
1180          // always use the name + a colon as the prefix, e.g., draggable:start
1181          // don't prefix for widgets that aren't DOM-based
1182          widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
1183      }, proxiedPrototype, {
1184          constructor: constructor,
1185          namespace: namespace,
1186          widgetName: name,
1187          widgetFullName: fullName
1188      } );
1189  
1190      // If this widget is being redefined then we need to find all widgets that
1191      // are inheriting from it and redefine all of them so that they inherit from
1192      // the new version of this widget. We're essentially trying to replace one
1193      // level in the prototype chain.
1194      if ( existingConstructor ) {
1195          $.each( existingConstructor._childConstructors, function( i, child ) {
1196              var childPrototype = child.prototype;
1197  
1198              // Redefine the child widget using the same prototype that was
1199              // originally used, but inherit from the new version of the base
1200              $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
1201                  child._proto );
1202          } );
1203  
1204          // Remove the list of existing child constructors from the old constructor
1205          // so the old child constructors can be garbage collected
1206          delete existingConstructor._childConstructors;
1207      } else {
1208          base._childConstructors.push( constructor );
1209      }
1210  
1211      $.widget.bridge( name, constructor );
1212  
1213      return constructor;
1214  };
1215  
1216  $.widget.extend = function( target ) {
1217      var input = widgetSlice.call( arguments, 1 );
1218      var inputIndex = 0;
1219      var inputLength = input.length;
1220      var key;
1221      var value;
1222  
1223      for ( ; inputIndex < inputLength; inputIndex++ ) {
1224          for ( key in input[ inputIndex ] ) {
1225              value = input[ inputIndex ][ key ];
1226              if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
1227  
1228                  // Clone objects
1229                  if ( $.isPlainObject( value ) ) {
1230                      target[ key ] = $.isPlainObject( target[ key ] ) ?
1231                          $.widget.extend( {}, target[ key ], value ) :
1232  
1233                          // Don't extend strings, arrays, etc. with objects
1234                          $.widget.extend( {}, value );
1235  
1236                  // Copy everything else by reference
1237                  } else {
1238                      target[ key ] = value;
1239                  }
1240              }
1241          }
1242      }
1243      return target;
1244  };
1245  
1246  $.widget.bridge = function( name, object ) {
1247      var fullName = object.prototype.widgetFullName || name;
1248      $.fn[ name ] = function( options ) {
1249          var isMethodCall = typeof options === "string";
1250          var args = widgetSlice.call( arguments, 1 );
1251          var returnValue = this;
1252  
1253          if ( isMethodCall ) {
1254  
1255              // If this is an empty collection, we need to have the instance method
1256              // return undefined instead of the jQuery instance
1257              if ( !this.length && options === "instance" ) {
1258                  returnValue = undefined;
1259              } else {
1260                  this.each( function() {
1261                      var methodValue;
1262                      var instance = $.data( this, fullName );
1263  
1264                      if ( options === "instance" ) {
1265                          returnValue = instance;
1266                          return false;
1267                      }
1268  
1269                      if ( !instance ) {
1270                          return $.error( "cannot call methods on " + name +
1271                              " prior to initialization; " +
1272                              "attempted to call method '" + options + "'" );
1273                      }
1274  
1275                      if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
1276                          return $.error( "no such method '" + options + "' for " + name +
1277                              " widget instance" );
1278                      }
1279  
1280                      methodValue = instance[ options ].apply( instance, args );
1281  
1282                      if ( methodValue !== instance && methodValue !== undefined ) {
1283                          returnValue = methodValue && methodValue.jquery ?
1284                              returnValue.pushStack( methodValue.get() ) :
1285                              methodValue;
1286                          return false;
1287                      }
1288                  } );
1289              }
1290          } else {
1291  
1292              // Allow multiple hashes to be passed on init
1293              if ( args.length ) {
1294                  options = $.widget.extend.apply( null, [ options ].concat( args ) );
1295              }
1296  
1297              this.each( function() {
1298                  var instance = $.data( this, fullName );
1299                  if ( instance ) {
1300                      instance.option( options || {} );
1301                      if ( instance._init ) {
1302                          instance._init();
1303                      }
1304                  } else {
1305                      $.data( this, fullName, new object( options, this ) );
1306                  }
1307              } );
1308          }
1309  
1310          return returnValue;
1311      };
1312  };
1313  
1314  $.Widget = function( /* options, element */ ) {};
1315  $.Widget._childConstructors = [];
1316  
1317  $.Widget.prototype = {
1318      widgetName: "widget",
1319      widgetEventPrefix: "",
1320      defaultElement: "<div>",
1321  
1322      options: {
1323          classes: {},
1324          disabled: false,
1325  
1326          // Callbacks
1327          create: null
1328      },
1329  
1330      _createWidget: function( options, element ) {
1331          element = $( element || this.defaultElement || this )[ 0 ];
1332          this.element = $( element );
1333          this.uuid = widgetUuid++;
1334          this.eventNamespace = "." + this.widgetName + this.uuid;
1335  
1336          this.bindings = $();
1337          this.hoverable = $();
1338          this.focusable = $();
1339          this.classesElementLookup = {};
1340  
1341          if ( element !== this ) {
1342              $.data( element, this.widgetFullName, this );
1343              this._on( true, this.element, {
1344                  remove: function( event ) {
1345                      if ( event.target === element ) {
1346                          this.destroy();
1347                      }
1348                  }
1349              } );
1350              this.document = $( element.style ?
1351  
1352                  // Element within the document
1353                  element.ownerDocument :
1354  
1355                  // Element is window or document
1356                  element.document || element );
1357              this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
1358          }
1359  
1360          this.options = $.widget.extend( {},
1361              this.options,
1362              this._getCreateOptions(),
1363              options );
1364  
1365          this._create();
1366  
1367          if ( this.options.disabled ) {
1368              this._setOptionDisabled( this.options.disabled );
1369          }
1370  
1371          this._trigger( "create", null, this._getCreateEventData() );
1372          this._init();
1373      },
1374  
1375      _getCreateOptions: function() {
1376          return {};
1377      },
1378  
1379      _getCreateEventData: $.noop,
1380  
1381      _create: $.noop,
1382  
1383      _init: $.noop,
1384  
1385      destroy: function() {
1386          var that = this;
1387  
1388          this._destroy();
1389          $.each( this.classesElementLookup, function( key, value ) {
1390              that._removeClass( value, key );
1391          } );
1392  
1393          // We can probably remove the unbind calls in 2.0
1394          // all event bindings should go through this._on()
1395          this.element
1396              .off( this.eventNamespace )
1397              .removeData( this.widgetFullName );
1398          this.widget()
1399              .off( this.eventNamespace )
1400              .removeAttr( "aria-disabled" );
1401  
1402          // Clean up events and states
1403          this.bindings.off( this.eventNamespace );
1404      },
1405  
1406      _destroy: $.noop,
1407  
1408      widget: function() {
1409          return this.element;
1410      },
1411  
1412      option: function( key, value ) {
1413          var options = key;
1414          var parts;
1415          var curOption;
1416          var i;
1417  
1418          if ( arguments.length === 0 ) {
1419  
1420              // Don't return a reference to the internal hash
1421              return $.widget.extend( {}, this.options );
1422          }
1423  
1424          if ( typeof key === "string" ) {
1425  
1426              // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
1427              options = {};
1428              parts = key.split( "." );
1429              key = parts.shift();
1430              if ( parts.length ) {
1431                  curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
1432                  for ( i = 0; i < parts.length - 1; i++ ) {
1433                      curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
1434                      curOption = curOption[ parts[ i ] ];
1435                  }
1436                  key = parts.pop();
1437                  if ( arguments.length === 1 ) {
1438                      return curOption[ key ] === undefined ? null : curOption[ key ];
1439                  }
1440                  curOption[ key ] = value;
1441              } else {
1442                  if ( arguments.length === 1 ) {
1443                      return this.options[ key ] === undefined ? null : this.options[ key ];
1444                  }
1445                  options[ key ] = value;
1446              }
1447          }
1448  
1449          this._setOptions( options );
1450  
1451          return this;
1452      },
1453  
1454      _setOptions: function( options ) {
1455          var key;
1456  
1457          for ( key in options ) {
1458              this._setOption( key, options[ key ] );
1459          }
1460  
1461          return this;
1462      },
1463  
1464      _setOption: function( key, value ) {
1465          if ( key === "classes" ) {
1466              this._setOptionClasses( value );
1467          }
1468  
1469          this.options[ key ] = value;
1470  
1471          if ( key === "disabled" ) {
1472              this._setOptionDisabled( value );
1473          }
1474  
1475          return this;
1476      },
1477  
1478      _setOptionClasses: function( value ) {
1479          var classKey, elements, currentElements;
1480  
1481          for ( classKey in value ) {
1482              currentElements = this.classesElementLookup[ classKey ];
1483              if ( value[ classKey ] === this.options.classes[ classKey ] ||
1484                      !currentElements ||
1485                      !currentElements.length ) {
1486                  continue;
1487              }
1488  
1489              // We are doing this to create a new jQuery object because the _removeClass() call
1490              // on the next line is going to destroy the reference to the current elements being
1491              // tracked. We need to save a copy of this collection so that we can add the new classes
1492              // below.
1493              elements = $( currentElements.get() );
1494              this._removeClass( currentElements, classKey );
1495  
1496              // We don't use _addClass() here, because that uses this.options.classes
1497              // for generating the string of classes. We want to use the value passed in from
1498              // _setOption(), this is the new value of the classes option which was passed to
1499              // _setOption(). We pass this value directly to _classes().
1500              elements.addClass( this._classes( {
1501                  element: elements,
1502                  keys: classKey,
1503                  classes: value,
1504                  add: true
1505              } ) );
1506          }
1507      },
1508  
1509      _setOptionDisabled: function( value ) {
1510          this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
1511  
1512          // If the widget is becoming disabled, then nothing is interactive
1513          if ( value ) {
1514              this._removeClass( this.hoverable, null, "ui-state-hover" );
1515              this._removeClass( this.focusable, null, "ui-state-focus" );
1516          }
1517      },
1518  
1519      enable: function() {
1520          return this._setOptions( { disabled: false } );
1521      },
1522  
1523      disable: function() {
1524          return this._setOptions( { disabled: true } );
1525      },
1526  
1527      _classes: function( options ) {
1528          var full = [];
1529          var that = this;
1530  
1531          options = $.extend( {
1532              element: this.element,
1533              classes: this.options.classes || {}
1534          }, options );
1535  
1536  		function processClassString( classes, checkOption ) {
1537              var current, i;
1538              for ( i = 0; i < classes.length; i++ ) {
1539                  current = that.classesElementLookup[ classes[ i ] ] || $();
1540                  if ( options.add ) {
1541                      current = $( $.unique( current.get().concat( options.element.get() ) ) );
1542                  } else {
1543                      current = $( current.not( options.element ).get() );
1544                  }
1545                  that.classesElementLookup[ classes[ i ] ] = current;
1546                  full.push( classes[ i ] );
1547                  if ( checkOption && options.classes[ classes[ i ] ] ) {
1548                      full.push( options.classes[ classes[ i ] ] );
1549                  }
1550              }
1551          }
1552  
1553          this._on( options.element, {
1554              "remove": "_untrackClassesElement"
1555          } );
1556  
1557          if ( options.keys ) {
1558              processClassString( options.keys.match( /\S+/g ) || [], true );
1559          }
1560          if ( options.extra ) {
1561              processClassString( options.extra.match( /\S+/g ) || [] );
1562          }
1563  
1564          return full.join( " " );
1565      },
1566  
1567      _untrackClassesElement: function( event ) {
1568          var that = this;
1569          $.each( that.classesElementLookup, function( key, value ) {
1570              if ( $.inArray( event.target, value ) !== -1 ) {
1571                  that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
1572              }
1573          } );
1574      },
1575  
1576      _removeClass: function( element, keys, extra ) {
1577          return this._toggleClass( element, keys, extra, false );
1578      },
1579  
1580      _addClass: function( element, keys, extra ) {
1581          return this._toggleClass( element, keys, extra, true );
1582      },
1583  
1584      _toggleClass: function( element, keys, extra, add ) {
1585          add = ( typeof add === "boolean" ) ? add : extra;
1586          var shift = ( typeof element === "string" || element === null ),
1587              options = {
1588                  extra: shift ? keys : extra,
1589                  keys: shift ? element : keys,
1590                  element: shift ? this.element : element,
1591                  add: add
1592              };
1593          options.element.toggleClass( this._classes( options ), add );
1594          return this;
1595      },
1596  
1597      _on: function( suppressDisabledCheck, element, handlers ) {
1598          var delegateElement;
1599          var instance = this;
1600  
1601          // No suppressDisabledCheck flag, shuffle arguments
1602          if ( typeof suppressDisabledCheck !== "boolean" ) {
1603              handlers = element;
1604              element = suppressDisabledCheck;
1605              suppressDisabledCheck = false;
1606          }
1607  
1608          // No element argument, shuffle and use this.element
1609          if ( !handlers ) {
1610              handlers = element;
1611              element = this.element;
1612              delegateElement = this.widget();
1613          } else {
1614              element = delegateElement = $( element );
1615              this.bindings = this.bindings.add( element );
1616          }
1617  
1618          $.each( handlers, function( event, handler ) {
1619  			function handlerProxy() {
1620  
1621                  // Allow widgets to customize the disabled handling
1622                  // - disabled as an array instead of boolean
1623                  // - disabled class as method for disabling individual parts
1624                  if ( !suppressDisabledCheck &&
1625                          ( instance.options.disabled === true ||
1626                          $( this ).hasClass( "ui-state-disabled" ) ) ) {
1627                      return;
1628                  }
1629                  return ( typeof handler === "string" ? instance[ handler ] : handler )
1630                      .apply( instance, arguments );
1631              }
1632  
1633              // Copy the guid so direct unbinding works
1634              if ( typeof handler !== "string" ) {
1635                  handlerProxy.guid = handler.guid =
1636                      handler.guid || handlerProxy.guid || $.guid++;
1637              }
1638  
1639              var match = event.match( /^([\w:-]*)\s*(.*)$/ );
1640              var eventName = match[ 1 ] + instance.eventNamespace;
1641              var selector = match[ 2 ];
1642  
1643              if ( selector ) {
1644                  delegateElement.on( eventName, selector, handlerProxy );
1645              } else {
1646                  element.on( eventName, handlerProxy );
1647              }
1648          } );
1649      },
1650  
1651      _off: function( element, eventName ) {
1652          eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
1653              this.eventNamespace;
1654          element.off( eventName ).off( eventName );
1655  
1656          // Clear the stack to avoid memory leaks (#10056)
1657          this.bindings = $( this.bindings.not( element ).get() );
1658          this.focusable = $( this.focusable.not( element ).get() );
1659          this.hoverable = $( this.hoverable.not( element ).get() );
1660      },
1661  
1662      _delay: function( handler, delay ) {
1663  		function handlerProxy() {
1664              return ( typeof handler === "string" ? instance[ handler ] : handler )
1665                  .apply( instance, arguments );
1666          }
1667          var instance = this;
1668          return setTimeout( handlerProxy, delay || 0 );
1669      },
1670  
1671      _hoverable: function( element ) {
1672          this.hoverable = this.hoverable.add( element );
1673          this._on( element, {
1674              mouseenter: function( event ) {
1675                  this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
1676              },
1677              mouseleave: function( event ) {
1678                  this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
1679              }
1680          } );
1681      },
1682  
1683      _focusable: function( element ) {
1684          this.focusable = this.focusable.add( element );
1685          this._on( element, {
1686              focusin: function( event ) {
1687                  this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
1688              },
1689              focusout: function( event ) {
1690                  this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
1691              }
1692          } );
1693      },
1694  
1695      _trigger: function( type, event, data ) {
1696          var prop, orig;
1697          var callback = this.options[ type ];
1698  
1699          data = data || {};
1700          event = $.Event( event );
1701          event.type = ( type === this.widgetEventPrefix ?
1702              type :
1703              this.widgetEventPrefix + type ).toLowerCase();
1704  
1705          // The original event may come from any element
1706          // so we need to reset the target on the new event
1707          event.target = this.element[ 0 ];
1708  
1709          // Copy original event properties over to the new event
1710          orig = event.originalEvent;
1711          if ( orig ) {
1712              for ( prop in orig ) {
1713                  if ( !( prop in event ) ) {
1714                      event[ prop ] = orig[ prop ];
1715                  }
1716              }
1717          }
1718  
1719          this.element.trigger( event, data );
1720          return !( $.isFunction( callback ) &&
1721              callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
1722              event.isDefaultPrevented() );
1723      }
1724  };
1725  
1726  $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
1727      $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
1728          if ( typeof options === "string" ) {
1729              options = { effect: options };
1730          }
1731  
1732          var hasOptions;
1733          var effectName = !options ?
1734              method :
1735              options === true || typeof options === "number" ?
1736                  defaultEffect :
1737                  options.effect || defaultEffect;
1738  
1739          options = options || {};
1740          if ( typeof options === "number" ) {
1741              options = { duration: options };
1742          }
1743  
1744          hasOptions = !$.isEmptyObject( options );
1745          options.complete = callback;
1746  
1747          if ( options.delay ) {
1748              element.delay( options.delay );
1749          }
1750  
1751          if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
1752              element[ method ]( options );
1753          } else if ( effectName !== method && element[ effectName ] ) {
1754              element[ effectName ]( options.duration, options.easing, callback );
1755          } else {
1756              element.queue( function( next ) {
1757                  $( this )[ method ]();
1758                  if ( callback ) {
1759                      callback.call( element[ 0 ] );
1760                  }
1761                  next();
1762              } );
1763          }
1764      };
1765  } );
1766  
1767  
1768  } ) );


Generated : Thu Nov 26 08:20:02 2020 Cross-referenced by PHPXref