PageRenderTime 65ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/static/scripts/jquery.ui.sortable.slider.js

https://bitbucket.org/cistrome/cistrome-harvard/
JavaScript | 2086 lines | 1490 code | 389 blank | 207 comment | 485 complexity | 0fb94f061421dfd49684bdf234862a1d MD5 | raw file
  1. /*!
  2. * jQuery UI 1.8.5
  3. *
  4. * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  5. * Dual licensed under the MIT or GPL Version 2 licenses.
  6. * http://jquery.org/license
  7. *
  8. * http://docs.jquery.com/UI
  9. */
  10. (function( $, undefined ) {
  11. // prevent duplicate loading
  12. // this is only a problem because we proxy existing functions
  13. // and we don't want to double proxy them
  14. $.ui = $.ui || {};
  15. if ( $.ui.version ) {
  16. return;
  17. }
  18. $.extend( $.ui, {
  19. version: "1.8.5",
  20. keyCode: {
  21. ALT: 18,
  22. BACKSPACE: 8,
  23. CAPS_LOCK: 20,
  24. COMMA: 188,
  25. COMMAND: 91,
  26. COMMAND_LEFT: 91, // COMMAND
  27. COMMAND_RIGHT: 93,
  28. CONTROL: 17,
  29. DELETE: 46,
  30. DOWN: 40,
  31. END: 35,
  32. ENTER: 13,
  33. ESCAPE: 27,
  34. HOME: 36,
  35. INSERT: 45,
  36. LEFT: 37,
  37. MENU: 93, // COMMAND_RIGHT
  38. NUMPAD_ADD: 107,
  39. NUMPAD_DECIMAL: 110,
  40. NUMPAD_DIVIDE: 111,
  41. NUMPAD_ENTER: 108,
  42. NUMPAD_MULTIPLY: 106,
  43. NUMPAD_SUBTRACT: 109,
  44. PAGE_DOWN: 34,
  45. PAGE_UP: 33,
  46. PERIOD: 190,
  47. RIGHT: 39,
  48. SHIFT: 16,
  49. SPACE: 32,
  50. TAB: 9,
  51. UP: 38,
  52. WINDOWS: 91 // COMMAND
  53. }
  54. });
  55. // plugins
  56. $.fn.extend({
  57. _focus: $.fn.focus,
  58. focus: function( delay, fn ) {
  59. return typeof delay === "number" ?
  60. this.each(function() {
  61. var elem = this;
  62. setTimeout(function() {
  63. $( elem ).focus();
  64. if ( fn ) {
  65. fn.call( elem );
  66. }
  67. }, delay );
  68. }) :
  69. this._focus.apply( this, arguments );
  70. },
  71. scrollParent: function() {
  72. var scrollParent;
  73. if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
  74. scrollParent = this.parents().filter(function() {
  75. return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
  76. }).eq(0);
  77. } else {
  78. scrollParent = this.parents().filter(function() {
  79. return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
  80. }).eq(0);
  81. }
  82. return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
  83. },
  84. zIndex: function( zIndex ) {
  85. if ( zIndex !== undefined ) {
  86. return this.css( "zIndex", zIndex );
  87. }
  88. if ( this.length ) {
  89. var elem = $( this[ 0 ] ), position, value;
  90. while ( elem.length && elem[ 0 ] !== document ) {
  91. // Ignore z-index if position is set to a value where z-index is ignored by the browser
  92. // This makes behavior of this function consistent across browsers
  93. // WebKit always returns auto if the element is positioned
  94. position = elem.css( "position" );
  95. if ( position === "absolute" || position === "relative" || position === "fixed" ) {
  96. // IE returns 0 when zIndex is not specified
  97. // other browsers return a string
  98. // we ignore the case of nested elements with an explicit value of 0
  99. // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
  100. value = parseInt( elem.css( "zIndex" ) );
  101. if ( !isNaN( value ) && value != 0 ) {
  102. return value;
  103. }
  104. }
  105. elem = elem.parent();
  106. }
  107. }
  108. return 0;
  109. },
  110. disableSelection: function() {
  111. return this.bind(
  112. "mousedown.ui-disableSelection selectstart.ui-disableSelection",
  113. function( event ) {
  114. event.preventDefault();
  115. });
  116. },
  117. enableSelection: function() {
  118. return this.unbind( ".ui-disableSelection" );
  119. }
  120. });
  121. $.each( [ "Width", "Height" ], function( i, name ) {
  122. var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
  123. type = name.toLowerCase(),
  124. orig = {
  125. innerWidth: $.fn.innerWidth,
  126. innerHeight: $.fn.innerHeight,
  127. outerWidth: $.fn.outerWidth,
  128. outerHeight: $.fn.outerHeight
  129. };
  130. function reduce( elem, size, border, margin ) {
  131. $.each( side, function() {
  132. size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
  133. if ( border ) {
  134. size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
  135. }
  136. if ( margin ) {
  137. size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
  138. }
  139. });
  140. return size;
  141. }
  142. $.fn[ "inner" + name ] = function( size ) {
  143. if ( size === undefined ) {
  144. return orig[ "inner" + name ].call( this );
  145. }
  146. return this.each(function() {
  147. $.style( this, type, reduce( this, size ) + "px" );
  148. });
  149. };
  150. $.fn[ "outer" + name] = function( size, margin ) {
  151. if ( typeof size !== "number" ) {
  152. return orig[ "outer" + name ].call( this, size );
  153. }
  154. return this.each(function() {
  155. $.style( this, type, reduce( this, size, true, margin ) + "px" );
  156. });
  157. };
  158. });
  159. // selectors
  160. function visible( element ) {
  161. return !$( element ).parents().andSelf().filter(function() {
  162. return $.curCSS( this, "visibility" ) === "hidden" ||
  163. $.expr.filters.hidden( this );
  164. }).length;
  165. }
  166. $.extend( $.expr[ ":" ], {
  167. data: function( elem, i, match ) {
  168. return !!$.data( elem, match[ 3 ] );
  169. },
  170. focusable: function( element ) {
  171. var nodeName = element.nodeName.toLowerCase(),
  172. tabIndex = $.attr( element, "tabindex" );
  173. if ( "area" === nodeName ) {
  174. var map = element.parentNode,
  175. mapName = map.name,
  176. img;
  177. if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
  178. return false;
  179. }
  180. img = $( "img[usemap=#" + mapName + "]" )[0];
  181. return !!img && visible( img );
  182. }
  183. return ( /input|select|textarea|button|object/.test( nodeName )
  184. ? !element.disabled
  185. : "a" == nodeName
  186. ? element.href || !isNaN( tabIndex )
  187. : !isNaN( tabIndex ))
  188. // the element and all of its ancestors must be visible
  189. && visible( element );
  190. },
  191. tabbable: function( element ) {
  192. var tabIndex = $.attr( element, "tabindex" );
  193. return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
  194. }
  195. });
  196. // support
  197. $(function() {
  198. var div = document.createElement( "div" ),
  199. body = document.body;
  200. $.extend( div.style, {
  201. minHeight: "100px",
  202. height: "auto",
  203. padding: 0,
  204. borderWidth: 0
  205. });
  206. $.support.minHeight = body.appendChild( div ).offsetHeight === 100;
  207. // set display to none to avoid a layout bug in IE
  208. // http://dev.jquery.com/ticket/4014
  209. body.removeChild( div ).style.display = "none";
  210. });
  211. // deprecated
  212. $.extend( $.ui, {
  213. // $.ui.plugin is deprecated. Use the proxy pattern instead.
  214. plugin: {
  215. add: function( module, option, set ) {
  216. var proto = $.ui[ module ].prototype;
  217. for ( var i in set ) {
  218. proto.plugins[ i ] = proto.plugins[ i ] || [];
  219. proto.plugins[ i ].push( [ option, set[ i ] ] );
  220. }
  221. },
  222. call: function( instance, name, args ) {
  223. var set = instance.plugins[ name ];
  224. if ( !set || !instance.element[ 0 ].parentNode ) {
  225. return;
  226. }
  227. for ( var i = 0; i < set.length; i++ ) {
  228. if ( instance.options[ set[ i ][ 0 ] ] ) {
  229. set[ i ][ 1 ].apply( instance.element, args );
  230. }
  231. }
  232. }
  233. },
  234. // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
  235. contains: function( a, b ) {
  236. return document.compareDocumentPosition ?
  237. a.compareDocumentPosition( b ) & 16 :
  238. a !== b && a.contains( b );
  239. },
  240. // only used by resizable
  241. hasScroll: function( el, a ) {
  242. //If overflow is hidden, the element might have extra content, but the user wants to hide it
  243. if ( $( el ).css( "overflow" ) === "hidden") {
  244. return false;
  245. }
  246. var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
  247. has = false;
  248. if ( el[ scroll ] > 0 ) {
  249. return true;
  250. }
  251. // TODO: determine which cases actually cause this to happen
  252. // if the element doesn't have the scroll set, see if it's possible to
  253. // set the scroll
  254. el[ scroll ] = 1;
  255. has = ( el[ scroll ] > 0 );
  256. el[ scroll ] = 0;
  257. return has;
  258. },
  259. // these are odd functions, fix the API or move into individual plugins
  260. isOverAxis: function( x, reference, size ) {
  261. //Determines when x coordinate is over "b" element axis
  262. return ( x > reference ) && ( x < ( reference + size ) );
  263. },
  264. isOver: function( y, x, top, left, height, width ) {
  265. //Determines when x, y coordinates is over "b" element
  266. return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
  267. }
  268. });
  269. })( jQuery );
  270. /*!
  271. * jQuery UI Widget 1.8.5
  272. *
  273. * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  274. * Dual licensed under the MIT or GPL Version 2 licenses.
  275. * http://jquery.org/license
  276. *
  277. * http://docs.jquery.com/UI/Widget
  278. */
  279. (function( $, undefined ) {
  280. // jQuery 1.4+
  281. if ( $.cleanData ) {
  282. var _cleanData = $.cleanData;
  283. $.cleanData = function( elems ) {
  284. for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
  285. $( elem ).triggerHandler( "remove" );
  286. }
  287. _cleanData( elems );
  288. };
  289. } else {
  290. var _remove = $.fn.remove;
  291. $.fn.remove = function( selector, keepData ) {
  292. return this.each(function() {
  293. if ( !keepData ) {
  294. if ( !selector || $.filter( selector, [ this ] ).length ) {
  295. $( "*", this ).add( [ this ] ).each(function() {
  296. $( this ).triggerHandler( "remove" );
  297. });
  298. }
  299. }
  300. return _remove.call( $(this), selector, keepData );
  301. });
  302. };
  303. }
  304. $.widget = function( name, base, prototype ) {
  305. var namespace = name.split( "." )[ 0 ],
  306. fullName;
  307. name = name.split( "." )[ 1 ];
  308. fullName = namespace + "-" + name;
  309. if ( !prototype ) {
  310. prototype = base;
  311. base = $.Widget;
  312. }
  313. // create selector for plugin
  314. $.expr[ ":" ][ fullName ] = function( elem ) {
  315. return !!$.data( elem, name );
  316. };
  317. $[ namespace ] = $[ namespace ] || {};
  318. $[ namespace ][ name ] = function( options, element ) {
  319. // allow instantiation without initializing for simple inheritance
  320. if ( arguments.length ) {
  321. this._createWidget( options, element );
  322. }
  323. };
  324. var basePrototype = new base();
  325. // we need to make the options hash a property directly on the new instance
  326. // otherwise we'll modify the options hash on the prototype that we're
  327. // inheriting from
  328. // $.each( basePrototype, function( key, val ) {
  329. // if ( $.isPlainObject(val) ) {
  330. // basePrototype[ key ] = $.extend( {}, val );
  331. // }
  332. // });
  333. basePrototype.options = $.extend( true, {}, basePrototype.options );
  334. $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
  335. namespace: namespace,
  336. widgetName: name,
  337. widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
  338. widgetBaseClass: fullName
  339. }, prototype );
  340. $.widget.bridge( name, $[ namespace ][ name ] );
  341. };
  342. $.widget.bridge = function( name, object ) {
  343. $.fn[ name ] = function( options ) {
  344. var isMethodCall = typeof options === "string",
  345. args = Array.prototype.slice.call( arguments, 1 ),
  346. returnValue = this;
  347. // allow multiple hashes to be passed on init
  348. options = !isMethodCall && args.length ?
  349. $.extend.apply( null, [ true, options ].concat(args) ) :
  350. options;
  351. // prevent calls to internal methods
  352. if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {
  353. return returnValue;
  354. }
  355. if ( isMethodCall ) {
  356. this.each(function() {
  357. var instance = $.data( this, name );
  358. if ( !instance ) {
  359. throw "cannot call methods on " + name + " prior to initialization; " +
  360. "attempted to call method '" + options + "'";
  361. }
  362. if ( !$.isFunction( instance[options] ) ) {
  363. throw "no such method '" + options + "' for " + name + " widget instance";
  364. }
  365. var methodValue = instance[ options ].apply( instance, args );
  366. if ( methodValue !== instance && methodValue !== undefined ) {
  367. returnValue = methodValue;
  368. return false;
  369. }
  370. });
  371. } else {
  372. this.each(function() {
  373. var instance = $.data( this, name );
  374. if ( instance ) {
  375. instance.option( options || {} )._init();
  376. } else {
  377. $.data( this, name, new object( options, this ) );
  378. }
  379. });
  380. }
  381. return returnValue;
  382. };
  383. };
  384. $.Widget = function( options, element ) {
  385. // allow instantiation without initializing for simple inheritance
  386. if ( arguments.length ) {
  387. this._createWidget( options, element );
  388. }
  389. };
  390. $.Widget.prototype = {
  391. widgetName: "widget",
  392. widgetEventPrefix: "",
  393. options: {
  394. disabled: false
  395. },
  396. _createWidget: function( options, element ) {
  397. // $.widget.bridge stores the plugin instance, but we do it anyway
  398. // so that it's stored even before the _create function runs
  399. $.data( element, this.widgetName, this );
  400. this.element = $( element );
  401. this.options = $.extend( true, {},
  402. this.options,
  403. $.metadata && $.metadata.get( element )[ this.widgetName ],
  404. options );
  405. var self = this;
  406. this.element.bind( "remove." + this.widgetName, function() {
  407. self.destroy();
  408. });
  409. this._create();
  410. this._init();
  411. },
  412. _create: function() {},
  413. _init: function() {},
  414. destroy: function() {
  415. this.element
  416. .unbind( "." + this.widgetName )
  417. .removeData( this.widgetName );
  418. this.widget()
  419. .unbind( "." + this.widgetName )
  420. .removeAttr( "aria-disabled" )
  421. .removeClass(
  422. this.widgetBaseClass + "-disabled " +
  423. "ui-state-disabled" );
  424. },
  425. widget: function() {
  426. return this.element;
  427. },
  428. option: function( key, value ) {
  429. var options = key,
  430. self = this;
  431. if ( arguments.length === 0 ) {
  432. // don't return a reference to the internal hash
  433. return $.extend( {}, self.options );
  434. }
  435. if (typeof key === "string" ) {
  436. if ( value === undefined ) {
  437. return this.options[ key ];
  438. }
  439. options = {};
  440. options[ key ] = value;
  441. }
  442. $.each( options, function( key, value ) {
  443. self._setOption( key, value );
  444. });
  445. return self;
  446. },
  447. _setOption: function( key, value ) {
  448. this.options[ key ] = value;
  449. if ( key === "disabled" ) {
  450. this.widget()
  451. [ value ? "addClass" : "removeClass"](
  452. this.widgetBaseClass + "-disabled" + " " +
  453. "ui-state-disabled" )
  454. .attr( "aria-disabled", value );
  455. }
  456. return this;
  457. },
  458. enable: function() {
  459. return this._setOption( "disabled", false );
  460. },
  461. disable: function() {
  462. return this._setOption( "disabled", true );
  463. },
  464. _trigger: function( type, event, data ) {
  465. var callback = this.options[ type ];
  466. event = $.Event( event );
  467. event.type = ( type === this.widgetEventPrefix ?
  468. type :
  469. this.widgetEventPrefix + type ).toLowerCase();
  470. data = data || {};
  471. // copy original event properties over to the new event
  472. // this would happen if we could call $.event.fix instead of $.Event
  473. // but we don't have a way to force an event to be fixed multiple times
  474. if ( event.originalEvent ) {
  475. for ( var i = $.event.props.length, prop; i; ) {
  476. prop = $.event.props[ --i ];
  477. event[ prop ] = event.originalEvent[ prop ];
  478. }
  479. }
  480. this.element.trigger( event, data );
  481. return !( $.isFunction(callback) &&
  482. callback.call( this.element[0], event, data ) === false ||
  483. event.isDefaultPrevented() );
  484. }
  485. };
  486. })( jQuery );
  487. /*!
  488. * jQuery UI Mouse 1.8.5
  489. *
  490. * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  491. * Dual licensed under the MIT or GPL Version 2 licenses.
  492. * http://jquery.org/license
  493. *
  494. * http://docs.jquery.com/UI/Mouse
  495. *
  496. * Depends:
  497. * jquery.ui.widget.js
  498. */
  499. (function( $, undefined ) {
  500. $.widget("ui.mouse", {
  501. options: {
  502. cancel: ':input,option',
  503. distance: 1,
  504. delay: 0
  505. },
  506. _mouseInit: function() {
  507. var self = this;
  508. this.element
  509. .bind('mousedown.'+this.widgetName, function(event) {
  510. return self._mouseDown(event);
  511. })
  512. .bind('click.'+this.widgetName, function(event) {
  513. if(self._preventClickEvent) {
  514. self._preventClickEvent = false;
  515. event.stopImmediatePropagation();
  516. return false;
  517. }
  518. });
  519. this.started = false;
  520. },
  521. // TODO: make sure destroying one instance of mouse doesn't mess with
  522. // other instances of mouse
  523. _mouseDestroy: function() {
  524. this.element.unbind('.'+this.widgetName);
  525. },
  526. _mouseDown: function(event) {
  527. // don't let more than one widget handle mouseStart
  528. // TODO: figure out why we have to use originalEvent
  529. event.originalEvent = event.originalEvent || {};
  530. if (event.originalEvent.mouseHandled) { return; }
  531. // we may have missed mouseup (out of window)
  532. (this._mouseStarted && this._mouseUp(event));
  533. this._mouseDownEvent = event;
  534. var self = this,
  535. btnIsLeft = (event.which == 1),
  536. elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
  537. if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
  538. return true;
  539. }
  540. this.mouseDelayMet = !this.options.delay;
  541. if (!this.mouseDelayMet) {
  542. this._mouseDelayTimer = setTimeout(function() {
  543. self.mouseDelayMet = true;
  544. }, this.options.delay);
  545. }
  546. if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
  547. this._mouseStarted = (this._mouseStart(event) !== false);
  548. if (!this._mouseStarted) {
  549. event.preventDefault();
  550. return true;
  551. }
  552. }
  553. // these delegates are required to keep context
  554. this._mouseMoveDelegate = function(event) {
  555. return self._mouseMove(event);
  556. };
  557. this._mouseUpDelegate = function(event) {
  558. return self._mouseUp(event);
  559. };
  560. $(document)
  561. .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
  562. .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
  563. // preventDefault() is used to prevent the selection of text here -
  564. // however, in Safari, this causes select boxes not to be selectable
  565. // anymore, so this fix is needed
  566. ($.browser.safari || event.preventDefault());
  567. event.originalEvent.mouseHandled = true;
  568. return true;
  569. },
  570. _mouseMove: function(event) {
  571. // IE mouseup check - mouseup happened when mouse was out of window
  572. if ($.browser.msie && !event.button) {
  573. return this._mouseUp(event);
  574. }
  575. if (this._mouseStarted) {
  576. this._mouseDrag(event);
  577. return event.preventDefault();
  578. }
  579. if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
  580. this._mouseStarted =
  581. (this._mouseStart(this._mouseDownEvent, event) !== false);
  582. (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
  583. }
  584. return !this._mouseStarted;
  585. },
  586. _mouseUp: function(event) {
  587. $(document)
  588. .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
  589. .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
  590. if (this._mouseStarted) {
  591. this._mouseStarted = false;
  592. this._preventClickEvent = (event.target == this._mouseDownEvent.target);
  593. this._mouseStop(event);
  594. }
  595. return false;
  596. },
  597. _mouseDistanceMet: function(event) {
  598. return (Math.max(
  599. Math.abs(this._mouseDownEvent.pageX - event.pageX),
  600. Math.abs(this._mouseDownEvent.pageY - event.pageY)
  601. ) >= this.options.distance
  602. );
  603. },
  604. _mouseDelayMet: function(event) {
  605. return this.mouseDelayMet;
  606. },
  607. // These are placeholder methods, to be overriden by extending plugin
  608. _mouseStart: function(event) {},
  609. _mouseDrag: function(event) {},
  610. _mouseStop: function(event) {},
  611. _mouseCapture: function(event) { return true; }
  612. });
  613. })(jQuery);
  614. /*
  615. * jQuery UI Sortable 1.8.5
  616. *
  617. * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  618. * Dual licensed under the MIT or GPL Version 2 licenses.
  619. * http://jquery.org/license
  620. *
  621. * http://docs.jquery.com/UI/Sortables
  622. *
  623. * Depends:
  624. * jquery.ui.core.js
  625. * jquery.ui.mouse.js
  626. * jquery.ui.widget.js
  627. */
  628. (function( $, undefined ) {
  629. $.widget("ui.sortable", $.ui.mouse, {
  630. widgetEventPrefix: "sort",
  631. options: {
  632. appendTo: "parent",
  633. axis: false,
  634. connectWith: false,
  635. containment: false,
  636. cursor: 'auto',
  637. cursorAt: false,
  638. dropOnEmpty: true,
  639. forcePlaceholderSize: false,
  640. forceHelperSize: false,
  641. grid: false,
  642. handle: false,
  643. helper: "original",
  644. items: '> *',
  645. opacity: false,
  646. placeholder: false,
  647. revert: false,
  648. scroll: true,
  649. scrollSensitivity: 20,
  650. scrollSpeed: 20,
  651. scope: "default",
  652. tolerance: "intersect",
  653. zIndex: 1000
  654. },
  655. _create: function() {
  656. var o = this.options;
  657. this.containerCache = {};
  658. this.element.addClass("ui-sortable");
  659. //Get the items
  660. this.refresh();
  661. //Let's determine if the items are floating
  662. this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
  663. //Let's determine the parent's offset
  664. this.offset = this.element.offset();
  665. //Initialize mouse events for interaction
  666. this._mouseInit();
  667. },
  668. destroy: function() {
  669. this.element
  670. .removeClass("ui-sortable ui-sortable-disabled")
  671. .removeData("sortable")
  672. .unbind(".sortable");
  673. this._mouseDestroy();
  674. for ( var i = this.items.length - 1; i >= 0; i-- )
  675. this.items[i].item.removeData("sortable-item");
  676. return this;
  677. },
  678. _setOption: function(key, value){
  679. if ( key === "disabled" ) {
  680. this.options[ key ] = value;
  681. this.widget()
  682. [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
  683. } else {
  684. // Don't call widget base _setOption for disable as it adds ui-state-disabled class
  685. $.Widget.prototype._setOption.apply(this, arguments);
  686. }
  687. },
  688. _mouseCapture: function(event, overrideHandle) {
  689. if (this.reverting) {
  690. return false;
  691. }
  692. if(this.options.disabled || this.options.type == 'static') return false;
  693. //We have to refresh the items data once first
  694. this._refreshItems(event);
  695. //Find out if the clicked node (or one of its parents) is a actual item in this.items
  696. var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
  697. if($.data(this, 'sortable-item') == self) {
  698. currentItem = $(this);
  699. return false;
  700. }
  701. });
  702. if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
  703. if(!currentItem) return false;
  704. if(this.options.handle && !overrideHandle) {
  705. var validHandle = false;
  706. $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
  707. if(!validHandle) return false;
  708. }
  709. this.currentItem = currentItem;
  710. this._removeCurrentsFromItems();
  711. return true;
  712. },
  713. _mouseStart: function(event, overrideHandle, noActivation) {
  714. var o = this.options, self = this;
  715. this.currentContainer = this;
  716. //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
  717. this.refreshPositions();
  718. //Create and append the visible helper
  719. this.helper = this._createHelper(event);
  720. //Cache the helper size
  721. this._cacheHelperProportions();
  722. /*
  723. * - Position generation -
  724. * This block generates everything position related - it's the core of draggables.
  725. */
  726. //Cache the margins of the original element
  727. this._cacheMargins();
  728. //Get the next scrolling parent
  729. this.scrollParent = this.helper.scrollParent();
  730. //The element's absolute position on the page minus margins
  731. this.offset = this.currentItem.offset();
  732. this.offset = {
  733. top: this.offset.top - this.margins.top,
  734. left: this.offset.left - this.margins.left
  735. };
  736. // Only after we got the offset, we can change the helper's position to absolute
  737. // TODO: Still need to figure out a way to make relative sorting possible
  738. this.helper.css("position", "absolute");
  739. this.cssPosition = this.helper.css("position");
  740. $.extend(this.offset, {
  741. click: { //Where the click happened, relative to the element
  742. left: event.pageX - this.offset.left,
  743. top: event.pageY - this.offset.top
  744. },
  745. parent: this._getParentOffset(),
  746. relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
  747. });
  748. //Generate the original position
  749. this.originalPosition = this._generatePosition(event);
  750. this.originalPageX = event.pageX;
  751. this.originalPageY = event.pageY;
  752. //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
  753. (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
  754. //Cache the former DOM position
  755. this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
  756. //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
  757. if(this.helper[0] != this.currentItem[0]) {
  758. this.currentItem.hide();
  759. }
  760. //Create the placeholder
  761. this._createPlaceholder();
  762. //Set a containment if given in the options
  763. if(o.containment)
  764. this._setContainment();
  765. if(o.cursor) { // cursor option
  766. if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
  767. $('body').css("cursor", o.cursor);
  768. }
  769. if(o.opacity) { // opacity option
  770. if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
  771. this.helper.css("opacity", o.opacity);
  772. }
  773. if(o.zIndex) { // zIndex option
  774. if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
  775. this.helper.css("zIndex", o.zIndex);
  776. }
  777. //Prepare scrolling
  778. if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
  779. this.overflowOffset = this.scrollParent.offset();
  780. //Call callbacks
  781. this._trigger("start", event, this._uiHash());
  782. //Recache the helper size
  783. if(!this._preserveHelperProportions)
  784. this._cacheHelperProportions();
  785. //Post 'activate' events to possible containers
  786. if(!noActivation) {
  787. for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
  788. }
  789. //Prepare possible droppables
  790. if($.ui.ddmanager)
  791. $.ui.ddmanager.current = this;
  792. if ($.ui.ddmanager && !o.dropBehaviour)
  793. $.ui.ddmanager.prepareOffsets(this, event);
  794. this.dragging = true;
  795. this.helper.addClass("ui-sortable-helper");
  796. this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
  797. return true;
  798. },
  799. _mouseDrag: function(event) {
  800. //Compute the helpers position
  801. this.position = this._generatePosition(event);
  802. this.positionAbs = this._convertPositionTo("absolute");
  803. if (!this.lastPositionAbs) {
  804. this.lastPositionAbs = this.positionAbs;
  805. }
  806. //Do scrolling
  807. if(this.options.scroll) {
  808. var o = this.options, scrolled = false;
  809. if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
  810. if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
  811. this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
  812. else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
  813. this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
  814. if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
  815. this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
  816. else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
  817. this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
  818. } else {
  819. if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
  820. scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
  821. else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
  822. scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
  823. if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
  824. scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
  825. else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
  826. scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
  827. }
  828. if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
  829. $.ui.ddmanager.prepareOffsets(this, event);
  830. }
  831. //Regenerate the absolute position used for position checks
  832. this.positionAbs = this._convertPositionTo("absolute");
  833. //Set the helper position
  834. if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
  835. if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
  836. //Rearrange
  837. for (var i = this.items.length - 1; i >= 0; i--) {
  838. //Cache variables and intersection, continue if no intersection
  839. var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
  840. if (!intersection) continue;
  841. if(itemElement != this.currentItem[0] //cannot intersect with itself
  842. && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
  843. && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
  844. && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
  845. //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
  846. ) {
  847. this.direction = intersection == 1 ? "down" : "up";
  848. if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
  849. this._rearrange(event, item);
  850. } else {
  851. break;
  852. }
  853. this._trigger("change", event, this._uiHash());
  854. break;
  855. }
  856. }
  857. //Post events to containers
  858. this._contactContainers(event);
  859. //Interconnect with droppables
  860. if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
  861. //Call callbacks
  862. this._trigger('sort', event, this._uiHash());
  863. this.lastPositionAbs = this.positionAbs;
  864. return false;
  865. },
  866. _mouseStop: function(event, noPropagation) {
  867. if(!event) return;
  868. //If we are using droppables, inform the manager about the drop
  869. if ($.ui.ddmanager && !this.options.dropBehaviour)
  870. $.ui.ddmanager.drop(this, event);
  871. if(this.options.revert) {
  872. var self = this;
  873. var cur = self.placeholder.offset();
  874. self.reverting = true;
  875. $(this.helper).animate({
  876. left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
  877. top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
  878. }, parseInt(this.options.revert, 10) || 500, function() {
  879. self._clear(event);
  880. });
  881. } else {
  882. this._clear(event, noPropagation);
  883. }
  884. return false;
  885. },
  886. cancel: function() {
  887. var self = this;
  888. if(this.dragging) {
  889. this._mouseUp();
  890. if(this.options.helper == "original")
  891. this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
  892. else
  893. this.currentItem.show();
  894. //Post deactivating events to containers
  895. for (var i = this.containers.length - 1; i >= 0; i--){
  896. this.containers[i]._trigger("deactivate", null, self._uiHash(this));
  897. if(this.containers[i].containerCache.over) {
  898. this.containers[i]._trigger("out", null, self._uiHash(this));
  899. this.containers[i].containerCache.over = 0;
  900. }
  901. }
  902. }
  903. //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
  904. if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
  905. if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
  906. $.extend(this, {
  907. helper: null,
  908. dragging: false,
  909. reverting: false,
  910. _noFinalSort: null
  911. });
  912. if(this.domPosition.prev) {
  913. $(this.domPosition.prev).after(this.currentItem);
  914. } else {
  915. $(this.domPosition.parent).prepend(this.currentItem);
  916. }
  917. return this;
  918. },
  919. serialize: function(o) {
  920. var items = this._getItemsAsjQuery(o && o.connected);
  921. var str = []; o = o || {};
  922. $(items).each(function() {
  923. var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
  924. if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
  925. });
  926. if(!str.length && o.key) {
  927. str.push(o.key + '=');
  928. }
  929. return str.join('&');
  930. },
  931. toArray: function(o) {
  932. var items = this._getItemsAsjQuery(o && o.connected);
  933. var ret = []; o = o || {};
  934. items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
  935. return ret;
  936. },
  937. /* Be careful with the following core functions */
  938. _intersectsWith: function(item) {
  939. var x1 = this.positionAbs.left,
  940. x2 = x1 + this.helperProportions.width,
  941. y1 = this.positionAbs.top,
  942. y2 = y1 + this.helperProportions.height;
  943. var l = item.left,
  944. r = l + item.width,
  945. t = item.top,
  946. b = t + item.height;
  947. var dyClick = this.offset.click.top,
  948. dxClick = this.offset.click.left;
  949. var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
  950. if( this.options.tolerance == "pointer"
  951. || this.options.forcePointerForContainers
  952. || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
  953. ) {
  954. return isOverElement;
  955. } else {
  956. return (l < x1 + (this.helperProportions.width / 2) // Right Half
  957. && x2 - (this.helperProportions.width / 2) < r // Left Half
  958. && t < y1 + (this.helperProportions.height / 2) // Bottom Half
  959. && y2 - (this.helperProportions.height / 2) < b ); // Top Half
  960. }
  961. },
  962. _intersectsWithPointer: function(item) {
  963. var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
  964. isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
  965. isOverElement = isOverElementHeight && isOverElementWidth,
  966. verticalDirection = this._getDragVerticalDirection(),
  967. horizontalDirection = this._getDragHorizontalDirection();
  968. if (!isOverElement)
  969. return false;
  970. return this.floating ?
  971. ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
  972. : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
  973. },
  974. _intersectsWithSides: function(item) {
  975. var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
  976. isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
  977. verticalDirection = this._getDragVerticalDirection(),
  978. horizontalDirection = this._getDragHorizontalDirection();
  979. if (this.floating && horizontalDirection) {
  980. return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
  981. } else {
  982. return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
  983. }
  984. },
  985. _getDragVerticalDirection: function() {
  986. var delta = this.positionAbs.top - this.lastPositionAbs.top;
  987. return delta != 0 && (delta > 0 ? "down" : "up");
  988. },
  989. _getDragHorizontalDirection: function() {
  990. var delta = this.positionAbs.left - this.lastPositionAbs.left;
  991. return delta != 0 && (delta > 0 ? "right" : "left");
  992. },
  993. refresh: function(event) {
  994. this._refreshItems(event);
  995. this.refreshPositions();
  996. return this;
  997. },
  998. _connectWith: function() {
  999. var options = this.options;
  1000. return options.connectWith.constructor == String
  1001. ? [options.connectWith]
  1002. : options.connectWith;
  1003. },
  1004. _getItemsAsjQuery: function(connected) {
  1005. var self = this;
  1006. var items = [];
  1007. var queries = [];
  1008. var connectWith = this._connectWith();
  1009. if(connectWith && connected) {
  1010. for (var i = connectWith.length - 1; i >= 0; i--){
  1011. var cur = $(connectWith[i]);
  1012. for (var j = cur.length - 1; j >= 0; j--){
  1013. var inst = $.data(cur[j], 'sortable');
  1014. if(inst && inst != this && !inst.options.disabled) {
  1015. queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
  1016. }
  1017. };
  1018. };
  1019. }
  1020. queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
  1021. for (var i = queries.length - 1; i >= 0; i--){
  1022. queries[i][0].each(function() {
  1023. items.push(this);
  1024. });
  1025. };
  1026. return $(items);
  1027. },
  1028. _removeCurrentsFromItems: function() {
  1029. var list = this.currentItem.find(":data(sortable-item)");
  1030. for (var i=0; i < this.items.length; i++) {
  1031. for (var j=0; j < list.length; j++) {
  1032. if(list[j] == this.items[i].item[0])
  1033. this.items.splice(i,1);
  1034. };
  1035. };
  1036. },
  1037. _refreshItems: function(event) {
  1038. this.items = [];
  1039. this.containers = [this];
  1040. var items = this.items;
  1041. var self = this;
  1042. var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
  1043. var connectWith = this._connectWith();
  1044. if(connectWith) {
  1045. for (var i = connectWith.length - 1; i >= 0; i--){
  1046. var cur = $(connectWith[i]);
  1047. for (var j = cur.length - 1; j >= 0; j--){
  1048. var inst = $.data(cur[j], 'sortable');
  1049. if(inst && inst != this && !inst.options.disabled) {
  1050. queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
  1051. this.containers.push(inst);
  1052. }
  1053. };
  1054. };
  1055. }
  1056. for (var i = queries.length - 1; i >= 0; i--) {
  1057. var targetData = queries[i][1];
  1058. var _queries = queries[i][0];
  1059. for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
  1060. var item = $(_queries[j]);
  1061. item.data('sortable-item', targetData); // Data for target checking (mouse manager)
  1062. items.push({
  1063. item: item,
  1064. instance: targetData,
  1065. width: 0, height: 0,
  1066. left: 0, top: 0
  1067. });
  1068. };
  1069. };
  1070. },
  1071. refreshPositions: function(fast) {
  1072. //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
  1073. if(this.offsetParent && this.helper) {
  1074. this.offset.parent = this._getParentOffset();
  1075. }
  1076. for (var i = this.items.length - 1; i >= 0; i--){
  1077. var item = this.items[i];
  1078. var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
  1079. if (!fast) {
  1080. item.width = t.outerWidth();
  1081. item.height = t.outerHeight();
  1082. }
  1083. var p = t.offset();
  1084. item.left = p.left;
  1085. item.top = p.top;
  1086. };
  1087. if(this.options.custom && this.options.custom.refreshContainers) {
  1088. this.options.custom.refreshContainers.call(this);
  1089. } else {
  1090. for (var i = this.containers.length - 1; i >= 0; i--){
  1091. var p = this.containers[i].element.offset();
  1092. this.containers[i].containerCache.left = p.left;
  1093. this.containers[i].containerCache.top = p.top;
  1094. this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
  1095. this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
  1096. };
  1097. }
  1098. return this;
  1099. },
  1100. _createPlaceholder: function(that) {
  1101. var self = that || this, o = self.options;
  1102. if(!o.placeholder || o.placeholder.constructor == String) {
  1103. var className = o.placeholder;
  1104. o.placeholder = {
  1105. element: function() {
  1106. var el = $(document.createElement(self.currentItem[0].nodeName))
  1107. .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
  1108. .removeClass("ui-sortable-helper")[0];
  1109. if(!className)
  1110. el.style.visibility = "hidden";
  1111. return el;
  1112. },
  1113. update: function(container, p) {
  1114. // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
  1115. // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
  1116. if(className && !o.forcePlaceholderSize) return;
  1117. //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
  1118. if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
  1119. if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
  1120. }
  1121. };
  1122. }
  1123. //Create the placeholder
  1124. self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
  1125. //Append it after the actual current item
  1126. self.currentItem.after(self.placeholder);
  1127. //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
  1128. o.placeholder.update(self, self.placeholder);
  1129. },
  1130. _contactContainers: function(event) {
  1131. // get innermost container that intersects with item
  1132. var innermostContainer = null, innermostIndex = null;
  1133. for (var i = this.containers.length - 1; i >= 0; i--){
  1134. // never consider a container that's located within the item itself
  1135. if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
  1136. continue;
  1137. if(this._intersectsWith(this.containers[i].containerCache)) {
  1138. // if we've already found a container and it's more "inner" than this, then continue
  1139. if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
  1140. continue;
  1141. innermostContainer = this.containers[i];
  1142. innermostIndex = i;
  1143. } else {
  1144. // container doesn't intersect. trigger "out" event if necessary
  1145. if(this.containers[i].containerCache.over) {
  1146. this.containers[i]._trigger("out", event, this._uiHash(this));
  1147. this.containers[i].containerCache.over = 0;
  1148. }
  1149. }
  1150. }
  1151. // if no intersecting containers found, return
  1152. if(!innermostContainer) return;
  1153. // move the item into the container if it's not there already
  1154. if(this.containers.length === 1) {
  1155. this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
  1156. this.containers[innermostIndex].containerCache.over = 1;
  1157. } else if(this.currentContainer != this.containers[innermostIndex]) {
  1158. //When entering a new container, we will find the item with the least distance and append our item near it
  1159. var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
  1160. for (var j = this.items.length - 1; j >= 0; j--) {
  1161. if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
  1162. var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
  1163. if(Math.abs(cur - base) < dist) {
  1164. dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
  1165. }
  1166. }
  1167. if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
  1168. return;
  1169. this.currentContainer = this.containers[innermostIndex];
  1170. itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
  1171. this._trigger("change", event, this._uiHash());
  1172. this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
  1173. //Update the placeholder
  1174. this.options.placeholder.update(this.currentContainer, this.placeholder);
  1175. this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
  1176. this.containers[innermostIndex].containerCache.over = 1;
  1177. }
  1178. },
  1179. _createHelper: function(event) {
  1180. var o = this.options;
  1181. var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
  1182. if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
  1183. $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
  1184. if(helper[0] == this.currentItem[0])
  1185. this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
  1186. if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
  1187. if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
  1188. return helper;
  1189. },
  1190. _adjustOffsetFromHelper: function(obj) {
  1191. if (typeof obj == 'string') {
  1192. obj = obj.split(' ');
  1193. }
  1194. if ($.isArray(obj)) {
  1195. obj = {left: +obj[0], top: +obj[1] || 0};
  1196. }
  1197. if ('left' in obj) {
  1198. this.offset.click.left = obj.left + this.margins.left;
  1199. }
  1200. if ('right' in obj) {
  1201. this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
  1202. }
  1203. if ('top' in obj) {
  1204. this.offset.click.top = obj.top + this.margins.top;
  1205. }
  1206. if ('bottom' in obj) {
  1207. this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
  1208. }
  1209. },
  1210. _getParentOffset: function() {
  1211. //Get the offsetParent and cache its position
  1212. this.offsetParent = this.helper.offsetParent();
  1213. var po = this.offsetParent.offset();
  1214. // This is a special case where we need to modify a offset calculated on start, since the following happened:
  1215. // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
  1216. // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
  1217. // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
  1218. if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
  1219. po.left += this.scrollParent.scrollLeft();
  1220. po.top += this.scrollParent.scrollTop();
  1221. }
  1222. if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
  1223. || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
  1224. po = { top: 0, left: 0 };
  1225. return {
  1226. top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
  1227. left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
  1228. };
  1229. },
  1230. _getRelativeOffset: function() {
  1231. if(this.cssPosition == "relative") {
  1232. var p = this.currentItem.position();
  1233. return {
  1234. top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
  1235. left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
  1236. };
  1237. } else {
  1238. return { top: 0, left: 0 };
  1239. }
  1240. },
  1241. _cacheMargins: function() {
  1242. this.margins = {
  1243. left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
  1244. top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
  1245. };
  1246. },
  1247. _cacheHelperProportions: function() {
  1248. this.helperProportions = {
  1249. width: this.helper.outerWidth(),
  1250. height: this.helper.outerHeight()
  1251. };
  1252. },
  1253. _setContainment: function() {
  1254. var o = this.options;
  1255. if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
  1256. if(o.containment == 'document' || o.containment == 'window') this.containment = [
  1257. 0 - this.offset.relative.left - this.offset.parent.left,
  1258. 0 - this.offset.relative.top - this.offset.parent.top,
  1259. $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
  1260. ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
  1261. ];
  1262. if(!(/^(document|window|parent)$/).test(o.containment)) {
  1263. var ce = $(o.containment)[0];
  1264. var co = $(o.containment).offset();
  1265. var over = ($(ce).css("overflow") != 'hidden');
  1266. this.containment = [
  1267. co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
  1268. co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
  1269. co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
  1270. co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
  1271. ];
  1272. }
  1273. },
  1274. _convertPositionTo: function(d, pos) {
  1275. if(!pos) pos = this.position;
  1276. var mod = d == "absolute" ? 1 : -1;
  1277. var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
  1278. return {
  1279. top: (
  1280. pos.top // The absolute mouse position
  1281. + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
  1282. + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
  1283. - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
  1284. ),
  1285. left: (
  1286. pos.left // The absolute mouse position
  1287. + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
  1288. + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
  1289. - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
  1290. )
  1291. };
  1292. },
  1293. _generatePosition: function(event) {
  1294. var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
  1295. // This is another very weird special case that only happens for relative elements:
  1296. // 1. If the css position is relative
  1297. // 2. and the scroll parent is the document or similar to the offset parent
  1298. // we have to refresh the relative offset during the scroll so there are no jumps
  1299. if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
  1300. this.offset.relative = this._getRelativeOffset();
  1301. }
  1302. var pageX = event.pageX;
  1303. var pageY = event.pageY;
  1304. /*
  1305. * - Position constraining -
  1306. * Constrain the position to a mix of grid, containment.
  1307. */
  1308. if(this.originalPosition) { //If we are not dragging yet, we won't check for options
  1309. if(this.containment) {
  1310. if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
  1311. if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
  1312. if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
  1313. if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
  1314. }
  1315. if(o.grid) {
  1316. var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
  1317. pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
  1318. var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
  1319. pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
  1320. }
  1321. }
  1322. return {
  1323. top: (
  1324. pageY // The absolute mouse position
  1325. - this.offset.click.top // Click offset (relative to the element)
  1326. - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
  1327. - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
  1328. + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
  1329. ),
  1330. left: (
  1331. pageX // The absolute mouse position
  1332. - this.offset.click.left // Click offset (relative to the element)
  1333. - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
  1334. - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
  1335. + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
  1336. )
  1337. };
  1338. },
  1339. _rearrange: function(event, i, a, hardRefresh) {
  1340. a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
  1341. //Various things done here to improve the performance:
  1342. // 1. we create a setTimeout, that calls refreshPositions
  1343. // 2. on the instance, we have a counter variable, that get's higher after every append
  1344. // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
  1345. // 4. this lets only the last addition to the timeout stack through
  1346. this.counter = this.counter ? ++this.counter : 1;
  1347. var self = this, counter = this.counter;
  1348. window.setTimeout(function() {
  1349. if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
  1350. },0);
  1351. },
  1352. _clear: function(event, noPropagation) {
  1353. this.reverting = false;
  1354. // We delay all events that have to be triggered to after the point where the placeholder has been removed and
  1355. // everything else normalized again
  1356. var delayedTriggers = [], self = this;
  1357. // We first have to update the dom position of the actual currentItem
  1358. // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
  1359. if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
  1360. this._noFinalSort = null;
  1361. if(this.helper[0] == this.currentItem[0]) {
  1362. for(var i in this._storedCSS) {
  1363. if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
  1364. }
  1365. this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
  1366. } else {
  1367. this.currentItem.show();
  1368. }
  1369. if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
  1370. if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
  1371. if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
  1372. if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
  1373. for (var i = this.containers.length - 1; i >= 0; i--){
  1374. if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
  1375. delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
  1376. delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
  1377. }
  1378. };
  1379. };
  1380. //Post events to containers
  1381. for (var i = this.containers.length - 1; i >= 0; i--){
  1382. if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
  1383. if(this.containers[i].containerCache.over) {
  1384. delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
  1385. this.containers[i].containerCache.over = 0;
  1386. }
  1387. }
  1388. //Do what was originally in plugins
  1389. if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
  1390. if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
  1391. if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
  1392. this.dragging = false;
  1393. if(this.cancelHelperRemoval) {
  1394. if(!noPropagation) {
  1395. this._trigger("beforeStop", event, this._uiHash());
  1396. for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
  1397. this._trigger("stop", event, this._uiHash());
  1398. }
  1399. return false;
  1400. }
  1401. if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
  1402. //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
  1403. this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
  1404. if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
  1405. if(!noPropagation) {
  1406. for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
  1407. this._trigger("stop", event, this._uiHash());
  1408. }
  1409. this.fromOutside = false;
  1410. return true;
  1411. },
  1412. _trigger: function() {
  1413. if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
  1414. this.cancel();
  1415. }
  1416. },
  1417. _uiHash: function(inst) {
  1418. var self = inst || this;
  1419. return {
  1420. helper: self.helper,
  1421. placeholder: self.placeholder || $([]),
  1422. position: self.position,
  1423. originalPosition: self.originalPosition,
  1424. offset: self.positionAbs,
  1425. item: self.currentItem,
  1426. sender: inst ? inst.element : null
  1427. };
  1428. }
  1429. });
  1430. $.extend($.ui.sortable, {
  1431. version: "1.8.5"
  1432. });
  1433. })(jQuery);
  1434. /*
  1435. * jQuery UI Slider 1.8.5
  1436. *
  1437. * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  1438. * Dual licensed under the MIT or GPL Version 2 licenses.
  1439. * http://jquery.org/license
  1440. *
  1441. * http://docs.jquery.com/UI/Slider
  1442. *
  1443. * Depends:
  1444. * jquery.ui.core.js
  1445. * jquery.ui.mouse.js
  1446. * jquery.ui.widget.js
  1447. */
  1448. (function( $, undefined ) {
  1449. // number of pages in a slider
  1450. // (how many times can you page up/down to go through the whole range)
  1451. var numPages = 5;
  1452. $.widget( "ui.slider", $.ui.mouse, {
  1453. widgetEventPrefix: "slide",
  1454. options: {
  1455. animate: false,
  1456. distance: 0,
  1457. max: 100,
  1458. min: 0,
  1459. orientation: "horizontal",
  1460. range: false,
  1461. step: 1,
  1462. value: 0,
  1463. values: null
  1464. },
  1465. _create: function() {
  1466. var self = this,
  1467. o = this.options;
  1468. this._keySliding = false;
  1469. this._mouseSliding = false;
  1470. this._animateOff = true;
  1471. this._handleIndex = null;
  1472. this._detectOrientation();
  1473. this._mouseInit();
  1474. this.element
  1475. .addClass( "ui-slider" +
  1476. " ui-slider-" + this.orientation +
  1477. " ui-widget" +
  1478. " ui-widget-content" +
  1479. " ui-corner-all" );
  1480. if ( o.disabled ) {
  1481. this.element.addClass( "ui-slider-disabled ui-disabled" );
  1482. }
  1483. this.range = $([]);
  1484. if ( o.range ) {
  1485. if ( o.range === true ) {
  1486. this.range = $( "<div></div>" );
  1487. if ( !o.values ) {
  1488. o.values = [ this._valueMin(), this._valueMin() ];
  1489. }
  1490. if ( o.values.length && o.values.length !== 2 ) {
  1491. o.values = [ o.values[0], o.values[0] ];
  1492. }
  1493. } else {
  1494. this.range = $( "<div></div>" );
  1495. }
  1496. this.range
  1497. .appendTo( this.element )
  1498. .addClass( "ui-slider-range" );
  1499. if ( o.range === "min" || o.range === "max" ) {
  1500. this.range.addClass( "ui-slider-range-" + o.range );
  1501. }
  1502. // note: this isn't the most fittingly semantic framework class for this element,
  1503. // but worked best visually with a variety of themes
  1504. this.range.addClass( "ui-widget-header" );
  1505. }
  1506. if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
  1507. $( "<a href='#'></a>" )
  1508. .appendTo( this.element )
  1509. .addClass( "ui-slider-handle" );
  1510. }
  1511. if ( o.values && o.values.length ) {
  1512. while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
  1513. $( "<a href='#'></a>" )
  1514. .appendTo( this.element )
  1515. .addClass( "ui-slider-handle" );
  1516. }
  1517. }
  1518. this.handles = $( ".ui-slider-handle", this.element )
  1519. .addClass( "ui-state-default" +
  1520. " ui-corner-all" );
  1521. this.handle = this.handles.eq( 0 );
  1522. this.handles.add( this.range ).filter( "a" )
  1523. .click(function( event ) {
  1524. event.preventDefault();
  1525. })
  1526. .hover(function() {
  1527. if ( !o.disabled ) {
  1528. $( this ).addClass( "ui-state-hover" );
  1529. }
  1530. }, function() {
  1531. $( this ).removeClass( "ui-state-hover" );
  1532. })
  1533. .focus(function() {
  1534. if ( !o.disabled ) {
  1535. $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
  1536. $( this ).addClass( "ui-state-focus" );
  1537. } else {
  1538. $( this ).blur();
  1539. }
  1540. })
  1541. .blur(function() {
  1542. $( this ).removeClass( "ui-state-focus" );
  1543. });
  1544. this.handles.each(function( i ) {
  1545. $( this ).data( "index.ui-slider-handle", i );
  1546. });
  1547. this.handles
  1548. .keydown(function( event ) {
  1549. var ret = true,
  1550. index = $( this ).data( "index.ui-slider-handle" ),
  1551. allowed,
  1552. curVal,
  1553. newVal,
  1554. step;
  1555. if ( self.options.disabled ) {
  1556. return;
  1557. }
  1558. switch ( event.keyCode ) {
  1559. case $.ui.keyCode.HOME:
  1560. case $.ui.keyCode.END:
  1561. case $.ui.keyCode.PAGE_UP:
  1562. case $.ui.keyCode.PAGE_DOWN:
  1563. case $.ui.keyCode.UP:
  1564. case $.ui.keyCode.RIGHT:
  1565. case $.ui.keyCode.DOWN:
  1566. case $.ui.keyCode.LEFT:
  1567. ret = false;
  1568. if ( !self._keySliding ) {
  1569. self._keySliding = true;
  1570. $( this ).addClass( "ui-state-active" );
  1571. allowed = self._start( event, index );
  1572. if ( allowed === false ) {
  1573. return;
  1574. }
  1575. }
  1576. break;
  1577. }
  1578. step = self.options.step;
  1579. if ( self.options.values && self.options.values.length ) {
  1580. curVal = newVal = self.values( index );
  1581. } else {
  1582. curVal = newVal = self.value();
  1583. }
  1584. switch ( event.keyCode ) {
  1585. case $.ui.keyCode.HOME:
  1586. newVal = self._valueMin();
  1587. break;
  1588. case $.ui.keyCode.END:
  1589. newVal = self._valueMax();
  1590. break;
  1591. case $.ui.keyCode.PAGE_UP:
  1592. newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
  1593. break;
  1594. case $.ui.keyCode.PAGE_DOWN:
  1595. newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
  1596. break;
  1597. case $.ui.keyCode.UP:
  1598. case $.ui.keyCode.RIGHT:
  1599. if ( curVal === self._valueMax() ) {
  1600. return;
  1601. }
  1602. newVal = self._trimAlignValue( curVal + step );
  1603. break;
  1604. case $.ui.keyCode.DOWN:
  1605. case $.ui.keyCode.LEFT:
  1606. if ( curVal === self._valueMin() ) {
  1607. return;
  1608. }
  1609. newVal = self._trimAlignValue( curVal - step );
  1610. break;
  1611. }
  1612. self._slide( event, index, newVal );
  1613. return ret;
  1614. })
  1615. .keyup(function( event ) {
  1616. var index = $( this ).data( "index.ui-slider-handle" );
  1617. if ( self._keySliding ) {
  1618. self._keySliding = false;
  1619. self._stop( event, index );
  1620. self._change( event, index );
  1621. $( this ).removeClass( "ui-state-active" );
  1622. }
  1623. });
  1624. this._refreshValue();
  1625. this._animateOff = false;
  1626. },
  1627. destroy: function() {
  1628. this.handles.remove();
  1629. this.range.remove();
  1630. this.element
  1631. .removeClass( "ui-slider" +
  1632. " ui-slider-horizontal" +
  1633. " ui-slider-vertical" +
  1634. " ui-slider-disabled" +
  1635. " ui-widget" +
  1636. " ui-widget-content" +
  1637. " ui-corner-all" )
  1638. .removeData( "slider" )
  1639. .unbind( ".slider" );
  1640. this._mouseDestroy();
  1641. return this;
  1642. },
  1643. _mouseCapture: function( event ) {
  1644. var o = this.options,
  1645. position,
  1646. normValue,
  1647. distance,
  1648. closestHandle,
  1649. self,
  1650. index,
  1651. allowed,
  1652. offset,
  1653. mouseOverHandle;
  1654. if ( o.disabled ) {
  1655. return false;
  1656. }
  1657. this.elementSize = {
  1658. width: this.element.outerWidth(),
  1659. height: this.element.outerHeight()
  1660. };
  1661. this.elementOffset = this.element.offset();
  1662. position = { x: event.pageX, y: event.pageY };
  1663. normValue = this._normValueFromMouse( position );
  1664. distance = this._valueMax() - this._valueMin() + 1;
  1665. self = this;
  1666. this.handles.each(function( i ) {
  1667. var thisDistance = Math.abs( normValue - self.values(i) );
  1668. if ( distance > thisDistance ) {
  1669. distance = thisDistance;
  1670. closestHandle = $( this );
  1671. index = i;
  1672. }
  1673. });
  1674. // workaround for bug #3736 (if both handles of a range are at 0,
  1675. // the first is always used as the one with least distance,
  1676. // and moving it is obviously prevented by preventing negative ranges)
  1677. if( o.range === true && this.values(1) === o.min ) {
  1678. index += 1;
  1679. closestHandle = $( this.handles[index] );
  1680. }
  1681. allowed = this._start( event, index );
  1682. if ( allowed === false ) {
  1683. return false;
  1684. }
  1685. this._mouseSliding = true;
  1686. self._handleIndex = index;
  1687. closestHandle
  1688. .addClass( "ui-state-active" )
  1689. .focus();
  1690. offset = closestHandle.offset();
  1691. mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
  1692. this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
  1693. left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
  1694. top: event.pageY - offset.top -
  1695. ( closestHandle.height() / 2 ) -
  1696. ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
  1697. ( p