You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1790 lines
49 KiB

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