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


Generated : Sat Dec 21 08:20:01 2024 Cross-referenced by PHPXref