otsdaq_utilities  v2_05_02_indev
jquery-ui.js
1 
6 (function( factory ) {
7  if ( typeof define === "function" && define.amd ) {
8 
9  // AMD. Register as an anonymous module.
10  define([ "jquery" ], factory );
11  } else {
12 
13  // Browser globals
14  factory( jQuery );
15  }
16 }(function( $ ) {
17 
18 $.ui = $.ui || {};
19 
20 var version = $.ui.version = "1.12.1";
21 
22 
32 //>>label: Widget
33 //>>group: Core
34 //>>description: Provides a factory for creating stateful widgets with a common API.
35 //>>docs: http://api.jqueryui.com/jQuery.widget/
36 //>>demos: http://jqueryui.com/widget/
37 
38 
39 
40 var widgetUuid = 0;
41 var widgetSlice = Array.prototype.slice;
42 
43 $.cleanData = ( function( orig ) {
44  return function( elems ) {
45  var events, elem, i;
46  for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
47  try {
48 
49  // Only trigger remove when necessary to save time
50  events = $._data( elem, "events" );
51  if ( events && events.remove ) {
52  $( elem ).triggerHandler( "remove" );
53  }
54 
55  // Http://bugs.jquery.com/ticket/8235
56  } catch ( e ) {}
57  }
58  orig( elems );
59  };
60 } )( $.cleanData );
61 
62 $.widget = function( name, base, prototype ) {
63  var existingConstructor, constructor, basePrototype;
64 
65  // ProxiedPrototype allows the provided prototype to remain unmodified
66  // so that it can be used as a mixin for multiple widgets (#8876)
67  var proxiedPrototype = {};
68 
69  var namespace = name.split( "." )[ 0 ];
70  name = name.split( "." )[ 1 ];
71  var fullName = namespace + "-" + name;
72 
73  if ( !prototype ) {
74  prototype = base;
75  base = $.Widget;
76  }
77 
78  if ( $.isArray( prototype ) ) {
79  prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
80  }
81 
82  // Create selector for plugin
83  $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
84  return !!$.data( elem, fullName );
85  };
86 
87  $[ namespace ] = $[ namespace ] || {};
88  existingConstructor = $[ namespace ][ name ];
89  constructor = $[ namespace ][ name ] = function( options, element ) {
90 
91  // Allow instantiation without "new" keyword
92  if ( !this._createWidget ) {
93  return new constructor( options, element );
94  }
95 
96  // Allow instantiation without initializing for simple inheritance
97  // must use "new" keyword (the code above always passes args)
98  if ( arguments.length ) {
99  this._createWidget( options, element );
100  }
101  };
102 
103  // Extend with the existing constructor to carry over any static properties
104  $.extend( constructor, existingConstructor, {
105  version: prototype.version,
106 
107  // Copy the object used to create the prototype in case we need to
108  // redefine the widget later
109  _proto: $.extend( {}, prototype ),
110 
111  // Track widgets that inherit from this widget in case this widget is
112  // redefined after a widget inherits from it
113  _childConstructors: []
114  } );
115 
116  basePrototype = new base();
117 
118  // We need to make the options hash a property directly on the new instance
119  // otherwise we'll modify the options hash on the prototype that we're
120  // inheriting from
121  basePrototype.options = $.widget.extend( {}, basePrototype.options );
122  $.each( prototype, function( prop, value ) {
123  if ( !$.isFunction( value ) ) {
124  proxiedPrototype[ prop ] = value;
125  return;
126  }
127  proxiedPrototype[ prop ] = ( function() {
128  function _super() {
129  return base.prototype[ prop ].apply( this, arguments );
130  }
131 
132  function _superApply( args ) {
133  return base.prototype[ prop ].apply( this, args );
134  }
135 
136  return function() {
137  var __super = this._super;
138  var __superApply = this._superApply;
139  var returnValue;
140 
141  this._super = _super;
142  this._superApply = _superApply;
143 
144  returnValue = value.apply( this, arguments );
145 
146  this._super = __super;
147  this._superApply = __superApply;
148 
149  return returnValue;
150  };
151  } )();
152  } );
153  constructor.prototype = $.widget.extend( basePrototype, {
154 
155  // TODO: remove support for widgetEventPrefix
156  // always use the name + a colon as the prefix, e.g., draggable:start
157  // don't prefix for widgets that aren't DOM-based
158  widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
159  }, proxiedPrototype, {
160  constructor: constructor,
161  namespace: namespace,
162  widgetName: name,
163  widgetFullName: fullName
164  } );
165 
166  // If this widget is being redefined then we need to find all widgets that
167  // are inheriting from it and redefine all of them so that they inherit from
168  // the new version of this widget. We're essentially trying to replace one
169  // level in the prototype chain.
170  if ( existingConstructor ) {
171  $.each( existingConstructor._childConstructors, function( i, child ) {
172  var childPrototype = child.prototype;
173 
174  // Redefine the child widget using the same prototype that was
175  // originally used, but inherit from the new version of the base
176  $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
177  child._proto );
178  } );
179 
180  // Remove the list of existing child constructors from the old constructor
181  // so the old child constructors can be garbage collected
182  delete existingConstructor._childConstructors;
183  } else {
184  base._childConstructors.push( constructor );
185  }
186 
187  $.widget.bridge( name, constructor );
188 
189  return constructor;
190 };
191 
192 $.widget.extend = function( target ) {
193  var input = widgetSlice.call( arguments, 1 );
194  var inputIndex = 0;
195  var inputLength = input.length;
196  var key;
197  var value;
198 
199  for ( ; inputIndex < inputLength; inputIndex++ ) {
200  for ( key in input[ inputIndex ] ) {
201  value = input[ inputIndex ][ key ];
202  if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
203 
204  // Clone objects
205  if ( $.isPlainObject( value ) ) {
206  target[ key ] = $.isPlainObject( target[ key ] ) ?
207  $.widget.extend( {}, target[ key ], value ) :
208 
209  // Don't extend strings, arrays, etc. with objects
210  $.widget.extend( {}, value );
211 
212  // Copy everything else by reference
213  } else {
214  target[ key ] = value;
215  }
216  }
217  }
218  }
219  return target;
220 };
221 
222 $.widget.bridge = function( name, object ) {
223  var fullName = object.prototype.widgetFullName || name;
224  $.fn[ name ] = function( options ) {
225  var isMethodCall = typeof options === "string";
226  var args = widgetSlice.call( arguments, 1 );
227  var returnValue = this;
228 
229  if ( isMethodCall ) {
230 
231  // If this is an empty collection, we need to have the instance method
232  // return undefined instead of the jQuery instance
233  if ( !this.length && options === "instance" ) {
234  returnValue = undefined;
235  } else {
236  this.each( function() {
237  var methodValue;
238  var instance = $.data( this, fullName );
239 
240  if ( options === "instance" ) {
241  returnValue = instance;
242  return false;
243  }
244 
245  if ( !instance ) {
246  return $.error( "cannot call methods on " + name +
247  " prior to initialization; " +
248  "attempted to call method '" + options + "'" );
249  }
250 
251  if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
252  return $.error( "no such method '" + options + "' for " + name +
253  " widget instance" );
254  }
255 
256  methodValue = instance[ options ].apply( instance, args );
257 
258  if ( methodValue !== instance && methodValue !== undefined ) {
259  returnValue = methodValue && methodValue.jquery ?
260  returnValue.pushStack( methodValue.get() ) :
261  methodValue;
262  return false;
263  }
264  } );
265  }
266  } else {
267 
268  // Allow multiple hashes to be passed on init
269  if ( args.length ) {
270  options = $.widget.extend.apply( null, [ options ].concat( args ) );
271  }
272 
273  this.each( function() {
274  var instance = $.data( this, fullName );
275  if ( instance ) {
276  instance.option( options || {} );
277  if ( instance._init ) {
278  instance._init();
279  }
280  } else {
281  $.data( this, fullName, new object( options, this ) );
282  }
283  } );
284  }
285 
286  return returnValue;
287  };
288 };
289 
290 $.Widget = function( /* options, element */ ) {};
291 $.Widget._childConstructors = [];
292 
293 $.Widget.prototype = {
294  widgetName: "widget",
295  widgetEventPrefix: "",
296  defaultElement: "<div>",
297 
298  options: {
299  classes: {},
300  disabled: false,
301 
302  // Callbacks
303  create: null
304  },
305 
306  _createWidget: function( options, element ) {
307  element = $( element || this.defaultElement || this )[ 0 ];
308  this.element = $( element );
309  this.uuid = widgetUuid++;
310  this.eventNamespace = "." + this.widgetName + this.uuid;
311 
312  this.bindings = $();
313  this.hoverable = $();
314  this.focusable = $();
315  this.classesElementLookup = {};
316 
317  if ( element !== this ) {
318  $.data( element, this.widgetFullName, this );
319  this._on( true, this.element, {
320  remove: function( event ) {
321  if ( event.target === element ) {
322  this.destroy();
323  }
324  }
325  } );
326  this.document = $( element.style ?
327 
328  // Element within the document
329  element.ownerDocument :
330 
331  // Element is window or document
332  element.document || element );
333  this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334  }
335 
336  this.options = $.widget.extend( {},
337  this.options,
338  this._getCreateOptions(),
339  options );
340 
341  this._create();
342 
343  if ( this.options.disabled ) {
344  this._setOptionDisabled( this.options.disabled );
345  }
346 
347  this._trigger( "create", null, this._getCreateEventData() );
348  this._init();
349  },
350 
351  _getCreateOptions: function() {
352  return {};
353  },
354 
355  _getCreateEventData: $.noop,
356 
357  _create: $.noop,
358 
359  _init: $.noop,
360 
361  destroy: function() {
362  var that = this;
363 
364  this._destroy();
365  $.each( this.classesElementLookup, function( key, value ) {
366  that._removeClass( value, key );
367  } );
368 
369  // We can probably remove the unbind calls in 2.0
370  // all event bindings should go through this._on()
371  this.element
372  .off( this.eventNamespace )
373  .removeData( this.widgetFullName );
374  this.widget()
375  .off( this.eventNamespace )
376  .removeAttr( "aria-disabled" );
377 
378  // Clean up events and states
379  this.bindings.off( this.eventNamespace );
380  },
381 
382  _destroy: $.noop,
383 
384  widget: function() {
385  return this.element;
386  },
387 
388  option: function( key, value ) {
389  var options = key;
390  var parts;
391  var curOption;
392  var i;
393 
394  if ( arguments.length === 0 ) {
395 
396  // Don't return a reference to the internal hash
397  return $.widget.extend( {}, this.options );
398  }
399 
400  if ( typeof key === "string" ) {
401 
402  // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
403  options = {};
404  parts = key.split( "." );
405  key = parts.shift();
406  if ( parts.length ) {
407  curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
408  for ( i = 0; i < parts.length - 1; i++ ) {
409  curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
410  curOption = curOption[ parts[ i ] ];
411  }
412  key = parts.pop();
413  if ( arguments.length === 1 ) {
414  return curOption[ key ] === undefined ? null : curOption[ key ];
415  }
416  curOption[ key ] = value;
417  } else {
418  if ( arguments.length === 1 ) {
419  return this.options[ key ] === undefined ? null : this.options[ key ];
420  }
421  options[ key ] = value;
422  }
423  }
424 
425  this._setOptions( options );
426 
427  return this;
428  },
429 
430  _setOptions: function( options ) {
431  var key;
432 
433  for ( key in options ) {
434  this._setOption( key, options[ key ] );
435  }
436 
437  return this;
438  },
439 
440  _setOption: function( key, value ) {
441  if ( key === "classes" ) {
442  this._setOptionClasses( value );
443  }
444 
445  this.options[ key ] = value;
446 
447  if ( key === "disabled" ) {
448  this._setOptionDisabled( value );
449  }
450 
451  return this;
452  },
453 
454  _setOptionClasses: function( value ) {
455  var classKey, elements, currentElements;
456 
457  for ( classKey in value ) {
458  currentElements = this.classesElementLookup[ classKey ];
459  if ( value[ classKey ] === this.options.classes[ classKey ] ||
460  !currentElements ||
461  !currentElements.length ) {
462  continue;
463  }
464 
465  // We are doing this to create a new jQuery object because the _removeClass() call
466  // on the next line is going to destroy the reference to the current elements being
467  // tracked. We need to save a copy of this collection so that we can add the new classes
468  // below.
469  elements = $( currentElements.get() );
470  this._removeClass( currentElements, classKey );
471 
472  // We don't use _addClass() here, because that uses this.options.classes
473  // for generating the string of classes. We want to use the value passed in from
474  // _setOption(), this is the new value of the classes option which was passed to
475  // _setOption(). We pass this value directly to _classes().
476  elements.addClass( this._classes( {
477  element: elements,
478  keys: classKey,
479  classes: value,
480  add: true
481  } ) );
482  }
483  },
484 
485  _setOptionDisabled: function( value ) {
486  this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
487 
488  // If the widget is becoming disabled, then nothing is interactive
489  if ( value ) {
490  this._removeClass( this.hoverable, null, "ui-state-hover" );
491  this._removeClass( this.focusable, null, "ui-state-focus" );
492  }
493  },
494 
495  enable: function() {
496  return this._setOptions( { disabled: false } );
497  },
498 
499  disable: function() {
500  return this._setOptions( { disabled: true } );
501  },
502 
503  _classes: function( options ) {
504  var full = [];
505  var that = this;
506 
507  options = $.extend( {
508  element: this.element,
509  classes: this.options.classes || {}
510  }, options );
511 
512  function processClassString( classes, checkOption ) {
513  var current, i;
514  for ( i = 0; i < classes.length; i++ ) {
515  current = that.classesElementLookup[ classes[ i ] ] || $();
516  if ( options.add ) {
517  current = $( $.unique( current.get().concat( options.element.get() ) ) );
518  } else {
519  current = $( current.not( options.element ).get() );
520  }
521  that.classesElementLookup[ classes[ i ] ] = current;
522  full.push( classes[ i ] );
523  if ( checkOption && options.classes[ classes[ i ] ] ) {
524  full.push( options.classes[ classes[ i ] ] );
525  }
526  }
527  }
528 
529  this._on( options.element, {
530  "remove": "_untrackClassesElement"
531  } );
532 
533  if ( options.keys ) {
534  processClassString( options.keys.match( /\S+/g ) || [], true );
535  }
536  if ( options.extra ) {
537  processClassString( options.extra.match( /\S+/g ) || [] );
538  }
539 
540  return full.join( " " );
541  },
542 
543  _untrackClassesElement: function( event ) {
544  var that = this;
545  $.each( that.classesElementLookup, function( key, value ) {
546  if ( $.inArray( event.target, value ) !== -1 ) {
547  that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
548  }
549  } );
550  },
551 
552  _removeClass: function( element, keys, extra ) {
553  return this._toggleClass( element, keys, extra, false );
554  },
555 
556  _addClass: function( element, keys, extra ) {
557  return this._toggleClass( element, keys, extra, true );
558  },
559 
560  _toggleClass: function( element, keys, extra, add ) {
561  add = ( typeof add === "boolean" ) ? add : extra;
562  var shift = ( typeof element === "string" || element === null ),
563  options = {
564  extra: shift ? keys : extra,
565  keys: shift ? element : keys,
566  element: shift ? this.element : element,
567  add: add
568  };
569  options.element.toggleClass( this._classes( options ), add );
570  return this;
571  },
572 
573  _on: function( suppressDisabledCheck, element, handlers ) {
574  var delegateElement;
575  var instance = this;
576 
577  // No suppressDisabledCheck flag, shuffle arguments
578  if ( typeof suppressDisabledCheck !== "boolean" ) {
579  handlers = element;
580  element = suppressDisabledCheck;
581  suppressDisabledCheck = false;
582  }
583 
584  // No element argument, shuffle and use this.element
585  if ( !handlers ) {
586  handlers = element;
587  element = this.element;
588  delegateElement = this.widget();
589  } else {
590  element = delegateElement = $( element );
591  this.bindings = this.bindings.add( element );
592  }
593 
594  $.each( handlers, function( event, handler ) {
595  function handlerProxy() {
596 
597  // Allow widgets to customize the disabled handling
598  // - disabled as an array instead of boolean
599  // - disabled class as method for disabling individual parts
600  if ( !suppressDisabledCheck &&
601  ( instance.options.disabled === true ||
602  $( this ).hasClass( "ui-state-disabled" ) ) ) {
603  return;
604  }
605  return ( typeof handler === "string" ? instance[ handler ] : handler )
606  .apply( instance, arguments );
607  }
608 
609  // Copy the guid so direct unbinding works
610  if ( typeof handler !== "string" ) {
611  handlerProxy.guid = handler.guid =
612  handler.guid || handlerProxy.guid || $.guid++;
613  }
614 
615  var match = event.match( /^([\w:-]*)\s*(.*)$/ );
616  var eventName = match[ 1 ] + instance.eventNamespace;
617  var selector = match[ 2 ];
618 
619  if ( selector ) {
620  delegateElement.on( eventName, selector, handlerProxy );
621  } else {
622  element.on( eventName, handlerProxy );
623  }
624  } );
625  },
626 
627  _off: function( element, eventName ) {
628  eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
629  this.eventNamespace;
630  element.off( eventName ).off( eventName );
631 
632  // Clear the stack to avoid memory leaks (#10056)
633  this.bindings = $( this.bindings.not( element ).get() );
634  this.focusable = $( this.focusable.not( element ).get() );
635  this.hoverable = $( this.hoverable.not( element ).get() );
636  },
637 
638  _delay: function( handler, delay ) {
639  function handlerProxy() {
640  return ( typeof handler === "string" ? instance[ handler ] : handler )
641  .apply( instance, arguments );
642  }
643  var instance = this;
644  return setTimeout( handlerProxy, delay || 0 );
645  },
646 
647  _hoverable: function( element ) {
648  this.hoverable = this.hoverable.add( element );
649  this._on( element, {
650  mouseenter: function( event ) {
651  this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
652  },
653  mouseleave: function( event ) {
654  this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
655  }
656  } );
657  },
658 
659  _focusable: function( element ) {
660  this.focusable = this.focusable.add( element );
661  this._on( element, {
662  focusin: function( event ) {
663  this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
664  },
665  focusout: function( event ) {
666  this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
667  }
668  } );
669  },
670 
671  _trigger: function( type, event, data ) {
672  var prop, orig;
673  var callback = this.options[ type ];
674 
675  data = data || {};
676  event = $.Event( event );
677  event.type = ( type === this.widgetEventPrefix ?
678  type :
679  this.widgetEventPrefix + type ).toLowerCase();
680 
681  // The original event may come from any element
682  // so we need to reset the target on the new event
683  event.target = this.element[ 0 ];
684 
685  // Copy original event properties over to the new event
686  orig = event.originalEvent;
687  if ( orig ) {
688  for ( prop in orig ) {
689  if ( !( prop in event ) ) {
690  event[ prop ] = orig[ prop ];
691  }
692  }
693  }
694 
695  this.element.trigger( event, data );
696  return !( $.isFunction( callback ) &&
697  callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
698  event.isDefaultPrevented() );
699  }
700 };
701 
702 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
703  $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
704  if ( typeof options === "string" ) {
705  options = { effect: options };
706  }
707 
708  var hasOptions;
709  var effectName = !options ?
710  method :
711  options === true || typeof options === "number" ?
712  defaultEffect :
713  options.effect || defaultEffect;
714 
715  options = options || {};
716  if ( typeof options === "number" ) {
717  options = { duration: options };
718  }
719 
720  hasOptions = !$.isEmptyObject( options );
721  options.complete = callback;
722 
723  if ( options.delay ) {
724  element.delay( options.delay );
725  }
726 
727  if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
728  element[ method ]( options );
729  } else if ( effectName !== method && element[ effectName ] ) {
730  element[ effectName ]( options.duration, options.easing, callback );
731  } else {
732  element.queue( function( next ) {
733  $( this )[ method ]();
734  if ( callback ) {
735  callback.call( element[ 0 ] );
736  }
737  next();
738  } );
739  }
740  };
741 } );
742 
743 var widget = $.widget;
744 
745 
757 //>>label: Position
758 //>>group: Core
759 //>>description: Positions elements relative to other elements.
760 //>>docs: http://api.jqueryui.com/position/
761 //>>demos: http://jqueryui.com/position/
762 
763 
764 ( function() {
765 var cachedScrollbarWidth,
766  max = Math.max,
767  abs = Math.abs,
768  rhorizontal = /left|center|right/,
769  rvertical = /top|center|bottom/,
770  roffset = /[\+\-]\d+(\.[\d]+)?%?/,
771  rposition = /^\w+/,
772  rpercent = /%$/,
773  _position = $.fn.position;
774 
775 function getOffsets( offsets, width, height ) {
776  return [
777  parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
778  parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
779  ];
780 }
781 
782 function parseCss( element, property ) {
783  return parseInt( $.css( element, property ), 10 ) || 0;
784 }
785 
786 function getDimensions( elem ) {
787  var raw = elem[ 0 ];
788  if ( raw.nodeType === 9 ) {
789  return {
790  width: elem.width(),
791  height: elem.height(),
792  offset: { top: 0, left: 0 }
793  };
794  }
795  if ( $.isWindow( raw ) ) {
796  return {
797  width: elem.width(),
798  height: elem.height(),
799  offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
800  };
801  }
802  if ( raw.preventDefault ) {
803  return {
804  width: 0,
805  height: 0,
806  offset: { top: raw.pageY, left: raw.pageX }
807  };
808  }
809  return {
810  width: elem.outerWidth(),
811  height: elem.outerHeight(),
812  offset: elem.offset()
813  };
814 }
815 
816 $.position = {
817  scrollbarWidth: function() {
818  if ( cachedScrollbarWidth !== undefined ) {
819  return cachedScrollbarWidth;
820  }
821  var w1, w2,
822  div = $( "<div " +
823  "style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
824  "<div style='height:100px;width:auto;'></div></div>" ),
825  innerDiv = div.children()[ 0 ];
826 
827  $( "body" ).append( div );
828  w1 = innerDiv.offsetWidth;
829  div.css( "overflow", "scroll" );
830 
831  w2 = innerDiv.offsetWidth;
832 
833  if ( w1 === w2 ) {
834  w2 = div[ 0 ].clientWidth;
835  }
836 
837  div.remove();
838 
839  return ( cachedScrollbarWidth = w1 - w2 );
840  },
841  getScrollInfo: function( within ) {
842  var overflowX = within.isWindow || within.isDocument ? "" :
843  within.element.css( "overflow-x" ),
844  overflowY = within.isWindow || within.isDocument ? "" :
845  within.element.css( "overflow-y" ),
846  hasOverflowX = overflowX === "scroll" ||
847  ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
848  hasOverflowY = overflowY === "scroll" ||
849  ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
850  return {
851  width: hasOverflowY ? $.position.scrollbarWidth() : 0,
852  height: hasOverflowX ? $.position.scrollbarWidth() : 0
853  };
854  },
855  getWithinInfo: function( element ) {
856  var withinElement = $( element || window ),
857  isWindow = $.isWindow( withinElement[ 0 ] ),
858  isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
859  hasOffset = !isWindow && !isDocument;
860  return {
861  element: withinElement,
862  isWindow: isWindow,
863  isDocument: isDocument,
864  offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
865  scrollLeft: withinElement.scrollLeft(),
866  scrollTop: withinElement.scrollTop(),
867  width: withinElement.outerWidth(),
868  height: withinElement.outerHeight()
869  };
870  }
871 };
872 
873 $.fn.position = function( options ) {
874  if ( !options || !options.of ) {
875  return _position.apply( this, arguments );
876  }
877 
878  // Make a copy, we don't want to modify arguments
879  options = $.extend( {}, options );
880 
881  var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
882  target = $( options.of ),
883  within = $.position.getWithinInfo( options.within ),
884  scrollInfo = $.position.getScrollInfo( within ),
885  collision = ( options.collision || "flip" ).split( " " ),
886  offsets = {};
887 
888  dimensions = getDimensions( target );
889  if ( target[ 0 ].preventDefault ) {
890 
891  // Force left top to allow flipping
892  options.at = "left top";
893  }
894  targetWidth = dimensions.width;
895  targetHeight = dimensions.height;
896  targetOffset = dimensions.offset;
897 
898  // Clone to reuse original targetOffset later
899  basePosition = $.extend( {}, targetOffset );
900 
901  // Force my and at to have valid horizontal and vertical positions
902  // if a value is missing or invalid, it will be converted to center
903  $.each( [ "my", "at" ], function() {
904  var pos = ( options[ this ] || "" ).split( " " ),
905  horizontalOffset,
906  verticalOffset;
907 
908  if ( pos.length === 1 ) {
909  pos = rhorizontal.test( pos[ 0 ] ) ?
910  pos.concat( [ "center" ] ) :
911  rvertical.test( pos[ 0 ] ) ?
912  [ "center" ].concat( pos ) :
913  [ "center", "center" ];
914  }
915  pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
916  pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
917 
918  // Calculate offsets
919  horizontalOffset = roffset.exec( pos[ 0 ] );
920  verticalOffset = roffset.exec( pos[ 1 ] );
921  offsets[ this ] = [
922  horizontalOffset ? horizontalOffset[ 0 ] : 0,
923  verticalOffset ? verticalOffset[ 0 ] : 0
924  ];
925 
926  // Reduce to just the positions without the offsets
927  options[ this ] = [
928  rposition.exec( pos[ 0 ] )[ 0 ],
929  rposition.exec( pos[ 1 ] )[ 0 ]
930  ];
931  } );
932 
933  // Normalize collision option
934  if ( collision.length === 1 ) {
935  collision[ 1 ] = collision[ 0 ];
936  }
937 
938  if ( options.at[ 0 ] === "right" ) {
939  basePosition.left += targetWidth;
940  } else if ( options.at[ 0 ] === "center" ) {
941  basePosition.left += targetWidth / 2;
942  }
943 
944  if ( options.at[ 1 ] === "bottom" ) {
945  basePosition.top += targetHeight;
946  } else if ( options.at[ 1 ] === "center" ) {
947  basePosition.top += targetHeight / 2;
948  }
949 
950  atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
951  basePosition.left += atOffset[ 0 ];
952  basePosition.top += atOffset[ 1 ];
953 
954  return this.each( function() {
955  var collisionPosition, using,
956  elem = $( this ),
957  elemWidth = elem.outerWidth(),
958  elemHeight = elem.outerHeight(),
959  marginLeft = parseCss( this, "marginLeft" ),
960  marginTop = parseCss( this, "marginTop" ),
961  collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
962  scrollInfo.width,
963  collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
964  scrollInfo.height,
965  position = $.extend( {}, basePosition ),
966  myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
967 
968  if ( options.my[ 0 ] === "right" ) {
969  position.left -= elemWidth;
970  } else if ( options.my[ 0 ] === "center" ) {
971  position.left -= elemWidth / 2;
972  }
973 
974  if ( options.my[ 1 ] === "bottom" ) {
975  position.top -= elemHeight;
976  } else if ( options.my[ 1 ] === "center" ) {
977  position.top -= elemHeight / 2;
978  }
979 
980  position.left += myOffset[ 0 ];
981  position.top += myOffset[ 1 ];
982 
983  collisionPosition = {
984  marginLeft: marginLeft,
985  marginTop: marginTop
986  };
987 
988  $.each( [ "left", "top" ], function( i, dir ) {
989  if ( $.ui.position[ collision[ i ] ] ) {
990  $.ui.position[ collision[ i ] ][ dir ]( position, {
991  targetWidth: targetWidth,
992  targetHeight: targetHeight,
993  elemWidth: elemWidth,
994  elemHeight: elemHeight,
995  collisionPosition: collisionPosition,
996  collisionWidth: collisionWidth,
997  collisionHeight: collisionHeight,
998  offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
999  my: options.my,
1000  at: options.at,
1001  within: within,
1002  elem: elem
1003  } );
1004  }
1005  } );
1006 
1007  if ( options.using ) {
1008 
1009  // Adds feedback as second argument to using callback, if present
1010  using = function( props ) {
1011  var left = targetOffset.left - position.left,
1012  right = left + targetWidth - elemWidth,
1013  top = targetOffset.top - position.top,
1014  bottom = top + targetHeight - elemHeight,
1015  feedback = {
1016  target: {
1017  element: target,
1018  left: targetOffset.left,
1019  top: targetOffset.top,
1020  width: targetWidth,
1021  height: targetHeight
1022  },
1023  element: {
1024  element: elem,
1025  left: position.left,
1026  top: position.top,
1027  width: elemWidth,
1028  height: elemHeight
1029  },
1030  horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1031  vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1032  };
1033  if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1034  feedback.horizontal = "center";
1035  }
1036  if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1037  feedback.vertical = "middle";
1038  }
1039  if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1040  feedback.important = "horizontal";
1041  } else {
1042  feedback.important = "vertical";
1043  }
1044  options.using.call( this, props, feedback );
1045  };
1046  }
1047 
1048  elem.offset( $.extend( position, { using: using } ) );
1049  } );
1050 };
1051 
1052 $.ui.position = {
1053  fit: {
1054  left: function( position, data ) {
1055  var within = data.within,
1056  withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1057  outerWidth = within.width,
1058  collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1059  overLeft = withinOffset - collisionPosLeft,
1060  overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1061  newOverRight;
1062 
1063  // Element is wider than within
1064  if ( data.collisionWidth > outerWidth ) {
1065 
1066  // Element is initially over the left side of within
1067  if ( overLeft > 0 && overRight <= 0 ) {
1068  newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1069  withinOffset;
1070  position.left += overLeft - newOverRight;
1071 
1072  // Element is initially over right side of within
1073  } else if ( overRight > 0 && overLeft <= 0 ) {
1074  position.left = withinOffset;
1075 
1076  // Element is initially over both left and right sides of within
1077  } else {
1078  if ( overLeft > overRight ) {
1079  position.left = withinOffset + outerWidth - data.collisionWidth;
1080  } else {
1081  position.left = withinOffset;
1082  }
1083  }
1084 
1085  // Too far left -> align with left edge
1086  } else if ( overLeft > 0 ) {
1087  position.left += overLeft;
1088 
1089  // Too far right -> align with right edge
1090  } else if ( overRight > 0 ) {
1091  position.left -= overRight;
1092 
1093  // Adjust based on position and margin
1094  } else {
1095  position.left = max( position.left - collisionPosLeft, position.left );
1096  }
1097  },
1098  top: function( position, data ) {
1099  var within = data.within,
1100  withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1101  outerHeight = data.within.height,
1102  collisionPosTop = position.top - data.collisionPosition.marginTop,
1103  overTop = withinOffset - collisionPosTop,
1104  overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1105  newOverBottom;
1106 
1107  // Element is taller than within
1108  if ( data.collisionHeight > outerHeight ) {
1109 
1110  // Element is initially over the top of within
1111  if ( overTop > 0 && overBottom <= 0 ) {
1112  newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1113  withinOffset;
1114  position.top += overTop - newOverBottom;
1115 
1116  // Element is initially over bottom of within
1117  } else if ( overBottom > 0 && overTop <= 0 ) {
1118  position.top = withinOffset;
1119 
1120  // Element is initially over both top and bottom of within
1121  } else {
1122  if ( overTop > overBottom ) {
1123  position.top = withinOffset + outerHeight - data.collisionHeight;
1124  } else {
1125  position.top = withinOffset;
1126  }
1127  }
1128 
1129  // Too far up -> align with top
1130  } else if ( overTop > 0 ) {
1131  position.top += overTop;
1132 
1133  // Too far down -> align with bottom edge
1134  } else if ( overBottom > 0 ) {
1135  position.top -= overBottom;
1136 
1137  // Adjust based on position and margin
1138  } else {
1139  position.top = max( position.top - collisionPosTop, position.top );
1140  }
1141  }
1142  },
1143  flip: {
1144  left: function( position, data ) {
1145  var within = data.within,
1146  withinOffset = within.offset.left + within.scrollLeft,
1147  outerWidth = within.width,
1148  offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1149  collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1150  overLeft = collisionPosLeft - offsetLeft,
1151  overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1152  myOffset = data.my[ 0 ] === "left" ?
1153  -data.elemWidth :
1154  data.my[ 0 ] === "right" ?
1155  data.elemWidth :
1156  0,
1157  atOffset = data.at[ 0 ] === "left" ?
1158  data.targetWidth :
1159  data.at[ 0 ] === "right" ?
1160  -data.targetWidth :
1161  0,
1162  offset = -2 * data.offset[ 0 ],
1163  newOverRight,
1164  newOverLeft;
1165 
1166  if ( overLeft < 0 ) {
1167  newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1168  outerWidth - withinOffset;
1169  if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1170  position.left += myOffset + atOffset + offset;
1171  }
1172  } else if ( overRight > 0 ) {
1173  newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1174  atOffset + offset - offsetLeft;
1175  if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1176  position.left += myOffset + atOffset + offset;
1177  }
1178  }
1179  },
1180  top: function( position, data ) {
1181  var within = data.within,
1182  withinOffset = within.offset.top + within.scrollTop,
1183  outerHeight = within.height,
1184  offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1185  collisionPosTop = position.top - data.collisionPosition.marginTop,
1186  overTop = collisionPosTop - offsetTop,
1187  overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1188  top = data.my[ 1 ] === "top",
1189  myOffset = top ?
1190  -data.elemHeight :
1191  data.my[ 1 ] === "bottom" ?
1192  data.elemHeight :
1193  0,
1194  atOffset = data.at[ 1 ] === "top" ?
1195  data.targetHeight :
1196  data.at[ 1 ] === "bottom" ?
1197  -data.targetHeight :
1198  0,
1199  offset = -2 * data.offset[ 1 ],
1200  newOverTop,
1201  newOverBottom;
1202  if ( overTop < 0 ) {
1203  newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1204  outerHeight - withinOffset;
1205  if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1206  position.top += myOffset + atOffset + offset;
1207  }
1208  } else if ( overBottom > 0 ) {
1209  newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1210  offset - offsetTop;
1211  if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1212  position.top += myOffset + atOffset + offset;
1213  }
1214  }
1215  }
1216  },
1217  flipfit: {
1218  left: function() {
1219  $.ui.position.flip.left.apply( this, arguments );
1220  $.ui.position.fit.left.apply( this, arguments );
1221  },
1222  top: function() {
1223  $.ui.position.flip.top.apply( this, arguments );
1224  $.ui.position.fit.top.apply( this, arguments );
1225  }
1226  }
1227 };
1228 
1229 } )();
1230 
1231 var position = $.ui.position;
1232 
1233 
1243 //>>label: :data Selector
1244 //>>group: Core
1245 //>>description: Selects elements which have data stored under the specified key.
1246 //>>docs: http://api.jqueryui.com/data-selector/
1247 
1248 
1249 var data = $.extend( $.expr[ ":" ], {
1250  data: $.expr.createPseudo ?
1251  $.expr.createPseudo( function( dataName ) {
1252  return function( elem ) {
1253  return !!$.data( elem, dataName );
1254  };
1255  } ) :
1256 
1257  // Support: jQuery <1.8
1258  function( elem, i, match ) {
1259  return !!$.data( elem, match[ 3 ] );
1260  }
1261 } );
1262 
1272 //>>label: disableSelection
1273 //>>group: Core
1274 //>>description: Disable selection of text content within the set of matched elements.
1275 //>>docs: http://api.jqueryui.com/disableSelection/
1276 
1277 // This file is deprecated
1278 
1279 
1280 var disableSelection = $.fn.extend( {
1281  disableSelection: ( function() {
1282  var eventType = "onselectstart" in document.createElement( "div" ) ?
1283  "selectstart" :
1284  "mousedown";
1285 
1286  return function() {
1287  return this.on( eventType + ".ui-disableSelection", function( event ) {
1288  event.preventDefault();
1289  } );
1290  };
1291  } )(),
1292 
1293  enableSelection: function() {
1294  return this.off( ".ui-disableSelection" );
1295  }
1296 } );
1297 
1298 
1308 //>>label: Effects Core
1309 //>>group: Effects
1310 // jscs:disable maximumLineLength
1311 //>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
1312 // jscs:enable maximumLineLength
1313 //>>docs: http://api.jqueryui.com/category/effects-core/
1314 //>>demos: http://jqueryui.com/effect/
1315 
1316 
1317 
1318 var dataSpace = "ui-effects-",
1319  dataSpaceStyle = "ui-effects-style",
1320  dataSpaceAnimated = "ui-effects-animated",
1321 
1322  // Create a local jQuery because jQuery Color relies on it and the
1323  // global may not exist with AMD and a custom build (#10199)
1324  jQuery = $;
1325 
1326 $.effects = {
1327  effect: {}
1328 };
1329 
1340 ( function( jQuery, undefined ) {
1341 
1342  var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1343  "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1344 
1345  // Plusequals test for += 100 -= 100
1346  rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1347 
1348  // A set of RE's that can match strings and generate color tuples.
1349  stringParsers = [ {
1350  re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1351  parse: function( execResult ) {
1352  return [
1353  execResult[ 1 ],
1354  execResult[ 2 ],
1355  execResult[ 3 ],
1356  execResult[ 4 ]
1357  ];
1358  }
1359  }, {
1360  re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1361  parse: function( execResult ) {
1362  return [
1363  execResult[ 1 ] * 2.55,
1364  execResult[ 2 ] * 2.55,
1365  execResult[ 3 ] * 2.55,
1366  execResult[ 4 ]
1367  ];
1368  }
1369  }, {
1370 
1371  // This regex ignores A-F because it's compared against an already lowercased string
1372  re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
1373  parse: function( execResult ) {
1374  return [
1375  parseInt( execResult[ 1 ], 16 ),
1376  parseInt( execResult[ 2 ], 16 ),
1377  parseInt( execResult[ 3 ], 16 )
1378  ];
1379  }
1380  }, {
1381 
1382  // This regex ignores A-F because it's compared against an already lowercased string
1383  re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
1384  parse: function( execResult ) {
1385  return [
1386  parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1387  parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1388  parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
1389  ];
1390  }
1391  }, {
1392  re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1393  space: "hsla",
1394  parse: function( execResult ) {
1395  return [
1396  execResult[ 1 ],
1397  execResult[ 2 ] / 100,
1398  execResult[ 3 ] / 100,
1399  execResult[ 4 ]
1400  ];
1401  }
1402  } ],
1403 
1404  // JQuery.Color( )
1405  color = jQuery.Color = function( color, green, blue, alpha ) {
1406  return new jQuery.Color.fn.parse( color, green, blue, alpha );
1407  },
1408  spaces = {
1409  rgba: {
1410  props: {
1411  red: {
1412  idx: 0,
1413  type: "byte"
1414  },
1415  green: {
1416  idx: 1,
1417  type: "byte"
1418  },
1419  blue: {
1420  idx: 2,
1421  type: "byte"
1422  }
1423  }
1424  },
1425 
1426  hsla: {
1427  props: {
1428  hue: {
1429  idx: 0,
1430  type: "degrees"
1431  },
1432  saturation: {
1433  idx: 1,
1434  type: "percent"
1435  },
1436  lightness: {
1437  idx: 2,
1438  type: "percent"
1439  }
1440  }
1441  }
1442  },
1443  propTypes = {
1444  "byte": {
1445  floor: true,
1446  max: 255
1447  },
1448  "percent": {
1449  max: 1
1450  },
1451  "degrees": {
1452  mod: 360,
1453  floor: true
1454  }
1455  },
1456  support = color.support = {},
1457 
1458  // Element for support tests
1459  supportElem = jQuery( "<p>" )[ 0 ],
1460 
1461  // Colors = jQuery.Color.names
1462  colors,
1463 
1464  // Local aliases of functions called often
1465  each = jQuery.each;
1466 
1467 // Determine rgba support immediately
1468 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
1469 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
1470 
1471 // Define cache name and alpha properties
1472 // for rgba and hsla spaces
1473 each( spaces, function( spaceName, space ) {
1474  space.cache = "_" + spaceName;
1475  space.props.alpha = {
1476  idx: 3,
1477  type: "percent",
1478  def: 1
1479  };
1480 } );
1481 
1482 function clamp( value, prop, allowEmpty ) {
1483  var type = propTypes[ prop.type ] || {};
1484 
1485  if ( value == null ) {
1486  return ( allowEmpty || !prop.def ) ? null : prop.def;
1487  }
1488 
1489  // ~~ is an short way of doing floor for positive numbers
1490  value = type.floor ? ~~value : parseFloat( value );
1491 
1492  // IE will pass in empty strings as value for alpha,
1493  // which will hit this case
1494  if ( isNaN( value ) ) {
1495  return prop.def;
1496  }
1497 
1498  if ( type.mod ) {
1499 
1500  // We add mod before modding to make sure that negatives values
1501  // get converted properly: -10 -> 350
1502  return ( value + type.mod ) % type.mod;
1503  }
1504 
1505  // For now all property types without mod have min and max
1506  return 0 > value ? 0 : type.max < value ? type.max : value;
1507 }
1508 
1509 function stringParse( string ) {
1510  var inst = color(),
1511  rgba = inst._rgba = [];
1512 
1513  string = string.toLowerCase();
1514 
1515  each( stringParsers, function( i, parser ) {
1516  var parsed,
1517  match = parser.re.exec( string ),
1518  values = match && parser.parse( match ),
1519  spaceName = parser.space || "rgba";
1520 
1521  if ( values ) {
1522  parsed = inst[ spaceName ]( values );
1523 
1524  // If this was an rgba parse the assignment might happen twice
1525  // oh well....
1526  inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1527  rgba = inst._rgba = parsed._rgba;
1528 
1529  // Exit each( stringParsers ) here because we matched
1530  return false;
1531  }
1532  } );
1533 
1534  // Found a stringParser that handled it
1535  if ( rgba.length ) {
1536 
1537  // If this came from a parsed string, force "transparent" when alpha is 0
1538  // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1539  if ( rgba.join() === "0,0,0,0" ) {
1540  jQuery.extend( rgba, colors.transparent );
1541  }
1542  return inst;
1543  }
1544 
1545  // Named colors
1546  return colors[ string ];
1547 }
1548 
1549 color.fn = jQuery.extend( color.prototype, {
1550  parse: function( red, green, blue, alpha ) {
1551  if ( red === undefined ) {
1552  this._rgba = [ null, null, null, null ];
1553  return this;
1554  }
1555  if ( red.jquery || red.nodeType ) {
1556  red = jQuery( red ).css( green );
1557  green = undefined;
1558  }
1559 
1560  var inst = this,
1561  type = jQuery.type( red ),
1562  rgba = this._rgba = [];
1563 
1564  // More than 1 argument specified - assume ( red, green, blue, alpha )
1565  if ( green !== undefined ) {
1566  red = [ red, green, blue, alpha ];
1567  type = "array";
1568  }
1569 
1570  if ( type === "string" ) {
1571  return this.parse( stringParse( red ) || colors._default );
1572  }
1573 
1574  if ( type === "array" ) {
1575  each( spaces.rgba.props, function( key, prop ) {
1576  rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1577  } );
1578  return this;
1579  }
1580 
1581  if ( type === "object" ) {
1582  if ( red instanceof color ) {
1583  each( spaces, function( spaceName, space ) {
1584  if ( red[ space.cache ] ) {
1585  inst[ space.cache ] = red[ space.cache ].slice();
1586  }
1587  } );
1588  } else {
1589  each( spaces, function( spaceName, space ) {
1590  var cache = space.cache;
1591  each( space.props, function( key, prop ) {
1592 
1593  // If the cache doesn't exist, and we know how to convert
1594  if ( !inst[ cache ] && space.to ) {
1595 
1596  // If the value was null, we don't need to copy it
1597  // if the key was alpha, we don't need to copy it either
1598  if ( key === "alpha" || red[ key ] == null ) {
1599  return;
1600  }
1601  inst[ cache ] = space.to( inst._rgba );
1602  }
1603 
1604  // This is the only case where we allow nulls for ALL properties.
1605  // call clamp with alwaysAllowEmpty
1606  inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1607  } );
1608 
1609  // Everything defined but alpha?
1610  if ( inst[ cache ] &&
1611  jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
1612 
1613  // Use the default of 1
1614  inst[ cache ][ 3 ] = 1;
1615  if ( space.from ) {
1616  inst._rgba = space.from( inst[ cache ] );
1617  }
1618  }
1619  } );
1620  }
1621  return this;
1622  }
1623  },
1624  is: function( compare ) {
1625  var is = color( compare ),
1626  same = true,
1627  inst = this;
1628 
1629  each( spaces, function( _, space ) {
1630  var localCache,
1631  isCache = is[ space.cache ];
1632  if ( isCache ) {
1633  localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1634  each( space.props, function( _, prop ) {
1635  if ( isCache[ prop.idx ] != null ) {
1636  same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1637  return same;
1638  }
1639  } );
1640  }
1641  return same;
1642  } );
1643  return same;
1644  },
1645  _space: function() {
1646  var used = [],
1647  inst = this;
1648  each( spaces, function( spaceName, space ) {
1649  if ( inst[ space.cache ] ) {
1650  used.push( spaceName );
1651  }
1652  } );
1653  return used.pop();
1654  },
1655  transition: function( other, distance ) {
1656  var end = color( other ),
1657  spaceName = end._space(),
1658  space = spaces[ spaceName ],
1659  startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1660  start = startColor[ space.cache ] || space.to( startColor._rgba ),
1661  result = start.slice();
1662 
1663  end = end[ space.cache ];
1664  each( space.props, function( key, prop ) {
1665  var index = prop.idx,
1666  startValue = start[ index ],
1667  endValue = end[ index ],
1668  type = propTypes[ prop.type ] || {};
1669 
1670  // If null, don't override start value
1671  if ( endValue === null ) {
1672  return;
1673  }
1674 
1675  // If null - use end
1676  if ( startValue === null ) {
1677  result[ index ] = endValue;
1678  } else {
1679  if ( type.mod ) {
1680  if ( endValue - startValue > type.mod / 2 ) {
1681  startValue += type.mod;
1682  } else if ( startValue - endValue > type.mod / 2 ) {
1683  startValue -= type.mod;
1684  }
1685  }
1686  result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1687  }
1688  } );
1689  return this[ spaceName ]( result );
1690  },
1691  blend: function( opaque ) {
1692 
1693  // If we are already opaque - return ourself
1694  if ( this._rgba[ 3 ] === 1 ) {
1695  return this;
1696  }
1697 
1698  var rgb = this._rgba.slice(),
1699  a = rgb.pop(),
1700  blend = color( opaque )._rgba;
1701 
1702  return color( jQuery.map( rgb, function( v, i ) {
1703  return ( 1 - a ) * blend[ i ] + a * v;
1704  } ) );
1705  },
1706  toRgbaString: function() {
1707  var prefix = "rgba(",
1708  rgba = jQuery.map( this._rgba, function( v, i ) {
1709  return v == null ? ( i > 2 ? 1 : 0 ) : v;
1710  } );
1711 
1712  if ( rgba[ 3 ] === 1 ) {
1713  rgba.pop();
1714  prefix = "rgb(";
1715  }
1716 
1717  return prefix + rgba.join() + ")";
1718  },
1719  toHslaString: function() {
1720  var prefix = "hsla(",
1721  hsla = jQuery.map( this.hsla(), function( v, i ) {
1722  if ( v == null ) {
1723  v = i > 2 ? 1 : 0;
1724  }
1725 
1726  // Catch 1 and 2
1727  if ( i && i < 3 ) {
1728  v = Math.round( v * 100 ) + "%";
1729  }
1730  return v;
1731  } );
1732 
1733  if ( hsla[ 3 ] === 1 ) {
1734  hsla.pop();
1735  prefix = "hsl(";
1736  }
1737  return prefix + hsla.join() + ")";
1738  },
1739  toHexString: function( includeAlpha ) {
1740  var rgba = this._rgba.slice(),
1741  alpha = rgba.pop();
1742 
1743  if ( includeAlpha ) {
1744  rgba.push( ~~( alpha * 255 ) );
1745  }
1746 
1747  return "#" + jQuery.map( rgba, function( v ) {
1748 
1749  // Default to 0 when nulls exist
1750  v = ( v || 0 ).toString( 16 );
1751  return v.length === 1 ? "0" + v : v;
1752  } ).join( "" );
1753  },
1754  toString: function() {
1755  return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
1756  }
1757 } );
1758 color.fn.parse.prototype = color.fn;
1759 
1760 // Hsla conversions adapted from:
1761 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1762 
1763 function hue2rgb( p, q, h ) {
1764  h = ( h + 1 ) % 1;
1765  if ( h * 6 < 1 ) {
1766  return p + ( q - p ) * h * 6;
1767  }
1768  if ( h * 2 < 1 ) {
1769  return q;
1770  }
1771  if ( h * 3 < 2 ) {
1772  return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1773  }
1774  return p;
1775 }
1776 
1777 spaces.hsla.to = function( rgba ) {
1778  if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1779  return [ null, null, null, rgba[ 3 ] ];
1780  }
1781  var r = rgba[ 0 ] / 255,
1782  g = rgba[ 1 ] / 255,
1783  b = rgba[ 2 ] / 255,
1784  a = rgba[ 3 ],
1785  max = Math.max( r, g, b ),
1786  min = Math.min( r, g, b ),
1787  diff = max - min,
1788  add = max + min,
1789  l = add * 0.5,
1790  h, s;
1791 
1792  if ( min === max ) {
1793  h = 0;
1794  } else if ( r === max ) {
1795  h = ( 60 * ( g - b ) / diff ) + 360;
1796  } else if ( g === max ) {
1797  h = ( 60 * ( b - r ) / diff ) + 120;
1798  } else {
1799  h = ( 60 * ( r - g ) / diff ) + 240;
1800  }
1801 
1802  // Chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1803  // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1804  if ( diff === 0 ) {
1805  s = 0;
1806  } else if ( l <= 0.5 ) {
1807  s = diff / add;
1808  } else {
1809  s = diff / ( 2 - add );
1810  }
1811  return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1812 };
1813 
1814 spaces.hsla.from = function( hsla ) {
1815  if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1816  return [ null, null, null, hsla[ 3 ] ];
1817  }
1818  var h = hsla[ 0 ] / 360,
1819  s = hsla[ 1 ],
1820  l = hsla[ 2 ],
1821  a = hsla[ 3 ],
1822  q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1823  p = 2 * l - q;
1824 
1825  return [
1826  Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1827  Math.round( hue2rgb( p, q, h ) * 255 ),
1828  Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1829  a
1830  ];
1831 };
1832 
1833 each( spaces, function( spaceName, space ) {
1834  var props = space.props,
1835  cache = space.cache,
1836  to = space.to,
1837  from = space.from;
1838 
1839  // Makes rgba() and hsla()
1840  color.fn[ spaceName ] = function( value ) {
1841 
1842  // Generate a cache for this space if it doesn't exist
1843  if ( to && !this[ cache ] ) {
1844  this[ cache ] = to( this._rgba );
1845  }
1846  if ( value === undefined ) {
1847  return this[ cache ].slice();
1848  }
1849 
1850  var ret,
1851  type = jQuery.type( value ),
1852  arr = ( type === "array" || type === "object" ) ? value : arguments,
1853  local = this[ cache ].slice();
1854 
1855  each( props, function( key, prop ) {
1856  var val = arr[ type === "object" ? key : prop.idx ];
1857  if ( val == null ) {
1858  val = local[ prop.idx ];
1859  }
1860  local[ prop.idx ] = clamp( val, prop );
1861  } );
1862 
1863  if ( from ) {
1864  ret = color( from( local ) );
1865  ret[ cache ] = local;
1866  return ret;
1867  } else {
1868  return color( local );
1869  }
1870  };
1871 
1872  // Makes red() green() blue() alpha() hue() saturation() lightness()
1873  each( props, function( key, prop ) {
1874 
1875  // Alpha is included in more than one space
1876  if ( color.fn[ key ] ) {
1877  return;
1878  }
1879  color.fn[ key ] = function( value ) {
1880  var vtype = jQuery.type( value ),
1881  fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
1882  local = this[ fn ](),
1883  cur = local[ prop.idx ],
1884  match;
1885 
1886  if ( vtype === "undefined" ) {
1887  return cur;
1888  }
1889 
1890  if ( vtype === "function" ) {
1891  value = value.call( this, cur );
1892  vtype = jQuery.type( value );
1893  }
1894  if ( value == null && prop.empty ) {
1895  return this;
1896  }
1897  if ( vtype === "string" ) {
1898  match = rplusequals.exec( value );
1899  if ( match ) {
1900  value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1901  }
1902  }
1903  local[ prop.idx ] = value;
1904  return this[ fn ]( local );
1905  };
1906  } );
1907 } );
1908 
1909 // Add cssHook and .fx.step function for each named hook.
1910 // accept a space separated string of properties
1911 color.hook = function( hook ) {
1912  var hooks = hook.split( " " );
1913  each( hooks, function( i, hook ) {
1914  jQuery.cssHooks[ hook ] = {
1915  set: function( elem, value ) {
1916  var parsed, curElem,
1917  backgroundColor = "";
1918 
1919  if ( value !== "transparent" && ( jQuery.type( value ) !== "string" ||
1920  ( parsed = stringParse( value ) ) ) ) {
1921  value = color( parsed || value );
1922  if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
1923  curElem = hook === "backgroundColor" ? elem.parentNode : elem;
1924  while (
1925  ( backgroundColor === "" || backgroundColor === "transparent" ) &&
1926  curElem && curElem.style
1927  ) {
1928  try {
1929  backgroundColor = jQuery.css( curElem, "backgroundColor" );
1930  curElem = curElem.parentNode;
1931  } catch ( e ) {
1932  }
1933  }
1934 
1935  value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
1936  backgroundColor :
1937  "_default" );
1938  }
1939 
1940  value = value.toRgbaString();
1941  }
1942  try {
1943  elem.style[ hook ] = value;
1944  } catch ( e ) {
1945 
1946  // Wrapped to prevent IE from throwing errors on "invalid" values like
1947  // 'auto' or 'inherit'
1948  }
1949  }
1950  };
1951  jQuery.fx.step[ hook ] = function( fx ) {
1952  if ( !fx.colorInit ) {
1953  fx.start = color( fx.elem, hook );
1954  fx.end = color( fx.end );
1955  fx.colorInit = true;
1956  }
1957  jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1958  };
1959  } );
1960 
1961 };
1962 
1963 color.hook( stepHooks );
1964 
1965 jQuery.cssHooks.borderColor = {
1966  expand: function( value ) {
1967  var expanded = {};
1968 
1969  each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
1970  expanded[ "border" + part + "Color" ] = value;
1971  } );
1972  return expanded;
1973  }
1974 };
1975 
1976 // Basic color names only.
1977 // Usage of any of the other color names requires adding yourself or including
1978 // jquery.color.svg-names.js.
1979 colors = jQuery.Color.names = {
1980 
1981  // 4.1. Basic color keywords
1982  aqua: "#00ffff",
1983  black: "#000000",
1984  blue: "#0000ff",
1985  fuchsia: "#ff00ff",
1986  gray: "#808080",
1987  green: "#008000",
1988  lime: "#00ff00",
1989  maroon: "#800000",
1990  navy: "#000080",
1991  olive: "#808000",
1992  purple: "#800080",
1993  red: "#ff0000",
1994  silver: "#c0c0c0",
1995  teal: "#008080",
1996  white: "#ffffff",
1997  yellow: "#ffff00",
1998 
1999  // 4.2.3. "transparent" color keyword
2000  transparent: [ null, null, null, 0 ],
2001 
2002  _default: "#ffffff"
2003 };
2004 
2005 } )( jQuery );
2006 
2007 /******************************************************************************/
2008 /****************************** CLASS ANIMATIONS ******************************/
2009 /******************************************************************************/
2010 ( function() {
2011 
2012 var classAnimationActions = [ "add", "remove", "toggle" ],
2013  shorthandStyles = {
2014  border: 1,
2015  borderBottom: 1,
2016  borderColor: 1,
2017  borderLeft: 1,
2018  borderRight: 1,
2019  borderTop: 1,
2020  borderWidth: 1,
2021  margin: 1,
2022  padding: 1
2023  };
2024 
2025 $.each(
2026  [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2027  function( _, prop ) {
2028  $.fx.step[ prop ] = function( fx ) {
2029  if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2030  jQuery.style( fx.elem, prop, fx.end );
2031  fx.setAttr = true;
2032  }
2033  };
2034  }
2035 );
2036 
2037 function getElementStyles( elem ) {
2038  var key, len,
2039  style = elem.ownerDocument.defaultView ?
2040  elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
2041  elem.currentStyle,
2042  styles = {};
2043 
2044  if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
2045  len = style.length;
2046  while ( len-- ) {
2047  key = style[ len ];
2048  if ( typeof style[ key ] === "string" ) {
2049  styles[ $.camelCase( key ) ] = style[ key ];
2050  }
2051  }
2052 
2053  // Support: Opera, IE <9
2054  } else {
2055  for ( key in style ) {
2056  if ( typeof style[ key ] === "string" ) {
2057  styles[ key ] = style[ key ];
2058  }
2059  }
2060  }
2061 
2062  return styles;
2063 }
2064 
2065 function styleDifference( oldStyle, newStyle ) {
2066  var diff = {},
2067  name, value;
2068 
2069  for ( name in newStyle ) {
2070  value = newStyle[ name ];
2071  if ( oldStyle[ name ] !== value ) {
2072  if ( !shorthandStyles[ name ] ) {
2073  if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2074  diff[ name ] = value;
2075  }
2076  }
2077  }
2078  }
2079 
2080  return diff;
2081 }
2082 
2083 // Support: jQuery <1.8
2084 if ( !$.fn.addBack ) {
2085  $.fn.addBack = function( selector ) {
2086  return this.add( selector == null ?
2087  this.prevObject : this.prevObject.filter( selector )
2088  );
2089  };
2090 }
2091 
2092 $.effects.animateClass = function( value, duration, easing, callback ) {
2093  var o = $.speed( duration, easing, callback );
2094 
2095  return this.queue( function() {
2096  var animated = $( this ),
2097  baseClass = animated.attr( "class" ) || "",
2098  applyClassChange,
2099  allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2100 
2101  // Map the animated objects to store the original styles.
2102  allAnimations = allAnimations.map( function() {
2103  var el = $( this );
2104  return {
2105  el: el,
2106  start: getElementStyles( this )
2107  };
2108  } );
2109 
2110  // Apply class change
2111  applyClassChange = function() {
2112  $.each( classAnimationActions, function( i, action ) {
2113  if ( value[ action ] ) {
2114  animated[ action + "Class" ]( value[ action ] );
2115  }
2116  } );
2117  };
2118  applyClassChange();
2119 
2120  // Map all animated objects again - calculate new styles and diff
2121  allAnimations = allAnimations.map( function() {
2122  this.end = getElementStyles( this.el[ 0 ] );
2123  this.diff = styleDifference( this.start, this.end );
2124  return this;
2125  } );
2126 
2127  // Apply original class
2128  animated.attr( "class", baseClass );
2129 
2130  // Map all animated objects again - this time collecting a promise
2131  allAnimations = allAnimations.map( function() {
2132  var styleInfo = this,
2133  dfd = $.Deferred(),
2134  opts = $.extend( {}, o, {
2135  queue: false,
2136  complete: function() {
2137  dfd.resolve( styleInfo );
2138  }
2139  } );
2140 
2141  this.el.animate( this.diff, opts );
2142  return dfd.promise();
2143  } );
2144 
2145  // Once all animations have completed:
2146  $.when.apply( $, allAnimations.get() ).done( function() {
2147 
2148  // Set the final class
2149  applyClassChange();
2150 
2151  // For each animated element,
2152  // clear all css properties that were animated
2153  $.each( arguments, function() {
2154  var el = this.el;
2155  $.each( this.diff, function( key ) {
2156  el.css( key, "" );
2157  } );
2158  } );
2159 
2160  // This is guarnteed to be there if you use jQuery.speed()
2161  // it also handles dequeuing the next anim...
2162  o.complete.call( animated[ 0 ] );
2163  } );
2164  } );
2165 };
2166 
2167 $.fn.extend( {
2168  addClass: ( function( orig ) {
2169  return function( classNames, speed, easing, callback ) {
2170  return speed ?
2171  $.effects.animateClass.call( this,
2172  { add: classNames }, speed, easing, callback ) :
2173  orig.apply( this, arguments );
2174  };
2175  } )( $.fn.addClass ),
2176 
2177  removeClass: ( function( orig ) {
2178  return function( classNames, speed, easing, callback ) {
2179  return arguments.length > 1 ?
2180  $.effects.animateClass.call( this,
2181  { remove: classNames }, speed, easing, callback ) :
2182  orig.apply( this, arguments );
2183  };
2184  } )( $.fn.removeClass ),
2185 
2186  toggleClass: ( function( orig ) {
2187  return function( classNames, force, speed, easing, callback ) {
2188  if ( typeof force === "boolean" || force === undefined ) {
2189  if ( !speed ) {
2190 
2191  // Without speed parameter
2192  return orig.apply( this, arguments );
2193  } else {
2194  return $.effects.animateClass.call( this,
2195  ( force ? { add: classNames } : { remove: classNames } ),
2196  speed, easing, callback );
2197  }
2198  } else {
2199 
2200  // Without force parameter
2201  return $.effects.animateClass.call( this,
2202  { toggle: classNames }, force, speed, easing );
2203  }
2204  };
2205  } )( $.fn.toggleClass ),
2206 
2207  switchClass: function( remove, add, speed, easing, callback ) {
2208  return $.effects.animateClass.call( this, {
2209  add: add,
2210  remove: remove
2211  }, speed, easing, callback );
2212  }
2213 } );
2214 
2215 } )();
2216 
2217 /******************************************************************************/
2218 /*********************************** EFFECTS **********************************/
2219 /******************************************************************************/
2220 
2221 ( function() {
2222 
2223 if ( $.expr && $.expr.filters && $.expr.filters.animated ) {
2224  $.expr.filters.animated = ( function( orig ) {
2225  return function( elem ) {
2226  return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2227  };
2228  } )( $.expr.filters.animated );
2229 }
2230 
2231 if ( $.uiBackCompat !== false ) {
2232  $.extend( $.effects, {
2233 
2234  // Saves a set of properties in a data storage
2235  save: function( element, set ) {
2236  var i = 0, length = set.length;
2237  for ( ; i < length; i++ ) {
2238  if ( set[ i ] !== null ) {
2239  element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2240  }
2241  }
2242  },
2243 
2244  // Restores a set of previously saved properties from a data storage
2245  restore: function( element, set ) {
2246  var val, i = 0, length = set.length;
2247  for ( ; i < length; i++ ) {
2248  if ( set[ i ] !== null ) {
2249  val = element.data( dataSpace + set[ i ] );
2250  element.css( set[ i ], val );
2251  }
2252  }
2253  },
2254 
2255  setMode: function( el, mode ) {
2256  if ( mode === "toggle" ) {
2257  mode = el.is( ":hidden" ) ? "show" : "hide";
2258  }
2259  return mode;
2260  },
2261 
2262  // Wraps the element around a wrapper that copies position properties
2263  createWrapper: function( element ) {
2264 
2265  // If the element is already wrapped, return it
2266  if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2267  return element.parent();
2268  }
2269 
2270  // Wrap the element
2271  var props = {
2272  width: element.outerWidth( true ),
2273  height: element.outerHeight( true ),
2274  "float": element.css( "float" )
2275  },
2276  wrapper = $( "<div></div>" )
2277  .addClass( "ui-effects-wrapper" )
2278  .css( {
2279  fontSize: "100%",
2280  background: "transparent",
2281  border: "none",
2282  margin: 0,
2283  padding: 0
2284  } ),
2285 
2286  // Store the size in case width/height are defined in % - Fixes #5245
2287  size = {
2288  width: element.width(),
2289  height: element.height()
2290  },
2291  active = document.activeElement;
2292 
2293  // Support: Firefox
2294  // Firefox incorrectly exposes anonymous content
2295  // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2296  try {
2297  active.id;
2298  } catch ( e ) {
2299  active = document.body;
2300  }
2301 
2302  element.wrap( wrapper );
2303 
2304  // Fixes #7595 - Elements lose focus when wrapped.
2305  if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2306  $( active ).trigger( "focus" );
2307  }
2308 
2309  // Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2310  // lose the reference to the wrapped element
2311  wrapper = element.parent();
2312 
2313  // Transfer positioning properties to the wrapper
2314  if ( element.css( "position" ) === "static" ) {
2315  wrapper.css( { position: "relative" } );
2316  element.css( { position: "relative" } );
2317  } else {
2318  $.extend( props, {
2319  position: element.css( "position" ),
2320  zIndex: element.css( "z-index" )
2321  } );
2322  $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2323  props[ pos ] = element.css( pos );
2324  if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2325  props[ pos ] = "auto";
2326  }
2327  } );
2328  element.css( {
2329  position: "relative",
2330  top: 0,
2331  left: 0,
2332  right: "auto",
2333  bottom: "auto"
2334  } );
2335  }
2336  element.css( size );
2337 
2338  return wrapper.css( props ).show();
2339  },
2340 
2341  removeWrapper: function( element ) {
2342  var active = document.activeElement;
2343 
2344  if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2345  element.parent().replaceWith( element );
2346 
2347  // Fixes #7595 - Elements lose focus when wrapped.
2348  if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2349  $( active ).trigger( "focus" );
2350  }
2351  }
2352 
2353  return element;
2354  }
2355  } );
2356 }
2357 
2358 $.extend( $.effects, {
2359  version: "1.12.1",
2360 
2361  define: function( name, mode, effect ) {
2362  if ( !effect ) {
2363  effect = mode;
2364  mode = "effect";
2365  }
2366 
2367  $.effects.effect[ name ] = effect;
2368  $.effects.effect[ name ].mode = mode;
2369 
2370  return effect;
2371  },
2372 
2373  scaledDimensions: function( element, percent, direction ) {
2374  if ( percent === 0 ) {
2375  return {
2376  height: 0,
2377  width: 0,
2378  outerHeight: 0,
2379  outerWidth: 0
2380  };
2381  }
2382 
2383  var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2384  y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2385 
2386  return {
2387  height: element.height() * y,
2388  width: element.width() * x,
2389  outerHeight: element.outerHeight() * y,
2390  outerWidth: element.outerWidth() * x
2391  };
2392 
2393  },
2394 
2395  clipToBox: function( animation ) {
2396  return {
2397  width: animation.clip.right - animation.clip.left,
2398  height: animation.clip.bottom - animation.clip.top,
2399  left: animation.clip.left,
2400  top: animation.clip.top
2401  };
2402  },
2403 
2404  // Injects recently queued functions to be first in line (after "inprogress")
2405  unshift: function( element, queueLength, count ) {
2406  var queue = element.queue();
2407 
2408  if ( queueLength > 1 ) {
2409  queue.splice.apply( queue,
2410  [ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2411  }
2412  element.dequeue();
2413  },
2414 
2415  saveStyle: function( element ) {
2416  element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2417  },
2418 
2419  restoreStyle: function( element ) {
2420  element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2421  element.removeData( dataSpaceStyle );
2422  },
2423 
2424  mode: function( element, mode ) {
2425  var hidden = element.is( ":hidden" );
2426 
2427  if ( mode === "toggle" ) {
2428  mode = hidden ? "show" : "hide";
2429  }
2430  if ( hidden ? mode === "hide" : mode === "show" ) {
2431  mode = "none";
2432  }
2433  return mode;
2434  },
2435 
2436  // Translates a [top,left] array into a baseline value
2437  getBaseline: function( origin, original ) {
2438  var y, x;
2439 
2440  switch ( origin[ 0 ] ) {
2441  case "top":
2442  y = 0;
2443  break;
2444  case "middle":
2445  y = 0.5;
2446  break;
2447  case "bottom":
2448  y = 1;
2449  break;
2450  default:
2451  y = origin[ 0 ] / original.height;
2452  }
2453 
2454  switch ( origin[ 1 ] ) {
2455  case "left":
2456  x = 0;
2457  break;
2458  case "center":
2459  x = 0.5;
2460  break;
2461  case "right":
2462  x = 1;
2463  break;
2464  default:
2465  x = origin[ 1 ] / original.width;
2466  }
2467 
2468  return {
2469  x: x,
2470  y: y
2471  };
2472  },
2473 
2474  // Creates a placeholder element so that the original element can be made absolute
2475  createPlaceholder: function( element ) {
2476  var placeholder,
2477  cssPosition = element.css( "position" ),
2478  position = element.position();
2479 
2480  // Lock in margins first to account for form elements, which
2481  // will change margin if you explicitly set height
2482  // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2483  // Support: Safari
2484  element.css( {
2485  marginTop: element.css( "marginTop" ),
2486  marginBottom: element.css( "marginBottom" ),
2487  marginLeft: element.css( "marginLeft" ),
2488  marginRight: element.css( "marginRight" )
2489  } )
2490  .outerWidth( element.outerWidth() )
2491  .outerHeight( element.outerHeight() );
2492 
2493  if ( /^(static|relative)/.test( cssPosition ) ) {
2494  cssPosition = "absolute";
2495 
2496  placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2497 
2498  // Convert inline to inline block to account for inline elements
2499  // that turn to inline block based on content (like img)
2500  display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2501  "inline-block" :
2502  "block",
2503  visibility: "hidden",
2504 
2505  // Margins need to be set to account for margin collapse
2506  marginTop: element.css( "marginTop" ),
2507  marginBottom: element.css( "marginBottom" ),
2508  marginLeft: element.css( "marginLeft" ),
2509  marginRight: element.css( "marginRight" ),
2510  "float": element.css( "float" )
2511  } )
2512  .outerWidth( element.outerWidth() )
2513  .outerHeight( element.outerHeight() )
2514  .addClass( "ui-effects-placeholder" );
2515 
2516  element.data( dataSpace + "placeholder", placeholder );
2517  }
2518 
2519  element.css( {
2520  position: cssPosition,
2521  left: position.left,
2522  top: position.top
2523  } );
2524 
2525  return placeholder;
2526  },
2527 
2528  removePlaceholder: function( element ) {
2529  var dataKey = dataSpace + "placeholder",
2530  placeholder = element.data( dataKey );
2531 
2532  if ( placeholder ) {
2533  placeholder.remove();
2534  element.removeData( dataKey );
2535  }
2536  },
2537 
2538  // Removes a placeholder if it exists and restores
2539  // properties that were modified during placeholder creation
2540  cleanUp: function( element ) {
2541  $.effects.restoreStyle( element );
2542  $.effects.removePlaceholder( element );
2543  },
2544 
2545  setTransition: function( element, list, factor, value ) {
2546  value = value || {};
2547  $.each( list, function( i, x ) {
2548  var unit = element.cssUnit( x );
2549  if ( unit[ 0 ] > 0 ) {
2550  value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2551  }
2552  } );
2553  return value;
2554  }
2555 } );
2556 
2557 // Return an effect options object for the given parameters:
2558 function _normalizeArguments( effect, options, speed, callback ) {
2559 
2560  // Allow passing all options as the first parameter
2561  if ( $.isPlainObject( effect ) ) {
2562  options = effect;
2563  effect = effect.effect;
2564  }
2565 
2566  // Convert to an object
2567  effect = { effect: effect };
2568 
2569  // Catch (effect, null, ...)
2570  if ( options == null ) {
2571  options = {};
2572  }
2573 
2574  // Catch (effect, callback)
2575  if ( $.isFunction( options ) ) {
2576  callback = options;
2577  speed = null;
2578  options = {};
2579  }
2580 
2581  // Catch (effect, speed, ?)
2582  if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2583  callback = speed;
2584  speed = options;
2585  options = {};
2586  }
2587 
2588  // Catch (effect, options, callback)
2589  if ( $.isFunction( speed ) ) {
2590  callback = speed;
2591  speed = null;
2592  }
2593 
2594  // Add options to effect
2595  if ( options ) {
2596  $.extend( effect, options );
2597  }
2598 
2599  speed = speed || options.duration;
2600  effect.duration = $.fx.off ? 0 :
2601  typeof speed === "number" ? speed :
2602  speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2603  $.fx.speeds._default;
2604 
2605  effect.complete = callback || options.complete;
2606 
2607  return effect;
2608 }
2609 
2610 function standardAnimationOption( option ) {
2611 
2612  // Valid standard speeds (nothing, number, named speed)
2613  if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2614  return true;
2615  }
2616 
2617  // Invalid strings - treat as "normal" speed
2618  if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2619  return true;
2620  }
2621 
2622  // Complete callback
2623  if ( $.isFunction( option ) ) {
2624  return true;
2625  }
2626 
2627  // Options hash (but not naming an effect)
2628  if ( typeof option === "object" && !option.effect ) {
2629  return true;
2630  }
2631 
2632  // Didn't match any standard API
2633  return false;
2634 }
2635 
2636 $.fn.extend( {
2637  effect: function( /* effect, options, speed, callback */ ) {
2638  var args = _normalizeArguments.apply( this, arguments ),
2639  effectMethod = $.effects.effect[ args.effect ],
2640  defaultMode = effectMethod.mode,
2641  queue = args.queue,
2642  queueName = queue || "fx",
2643  complete = args.complete,
2644  mode = args.mode,
2645  modes = [],
2646  prefilter = function( next ) {
2647  var el = $( this ),
2648  normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2649 
2650  // Sentinel for duck-punching the :animated psuedo-selector
2651  el.data( dataSpaceAnimated, true );
2652 
2653  // Save effect mode for later use,
2654  // we can't just call $.effects.mode again later,
2655  // as the .show() below destroys the initial state
2656  modes.push( normalizedMode );
2657 
2658  // See $.uiBackCompat inside of run() for removal of defaultMode in 1.13
2659  if ( defaultMode && ( normalizedMode === "show" ||
2660  ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2661  el.show();
2662  }
2663 
2664  if ( !defaultMode || normalizedMode !== "none" ) {
2665  $.effects.saveStyle( el );
2666  }
2667 
2668  if ( $.isFunction( next ) ) {
2669  next();
2670  }
2671  };
2672 
2673  if ( $.fx.off || !effectMethod ) {
2674 
2675  // Delegate to the original method (e.g., .show()) if possible
2676  if ( mode ) {
2677  return this[ mode ]( args.duration, complete );
2678  } else {
2679  return this.each( function() {
2680  if ( complete ) {
2681  complete.call( this );
2682  }
2683  } );
2684  }
2685  }
2686 
2687  function run( next ) {
2688  var elem = $( this );
2689 
2690  function cleanup() {
2691  elem.removeData( dataSpaceAnimated );
2692 
2693  $.effects.cleanUp( elem );
2694 
2695  if ( args.mode === "hide" ) {
2696  elem.hide();
2697  }
2698 
2699  done();
2700  }
2701 
2702  function done() {
2703  if ( $.isFunction( complete ) ) {
2704  complete.call( elem[ 0 ] );
2705  }
2706 
2707  if ( $.isFunction( next ) ) {
2708  next();
2709  }
2710  }
2711 
2712  // Override mode option on a per element basis,
2713  // as toggle can be either show or hide depending on element state
2714  args.mode = modes.shift();
2715 
2716  if ( $.uiBackCompat !== false && !defaultMode ) {
2717  if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2718 
2719  // Call the core method to track "olddisplay" properly
2720  elem[ mode ]();
2721  done();
2722  } else {
2723  effectMethod.call( elem[ 0 ], args, done );
2724  }
2725  } else {
2726  if ( args.mode === "none" ) {
2727 
2728  // Call the core method to track "olddisplay" properly
2729  elem[ mode ]();
2730  done();
2731  } else {
2732  effectMethod.call( elem[ 0 ], args, cleanup );
2733  }
2734  }
2735  }
2736 
2737  // Run prefilter on all elements first to ensure that
2738  // any showing or hiding happens before placeholder creation,
2739  // which ensures that any layout changes are correctly captured.
2740  return queue === false ?
2741  this.each( prefilter ).each( run ) :
2742  this.queue( queueName, prefilter ).queue( queueName, run );
2743  },
2744 
2745  show: ( function( orig ) {
2746  return function( option ) {
2747  if ( standardAnimationOption( option ) ) {
2748  return orig.apply( this, arguments );
2749  } else {
2750  var args = _normalizeArguments.apply( this, arguments );
2751  args.mode = "show";
2752  return this.effect.call( this, args );
2753  }
2754  };
2755  } )( $.fn.show ),
2756 
2757  hide: ( function( orig ) {
2758  return function( option ) {
2759  if ( standardAnimationOption( option ) ) {
2760  return orig.apply( this, arguments );
2761  } else {
2762  var args = _normalizeArguments.apply( this, arguments );
2763  args.mode = "hide";
2764  return this.effect.call( this, args );
2765  }
2766  };
2767  } )( $.fn.hide ),
2768 
2769  toggle: ( function( orig ) {
2770  return function( option ) {
2771  if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2772  return orig.apply( this, arguments );
2773  } else {
2774  var args = _normalizeArguments.apply( this, arguments );
2775  args.mode = "toggle";
2776  return this.effect.call( this, args );
2777  }
2778  };
2779  } )( $.fn.toggle ),
2780 
2781  cssUnit: function( key ) {
2782  var style = this.css( key ),
2783  val = [];
2784 
2785  $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2786  if ( style.indexOf( unit ) > 0 ) {
2787  val = [ parseFloat( style ), unit ];
2788  }
2789  } );
2790  return val;
2791  },
2792 
2793  cssClip: function( clipObj ) {
2794  if ( clipObj ) {
2795  return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2796  clipObj.bottom + "px " + clipObj.left + "px)" );
2797  }
2798  return parseClip( this.css( "clip" ), this );
2799  },
2800 
2801  transfer: function( options, done ) {
2802  var element = $( this ),
2803  target = $( options.to ),
2804  targetFixed = target.css( "position" ) === "fixed",
2805  body = $( "body" ),
2806  fixTop = targetFixed ? body.scrollTop() : 0,
2807  fixLeft = targetFixed ? body.scrollLeft() : 0,
2808  endPosition = target.offset(),
2809  animation = {
2810  top: endPosition.top - fixTop,
2811  left: endPosition.left - fixLeft,
2812  height: target.innerHeight(),
2813  width: target.innerWidth()
2814  },
2815  startPosition = element.offset(),
2816  transfer = $( "<div class='ui-effects-transfer'></div>" )
2817  .appendTo( "body" )
2818  .addClass( options.className )
2819  .css( {
2820  top: startPosition.top - fixTop,
2821  left: startPosition.left - fixLeft,
2822  height: element.innerHeight(),
2823  width: element.innerWidth(),
2824  position: targetFixed ? "fixed" : "absolute"
2825  } )
2826  .animate( animation, options.duration, options.easing, function() {
2827  transfer.remove();
2828  if ( $.isFunction( done ) ) {
2829  done();
2830  }
2831  } );
2832  }
2833 } );
2834 
2835 function parseClip( str, element ) {
2836  var outerWidth = element.outerWidth(),
2837  outerHeight = element.outerHeight(),
2838  clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
2839  values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2840 
2841  return {
2842  top: parseFloat( values[ 1 ] ) || 0,
2843  right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2844  bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2845  left: parseFloat( values[ 4 ] ) || 0
2846  };
2847 }
2848 
2849 $.fx.step.clip = function( fx ) {
2850  if ( !fx.clipInit ) {
2851  fx.start = $( fx.elem ).cssClip();
2852  if ( typeof fx.end === "string" ) {
2853  fx.end = parseClip( fx.end, fx.elem );
2854  }
2855  fx.clipInit = true;
2856  }
2857 
2858  $( fx.elem ).cssClip( {
2859  top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2860  right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2861  bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2862  left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2863  } );
2864 };
2865 
2866 } )();
2867 
2868 /******************************************************************************/
2869 /*********************************** EASING ***********************************/
2870 /******************************************************************************/
2871 
2872 ( function() {
2873 
2874 // Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
2875 
2876 var baseEasings = {};
2877 
2878 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2879  baseEasings[ name ] = function( p ) {
2880  return Math.pow( p, i + 2 );
2881  };
2882 } );
2883 
2884 $.extend( baseEasings, {
2885  Sine: function( p ) {
2886  return 1 - Math.cos( p * Math.PI / 2 );
2887  },
2888  Circ: function( p ) {
2889  return 1 - Math.sqrt( 1 - p * p );
2890  },
2891  Elastic: function( p ) {
2892  return p === 0 || p === 1 ? p :
2893  -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2894  },
2895  Back: function( p ) {
2896  return p * p * ( 3 * p - 2 );
2897  },
2898  Bounce: function( p ) {
2899  var pow2,
2900  bounce = 4;
2901 
2902  while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2903  return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2904  }
2905 } );
2906 
2907 $.each( baseEasings, function( name, easeIn ) {
2908  $.easing[ "easeIn" + name ] = easeIn;
2909  $.easing[ "easeOut" + name ] = function( p ) {
2910  return 1 - easeIn( 1 - p );
2911  };
2912  $.easing[ "easeInOut" + name ] = function( p ) {
2913  return p < 0.5 ?
2914  easeIn( p * 2 ) / 2 :
2915  1 - easeIn( p * -2 + 2 ) / 2;
2916  };
2917 } );
2918 
2919 } )();
2920 
2921 var effect = $.effects;
2922 
2923 
2933 //>>label: Blind Effect
2934 //>>group: Effects
2935 //>>description: Blinds the element.
2936 //>>docs: http://api.jqueryui.com/blind-effect/
2937 //>>demos: http://jqueryui.com/effect/
2938 
2939 
2940 
2941 var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
2942  var map = {
2943  up: [ "bottom", "top" ],
2944  vertical: [ "bottom", "top" ],
2945  down: [ "top", "bottom" ],
2946  left: [ "right", "left" ],
2947  horizontal: [ "right", "left" ],
2948  right: [ "left", "right" ]
2949  },
2950  element = $( this ),
2951  direction = options.direction || "up",
2952  start = element.cssClip(),
2953  animate = { clip: $.extend( {}, start ) },
2954  placeholder = $.effects.createPlaceholder( element );
2955 
2956  animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
2957 
2958  if ( options.mode === "show" ) {
2959  element.cssClip( animate.clip );
2960  if ( placeholder ) {
2961  placeholder.css( $.effects.clipToBox( animate ) );
2962  }
2963 
2964  animate.clip = start;
2965  }
2966 
2967  if ( placeholder ) {
2968  placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
2969  }
2970 
2971  element.animate( animate, {
2972  queue: false,
2973  duration: options.duration,
2974  easing: options.easing,
2975  complete: done
2976  } );
2977 } );
2978 
2979 
2989 //>>label: Bounce Effect
2990 //>>group: Effects
2991 //>>description: Bounces an element horizontally or vertically n times.
2992 //>>docs: http://api.jqueryui.com/bounce-effect/
2993 //>>demos: http://jqueryui.com/effect/
2994 
2995 
2996 
2997 var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
2998  var upAnim, downAnim, refValue,
2999  element = $( this ),
3000 
3001  // Defaults:
3002  mode = options.mode,
3003  hide = mode === "hide",
3004  show = mode === "show",
3005  direction = options.direction || "up",
3006  distance = options.distance,
3007  times = options.times || 5,
3008 
3009  // Number of internal animations
3010  anims = times * 2 + ( show || hide ? 1 : 0 ),
3011  speed = options.duration / anims,
3012  easing = options.easing,
3013 
3014  // Utility:
3015  ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3016  motion = ( direction === "up" || direction === "left" ),
3017  i = 0,
3018 
3019  queuelen = element.queue().length;
3020 
3021  $.effects.createPlaceholder( element );
3022 
3023  refValue = element.css( ref );
3024 
3025  // Default distance for the BIGGEST bounce is the outer Distance / 3
3026  if ( !distance ) {
3027  distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3028  }
3029 
3030  if ( show ) {
3031  downAnim = { opacity: 1 };
3032  downAnim[ ref ] = refValue;
3033 
3034  // If we are showing, force opacity 0 and set the initial position
3035  // then do the "first" animation
3036  element
3037  .css( "opacity", 0 )
3038  .css( ref, motion ? -distance * 2 : distance * 2 )
3039  .animate( downAnim, speed, easing );
3040  }
3041 
3042  // Start at the smallest distance if we are hiding
3043  if ( hide ) {
3044  distance = distance / Math.pow( 2, times - 1 );
3045  }
3046 
3047  downAnim = {};
3048  downAnim[ ref ] = refValue;
3049 
3050  // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3051  for ( ; i < times; i++ ) {
3052  upAnim = {};
3053  upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3054 
3055  element
3056  .animate( upAnim, speed, easing )
3057  .animate( downAnim, speed, easing );
3058 
3059  distance = hide ? distance * 2 : distance / 2;
3060  }
3061 
3062  // Last Bounce when Hiding
3063  if ( hide ) {
3064  upAnim = { opacity: 0 };
3065  upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3066 
3067  element.animate( upAnim, speed, easing );
3068  }
3069 
3070  element.queue( done );
3071 
3072  $.effects.unshift( element, queuelen, anims + 1 );
3073 } );
3074 
3075 
3085 //>>label: Clip Effect
3086 //>>group: Effects
3087 //>>description: Clips the element on and off like an old TV.
3088 //>>docs: http://api.jqueryui.com/clip-effect/
3089 //>>demos: http://jqueryui.com/effect/
3090 
3091 
3092 
3093 var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3094  var start,
3095  animate = {},
3096  element = $( this ),
3097  direction = options.direction || "vertical",
3098  both = direction === "both",
3099  horizontal = both || direction === "horizontal",
3100  vertical = both || direction === "vertical";
3101 
3102  start = element.cssClip();
3103  animate.clip = {
3104  top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3105  right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3106  bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3107  left: horizontal ? ( start.right - start.left ) / 2 : start.left
3108  };
3109 
3110  $.effects.createPlaceholder( element );
3111 
3112  if ( options.mode === "show" ) {
3113  element.cssClip( animate.clip );
3114  animate.clip = start;
3115  }
3116 
3117  element.animate( animate, {
3118  queue: false,
3119  duration: options.duration,
3120  easing: options.easing,
3121  complete: done
3122  } );
3123 
3124 } );
3125 
3126 
3136 //>>label: Drop Effect
3137 //>>group: Effects
3138 //>>description: Moves an element in one direction and hides it at the same time.
3139 //>>docs: http://api.jqueryui.com/drop-effect/
3140 //>>demos: http://jqueryui.com/effect/
3141 
3142 
3143 
3144 var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3145 
3146  var distance,
3147  element = $( this ),
3148  mode = options.mode,
3149  show = mode === "show",
3150  direction = options.direction || "left",
3151  ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3152  motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3153  oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3154  animation = {
3155  opacity: 0
3156  };
3157 
3158  $.effects.createPlaceholder( element );
3159 
3160  distance = options.distance ||
3161  element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3162 
3163  animation[ ref ] = motion + distance;
3164 
3165  if ( show ) {
3166  element.css( animation );
3167 
3168  animation[ ref ] = oppositeMotion + distance;
3169  animation.opacity = 1;
3170  }
3171 
3172  // Animate
3173  element.animate( animation, {
3174  queue: false,
3175  duration: options.duration,
3176  easing: options.easing,
3177  complete: done
3178  } );
3179 } );
3180 
3181 
3191 //>>label: Explode Effect
3192 //>>group: Effects
3193 // jscs:disable maximumLineLength
3194 //>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3195 // jscs:enable maximumLineLength
3196 //>>docs: http://api.jqueryui.com/explode-effect/
3197 //>>demos: http://jqueryui.com/effect/
3198 
3199 
3200 
3201 var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3202 
3203  var i, j, left, top, mx, my,
3204  rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3205  cells = rows,
3206  element = $( this ),
3207  mode = options.mode,
3208  show = mode === "show",
3209 
3210  // Show and then visibility:hidden the element before calculating offset
3211  offset = element.show().css( "visibility", "hidden" ).offset(),
3212 
3213  // Width and height of a piece
3214  width = Math.ceil( element.outerWidth() / cells ),
3215  height = Math.ceil( element.outerHeight() / rows ),
3216  pieces = [];
3217 
3218  // Children animate complete:
3219  function childComplete() {
3220  pieces.push( this );
3221  if ( pieces.length === rows * cells ) {
3222  animComplete();
3223  }
3224  }
3225 
3226  // Clone the element for each row and cell.
3227  for ( i = 0; i < rows; i++ ) { // ===>
3228  top = offset.top + i * height;
3229  my = i - ( rows - 1 ) / 2;
3230 
3231  for ( j = 0; j < cells; j++ ) { // |||
3232  left = offset.left + j * width;
3233  mx = j - ( cells - 1 ) / 2;
3234 
3235  // Create a clone of the now hidden main element that will be absolute positioned
3236  // within a wrapper div off the -left and -top equal to size of our pieces
3237  element
3238  .clone()
3239  .appendTo( "body" )
3240  .wrap( "<div></div>" )
3241  .css( {
3242  position: "absolute",
3243  visibility: "visible",
3244  left: -j * width,
3245  top: -i * height
3246  } )
3247 
3248  // Select the wrapper - make it overflow: hidden and absolute positioned based on
3249  // where the original was located +left and +top equal to the size of pieces
3250  .parent()
3251  .addClass( "ui-effects-explode" )
3252  .css( {
3253  position: "absolute",
3254  overflow: "hidden",
3255  width: width,
3256  height: height,
3257  left: left + ( show ? mx * width : 0 ),
3258  top: top + ( show ? my * height : 0 ),
3259  opacity: show ? 0 : 1
3260  } )
3261  .animate( {
3262  left: left + ( show ? 0 : mx * width ),
3263  top: top + ( show ? 0 : my * height ),
3264  opacity: show ? 1 : 0
3265  }, options.duration || 500, options.easing, childComplete );
3266  }
3267  }
3268 
3269  function animComplete() {
3270  element.css( {
3271  visibility: "visible"
3272  } );
3273  $( pieces ).remove();
3274  done();
3275  }
3276 } );
3277 
3278 
3288 //>>label: Fade Effect
3289 //>>group: Effects
3290 //>>description: Fades the element.
3291 //>>docs: http://api.jqueryui.com/fade-effect/
3292 //>>demos: http://jqueryui.com/effect/
3293 
3294 
3295 
3296 var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3297  var show = options.mode === "show";
3298 
3299  $( this )
3300  .css( "opacity", show ? 0 : 1 )
3301  .animate( {
3302  opacity: show ? 1 : 0
3303  }, {
3304  queue: false,
3305  duration: options.duration,
3306  easing: options.easing,
3307  complete: done
3308  } );
3309 } );
3310 
3311 
3321 //>>label: Fold Effect
3322 //>>group: Effects
3323 //>>description: Folds an element first horizontally and then vertically.
3324 //>>docs: http://api.jqueryui.com/fold-effect/
3325 //>>demos: http://jqueryui.com/effect/
3326 
3327 
3328 
3329 var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3330 
3331  // Create element
3332  var element = $( this ),
3333  mode = options.mode,
3334  show = mode === "show",
3335  hide = mode === "hide",
3336  size = options.size || 15,
3337  percent = /([0-9]+)%/.exec( size ),
3338  horizFirst = !!options.horizFirst,
3339  ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3340  duration = options.duration / 2,
3341 
3342  placeholder = $.effects.createPlaceholder( element ),
3343 
3344  start = element.cssClip(),
3345  animation1 = { clip: $.extend( {}, start ) },
3346  animation2 = { clip: $.extend( {}, start ) },
3347 
3348  distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3349 
3350  queuelen = element.queue().length;
3351 
3352  if ( percent ) {
3353  size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3354  }
3355  animation1.clip[ ref[ 0 ] ] = size;
3356  animation2.clip[ ref[ 0 ] ] = size;
3357  animation2.clip[ ref[ 1 ] ] = 0;
3358 
3359  if ( show ) {
3360  element.cssClip( animation2.clip );
3361  if ( placeholder ) {
3362  placeholder.css( $.effects.clipToBox( animation2 ) );
3363  }
3364 
3365  animation2.clip = start;
3366  }
3367 
3368  // Animate
3369  element
3370  .queue( function( next ) {
3371  if ( placeholder ) {
3372  placeholder
3373  .animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3374  .animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3375  }
3376 
3377  next();
3378  } )
3379  .animate( animation1, duration, options.easing )
3380  .animate( animation2, duration, options.easing )
3381  .queue( done );
3382 
3383  $.effects.unshift( element, queuelen, 4 );
3384 } );
3385 
3386 
3396 //>>label: Highlight Effect
3397 //>>group: Effects
3398 //>>description: Highlights the background of an element in a defined color for a custom duration.
3399 //>>docs: http://api.jqueryui.com/highlight-effect/
3400 //>>demos: http://jqueryui.com/effect/
3401 
3402 
3403 
3404 var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3405  var element = $( this ),
3406  animation = {
3407  backgroundColor: element.css( "backgroundColor" )
3408  };
3409 
3410  if ( options.mode === "hide" ) {
3411  animation.opacity = 0;
3412  }
3413 
3414  $.effects.saveStyle( element );
3415 
3416  element
3417  .css( {
3418  backgroundImage: "none",
3419  backgroundColor: options.color || "#ffff99"
3420  } )
3421  .animate( animation, {
3422  queue: false,
3423  duration: options.duration,
3424  easing: options.easing,
3425  complete: done
3426  } );
3427 } );
3428 
3429 
3439 //>>label: Size Effect
3440 //>>group: Effects
3441 //>>description: Resize an element to a specified width and height.
3442 //>>docs: http://api.jqueryui.com/size-effect/
3443 //>>demos: http://jqueryui.com/effect/
3444 
3445 
3446 
3447 var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3448 
3449  // Create element
3450  var baseline, factor, temp,
3451  element = $( this ),
3452 
3453  // Copy for children
3454  cProps = [ "fontSize" ],
3455  vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3456  hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3457 
3458  // Set options
3459  mode = options.mode,
3460  restore = mode !== "effect",
3461  scale = options.scale || "both",
3462  origin = options.origin || [ "middle", "center" ],
3463  position = element.css( "position" ),
3464  pos = element.position(),
3465  original = $.effects.scaledDimensions( element ),
3466  from = options.from || original,
3467  to = options.to || $.effects.scaledDimensions( element, 0 );
3468 
3469  $.effects.createPlaceholder( element );
3470 
3471  if ( mode === "show" ) {
3472  temp = from;
3473  from = to;
3474  to = temp;
3475  }
3476 
3477  // Set scaling factor
3478  factor = {
3479  from: {
3480  y: from.height / original.height,
3481  x: from.width / original.width
3482  },
3483  to: {
3484  y: to.height / original.height,
3485  x: to.width / original.width
3486  }
3487  };
3488 
3489  // Scale the css box
3490  if ( scale === "box" || scale === "both" ) {
3491 
3492  // Vertical props scaling
3493  if ( factor.from.y !== factor.to.y ) {
3494  from = $.effects.setTransition( element, vProps, factor.from.y, from );
3495  to = $.effects.setTransition( element, vProps, factor.to.y, to );
3496  }
3497 
3498  // Horizontal props scaling
3499  if ( factor.from.x !== factor.to.x ) {
3500  from = $.effects.setTransition( element, hProps, factor.from.x, from );
3501  to = $.effects.setTransition( element, hProps, factor.to.x, to );
3502  }
3503  }
3504 
3505  // Scale the content
3506  if ( scale === "content" || scale === "both" ) {
3507 
3508  // Vertical props scaling
3509  if ( factor.from.y !== factor.to.y ) {
3510  from = $.effects.setTransition( element, cProps, factor.from.y, from );
3511  to = $.effects.setTransition( element, cProps, factor.to.y, to );
3512  }
3513  }
3514 
3515  // Adjust the position properties based on the provided origin points
3516  if ( origin ) {
3517  baseline = $.effects.getBaseline( origin, original );
3518  from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3519  from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3520  to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3521  to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3522  }
3523  element.css( from );
3524 
3525  // Animate the children if desired
3526  if ( scale === "content" || scale === "both" ) {
3527 
3528  vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3529  hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3530 
3531  // Only animate children with width attributes specified
3532  // TODO: is this right? should we include anything with css width specified as well
3533  element.find( "*[width]" ).each( function() {
3534  var child = $( this ),
3535  childOriginal = $.effects.scaledDimensions( child ),
3536  childFrom = {
3537  height: childOriginal.height * factor.from.y,
3538  width: childOriginal.width * factor.from.x,
3539  outerHeight: childOriginal.outerHeight * factor.from.y,
3540  outerWidth: childOriginal.outerWidth * factor.from.x
3541  },
3542  childTo = {
3543  height: childOriginal.height * factor.to.y,
3544  width: childOriginal.width * factor.to.x,
3545  outerHeight: childOriginal.height * factor.to.y,
3546  outerWidth: childOriginal.width * factor.to.x
3547  };
3548 
3549  // Vertical props scaling
3550  if ( factor.from.y !== factor.to.y ) {
3551  childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3552  childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3553  }
3554 
3555  // Horizontal props scaling
3556  if ( factor.from.x !== factor.to.x ) {
3557  childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3558  childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3559  }
3560 
3561  if ( restore ) {
3562  $.effects.saveStyle( child );
3563  }
3564 
3565  // Animate children
3566  child.css( childFrom );
3567  child.animate( childTo, options.duration, options.easing, function() {
3568 
3569  // Restore children
3570  if ( restore ) {
3571  $.effects.restoreStyle( child );
3572  }
3573  } );
3574  } );
3575  }
3576 
3577  // Animate
3578  element.animate( to, {
3579  queue: false,
3580  duration: options.duration,
3581  easing: options.easing,
3582  complete: function() {
3583 
3584  var offset = element.offset();
3585 
3586  if ( to.opacity === 0 ) {
3587  element.css( "opacity", from.opacity );
3588  }
3589 
3590  if ( !restore ) {
3591  element
3592  .css( "position", position === "static" ? "relative" : position )
3593  .offset( offset );
3594 
3595  // Need to save style here so that automatic style restoration
3596  // doesn't restore to the original styles from before the animation.
3597  $.effects.saveStyle( element );
3598  }
3599 
3600  done();
3601  }
3602  } );
3603 
3604 } );
3605 
3606 
3616 //>>label: Scale Effect
3617 //>>group: Effects
3618 //>>description: Grows or shrinks an element and its content.
3619 //>>docs: http://api.jqueryui.com/scale-effect/
3620 //>>demos: http://jqueryui.com/effect/
3621 
3622 
3623 
3624 var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3625 
3626  // Create element
3627  var el = $( this ),
3628  mode = options.mode,
3629  percent = parseInt( options.percent, 10 ) ||
3630  ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3631 
3632  newOptions = $.extend( true, {
3633  from: $.effects.scaledDimensions( el ),
3634  to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3635  origin: options.origin || [ "middle", "center" ]
3636  }, options );
3637 
3638  // Fade option to support puff
3639  if ( options.fade ) {
3640  newOptions.from.opacity = 1;
3641  newOptions.to.opacity = 0;
3642  }
3643 
3644  $.effects.effect.size.call( this, newOptions, done );
3645 } );
3646 
3647 
3657 //>>label: Puff Effect
3658 //>>group: Effects
3659 //>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3660 //>>docs: http://api.jqueryui.com/puff-effect/
3661 //>>demos: http://jqueryui.com/effect/
3662 
3663 
3664 
3665 var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3666  var newOptions = $.extend( true, {}, options, {
3667  fade: true,
3668  percent: parseInt( options.percent, 10 ) || 150
3669  } );
3670 
3671  $.effects.effect.scale.call( this, newOptions, done );
3672 } );
3673 
3674 
3684 //>>label: Pulsate Effect
3685 //>>group: Effects
3686 //>>description: Pulsates an element n times by changing the opacity to zero and back.
3687 //>>docs: http://api.jqueryui.com/pulsate-effect/
3688 //>>demos: http://jqueryui.com/effect/
3689 
3690 
3691 
3692 var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3693  var element = $( this ),
3694  mode = options.mode,
3695  show = mode === "show",
3696  hide = mode === "hide",
3697  showhide = show || hide,
3698 
3699  // Showing or hiding leaves off the "last" animation
3700  anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3701  duration = options.duration / anims,
3702  animateTo = 0,
3703  i = 1,
3704  queuelen = element.queue().length;
3705 
3706  if ( show || !element.is( ":visible" ) ) {
3707  element.css( "opacity", 0 ).show();
3708  animateTo = 1;
3709  }
3710 
3711  // Anims - 1 opacity "toggles"
3712  for ( ; i < anims; i++ ) {
3713  element.animate( { opacity: animateTo }, duration, options.easing );
3714  animateTo = 1 - animateTo;
3715  }
3716 
3717  element.animate( { opacity: animateTo }, duration, options.easing );
3718 
3719  element.queue( done );
3720 
3721  $.effects.unshift( element, queuelen, anims + 1 );
3722 } );
3723 
3724 
3734 //>>label: Shake Effect
3735 //>>group: Effects
3736 //>>description: Shakes an element horizontally or vertically n times.
3737 //>>docs: http://api.jqueryui.com/shake-effect/
3738 //>>demos: http://jqueryui.com/effect/
3739 
3740 
3741 
3742 var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3743 
3744  var i = 1,
3745  element = $( this ),
3746  direction = options.direction || "left",
3747  distance = options.distance || 20,
3748  times = options.times || 3,
3749  anims = times * 2 + 1,
3750  speed = Math.round( options.duration / anims ),
3751  ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3752  positiveMotion = ( direction === "up" || direction === "left" ),
3753  animation = {},
3754  animation1 = {},
3755  animation2 = {},
3756 
3757  queuelen = element.queue().length;
3758 
3759  $.effects.createPlaceholder( element );
3760 
3761  // Animation
3762  animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3763  animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3764  animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3765 
3766  // Animate
3767  element.animate( animation, speed, options.easing );
3768 
3769  // Shakes
3770  for ( ; i < times; i++ ) {
3771  element
3772  .animate( animation1, speed, options.easing )
3773  .animate( animation2, speed, options.easing );
3774  }
3775 
3776  element
3777  .animate( animation1, speed, options.easing )
3778  .animate( animation, speed / 2, options.easing )
3779  .queue( done );
3780 
3781  $.effects.unshift( element, queuelen, anims + 1 );
3782 } );
3783 
3784 
3794 //>>label: Slide Effect
3795 //>>group: Effects
3796 //>>description: Slides an element in and out of the viewport.
3797 //>>docs: http://api.jqueryui.com/slide-effect/
3798 //>>demos: http://jqueryui.com/effect/
3799 
3800 
3801 
3802 var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3803  var startClip, startRef,
3804  element = $( this ),
3805  map = {
3806  up: [ "bottom", "top" ],
3807  down: [ "top", "bottom" ],
3808  left: [ "right", "left" ],
3809  right: [ "left", "right" ]
3810  },
3811  mode = options.mode,
3812  direction = options.direction || "left",
3813  ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3814  positiveMotion = ( direction === "up" || direction === "left" ),
3815  distance = options.distance ||
3816  element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3817  animation = {};
3818 
3819  $.effects.createPlaceholder( element );
3820 
3821  startClip = element.cssClip();
3822  startRef = element.position()[ ref ];
3823 
3824  // Define hide animation
3825  animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3826  animation.clip = element.cssClip();
3827  animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3828 
3829  // Reverse the animation if we're showing
3830  if ( mode === "show" ) {
3831  element.cssClip( animation.clip );
3832  element.css( ref, animation[ ref ] );
3833  animation.clip = startClip;
3834  animation[ ref ] = startRef;
3835  }
3836 
3837  // Actually animate
3838  element.animate( animation, {
3839  queue: false,
3840  duration: options.duration,
3841  easing: options.easing,
3842  complete: done
3843  } );
3844 } );
3845 
3846 
3856 //>>label: Transfer Effect
3857 //>>group: Effects
3858 //>>description: Displays a transfer effect from one element to another.
3859 //>>docs: http://api.jqueryui.com/transfer-effect/
3860 //>>demos: http://jqueryui.com/effect/
3861 
3862 
3863 
3864 var effect;
3865 if ( $.uiBackCompat !== false ) {
3866  effect = $.effects.define( "transfer", function( options, done ) {
3867  $( this ).transfer( options, done );
3868  } );
3869 }
3870 var effectsEffectTransfer = effect;
3871 
3872 
3882 //>>label: :focusable Selector
3883 //>>group: Core
3884 //>>description: Selects elements which can be focused.
3885 //>>docs: http://api.jqueryui.com/focusable-selector/
3886 
3887 
3888 
3889 // Selectors
3890 $.ui.focusable = function( element, hasTabindex ) {
3891  var map, mapName, img, focusableIfVisible, fieldset,
3892  nodeName = element.nodeName.toLowerCase();
3893 
3894  if ( "area" === nodeName ) {
3895  map = element.parentNode;
3896  mapName = map.name;
3897  if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3898  return false;
3899  }
3900  img = $( "img[usemap='#" + mapName + "']" );
3901  return img.length > 0 && img.is( ":visible" );
3902  }
3903 
3904  if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3905  focusableIfVisible = !element.disabled;
3906 
3907  if ( focusableIfVisible ) {
3908 
3909  // Form controls within a disabled fieldset are disabled.
3910  // However, controls within the fieldset's legend do not get disabled.
3911  // Since controls generally aren't placed inside legends, we skip
3912  // this portion of the check.
3913  fieldset = $( element ).closest( "fieldset" )[ 0 ];
3914  if ( fieldset ) {
3915  focusableIfVisible = !fieldset.disabled;
3916  }
3917  }
3918  } else if ( "a" === nodeName ) {
3919  focusableIfVisible = element.href || hasTabindex;
3920  } else {
3921  focusableIfVisible = hasTabindex;
3922  }
3923 
3924  return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
3925 };
3926 
3927 // Support: IE 8 only
3928 // IE 8 doesn't resolve inherit to visible/hidden for computed values
3929 function visible( element ) {
3930  var visibility = element.css( "visibility" );
3931  while ( visibility === "inherit" ) {
3932  element = element.parent();
3933  visibility = element.css( "visibility" );
3934  }
3935  return visibility !== "hidden";
3936 }
3937 
3938 $.extend( $.expr[ ":" ], {
3939  focusable: function( element ) {
3940  return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
3941  }
3942 } );
3943 
3944 var focusable = $.ui.focusable;
3945 
3946 
3947 
3948 
3949 // Support: IE8 Only
3950 // IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
3951 // with a string, so we need to find the proper form.
3952 var form = $.fn.form = function() {
3953  return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
3954 };
3955 
3956 
3966 //>>label: Form Reset Mixin
3967 //>>group: Core
3968 //>>description: Refresh input widgets when their form is reset
3969 //>>docs: http://api.jqueryui.com/form-reset-mixin/
3970 
3971 
3972 
3973 var formResetMixin = $.ui.formResetMixin = {
3974  _formResetHandler: function() {
3975  var form = $( this );
3976 
3977  // Wait for the form reset to actually happen before refreshing
3978  setTimeout( function() {
3979  var instances = form.data( "ui-form-reset-instances" );
3980  $.each( instances, function() {
3981  this.refresh();
3982  } );
3983  } );
3984  },
3985 
3986  _bindFormResetHandler: function() {
3987  this.form = this.element.form();
3988  if ( !this.form.length ) {
3989  return;
3990  }
3991 
3992  var instances = this.form.data( "ui-form-reset-instances" ) || [];
3993  if ( !instances.length ) {
3994 
3995  // We don't use _on() here because we use a single event handler per form
3996  this.form.on( "reset.ui-form-reset", this._formResetHandler );
3997  }
3998  instances.push( this );
3999  this.form.data( "ui-form-reset-instances", instances );
4000  },
4001 
4002  _unbindFormResetHandler: function() {
4003  if ( !this.form.length ) {
4004  return;
4005  }
4006 
4007  var instances = this.form.data( "ui-form-reset-instances" );
4008  instances.splice( $.inArray( this, instances ), 1 );
4009  if ( instances.length ) {
4010  this.form.data( "ui-form-reset-instances", instances );
4011  } else {
4012  this.form
4013  .removeData( "ui-form-reset-instances" )
4014  .off( "reset.ui-form-reset" );
4015  }
4016  }
4017 };
4018 
4019 
4030 //>>label: jQuery 1.7 Support
4031 //>>group: Core
4032 //>>description: Support version 1.7.x of jQuery core
4033 
4034 
4035 
4036 // Support: jQuery 1.7 only
4037 // Not a great way to check versions, but since we only support 1.7+ and only
4038 // need to detect <1.8, this is a simple check that should suffice. Checking
4039 // for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0
4040 // and we'll never reach 1.70.0 (if we do, we certainly won't be supporting
4041 // 1.7 anymore). See #11197 for why we're not using feature detection.
4042 if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
4043 
4044  // Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()
4045  // Unlike jQuery Core 1.8+, these only support numeric values to set the
4046  // dimensions in pixels
4047  $.each( [ "Width", "Height" ], function( i, name ) {
4048  var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
4049  type = name.toLowerCase(),
4050  orig = {
4051  innerWidth: $.fn.innerWidth,
4052  innerHeight: $.fn.innerHeight,
4053  outerWidth: $.fn.outerWidth,
4054  outerHeight: $.fn.outerHeight
4055  };
4056 
4057  function reduce( elem, size, border, margin ) {
4058  $.each( side, function() {
4059  size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
4060  if ( border ) {
4061  size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
4062  }
4063  if ( margin ) {
4064  size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
4065  }
4066  } );
4067  return size;
4068  }
4069 
4070  $.fn[ "inner" + name ] = function( size ) {
4071  if ( size === undefined ) {
4072  return orig[ "inner" + name ].call( this );
4073  }
4074 
4075  return this.each( function() {
4076  $( this ).css( type, reduce( this, size ) + "px" );
4077  } );
4078  };
4079 
4080  $.fn[ "outer" + name ] = function( size, margin ) {
4081  if ( typeof size !== "number" ) {
4082  return orig[ "outer" + name ].call( this, size );
4083  }
4084 
4085  return this.each( function() {
4086  $( this ).css( type, reduce( this, size, true, margin ) + "px" );
4087  } );
4088  };
4089  } );
4090 
4091  $.fn.addBack = function( selector ) {
4092  return this.add( selector == null ?
4093  this.prevObject : this.prevObject.filter( selector )
4094  );
4095  };
4096 }
4097 
4098 ;
4108 //>>label: Keycode
4109 //>>group: Core
4110 //>>description: Provide keycodes as keynames
4111 //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
4112 
4113 
4114 var keycode = $.ui.keyCode = {
4115  BACKSPACE: 8,
4116  COMMA: 188,
4117  DELETE: 46,
4118  DOWN: 40,
4119  END: 35,
4120  ENTER: 13,
4121  ESCAPE: 27,
4122  HOME: 36,
4123  LEFT: 37,
4124  PAGE_DOWN: 34,
4125  PAGE_UP: 33,
4126  PERIOD: 190,
4127  RIGHT: 39,
4128  SPACE: 32,
4129  TAB: 9,
4130  UP: 38
4131 };
4132 
4133 
4134 
4135 
4136 // Internal use only
4137 var escapeSelector = $.ui.escapeSelector = ( function() {
4138  var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
4139  return function( selector ) {
4140  return selector.replace( selectorEscape, "\\$1" );
4141  };
4142 } )();
4143 
4144 
4154 //>>label: labels
4155 //>>group: Core
4156 //>>description: Find all the labels associated with a given input
4157 //>>docs: http://api.jqueryui.com/labels/
4158 
4159 
4160 
4161 var labels = $.fn.labels = function() {
4162  var ancestor, selector, id, labels, ancestors;
4163 
4164  // Check control.labels first
4165  if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4166  return this.pushStack( this[ 0 ].labels );
4167  }
4168 
4169  // Support: IE <= 11, FF <= 37, Android <= 2.3 only
4170  // Above browsers do not support control.labels. Everything below is to support them
4171  // as well as document fragments. control.labels does not work on document fragments
4172  labels = this.eq( 0 ).parents( "label" );
4173 
4174  // Look for the label based on the id
4175  id = this.attr( "id" );
4176  if ( id ) {
4177 
4178  // We don't search against the document in case the element
4179  // is disconnected from the DOM
4180  ancestor = this.eq( 0 ).parents().last();
4181 
4182  // Get a full set of top level ancestors
4183  ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4184 
4185  // Create a selector for the label based on the id
4186  selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
4187 
4188  labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4189 
4190  }
4191 
4192  // Return whatever we have found for labels
4193  return this.pushStack( labels );
4194 };
4195 
4196 
4206 //>>label: scrollParent
4207 //>>group: Core
4208 //>>description: Get the closest ancestor element that is scrollable.
4209 //>>docs: http://api.jqueryui.com/scrollParent/
4210 
4211 
4212 
4213 var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4214  var position = this.css( "position" ),
4215  excludeStaticParent = position === "absolute",
4216  overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4217  scrollParent = this.parents().filter( function() {
4218  var parent = $( this );
4219  if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4220  return false;
4221  }
4222  return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4223  parent.css( "overflow-x" ) );
4224  } ).eq( 0 );
4225 
4226  return position === "fixed" || !scrollParent.length ?
4227  $( this[ 0 ].ownerDocument || document ) :
4228  scrollParent;
4229 };
4230 
4231 
4241 //>>label: :tabbable Selector
4242 //>>group: Core
4243 //>>description: Selects elements which can be tabbed to.
4244 //>>docs: http://api.jqueryui.com/tabbable-selector/
4245 
4246 
4247 
4248 var tabbable = $.extend( $.expr[ ":" ], {
4249  tabbable: function( element ) {
4250  var tabIndex = $.attr( element, "tabindex" ),
4251  hasTabindex = tabIndex != null;
4252  return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4253  }
4254 } );
4255 
4256 
4266 //>>label: uniqueId
4267 //>>group: Core
4268 //>>description: Functions to generate and remove uniqueId's
4269 //>>docs: http://api.jqueryui.com/uniqueId/
4270 
4271 
4272 
4273 var uniqueId = $.fn.extend( {
4274  uniqueId: ( function() {
4275  var uuid = 0;
4276 
4277  return function() {
4278  return this.each( function() {
4279  if ( !this.id ) {
4280  this.id = "ui-id-" + ( ++uuid );
4281  }
4282  } );
4283  };
4284  } )(),
4285 
4286  removeUniqueId: function() {
4287  return this.each( function() {
4288  if ( /^ui-id-\d+$/.test( this.id ) ) {
4289  $( this ).removeAttr( "id" );
4290  }
4291  } );
4292  }
4293 } );
4294 
4295 
4305 //>>label: Accordion
4306 //>>group: Widgets
4307 // jscs:disable maximumLineLength
4308 //>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4309 // jscs:enable maximumLineLength
4310 //>>docs: http://api.jqueryui.com/accordion/
4311 //>>demos: http://jqueryui.com/accordion/
4312 //>>css.structure: ../../themes/base/core.css
4313 //>>css.structure: ../../themes/base/accordion.css
4314 //>>css.theme: ../../themes/base/theme.css
4315 
4316 
4317 
4318 var widgetsAccordion = $.widget( "ui.accordion", {
4319  version: "1.12.1",
4320  options: {
4321  active: 0,
4322  animate: {},
4323  classes: {
4324  "ui-accordion-header": "ui-corner-top",
4325  "ui-accordion-header-collapsed": "ui-corner-all",
4326  "ui-accordion-content": "ui-corner-bottom"
4327  },
4328  collapsible: false,
4329  event: "click",
4330  header: "> li > :first-child, > :not(li):even",
4331  heightStyle: "auto",
4332  icons: {
4333  activeHeader: "ui-icon-triangle-1-s",
4334  header: "ui-icon-triangle-1-e"
4335  },
4336 
4337  // Callbacks
4338  activate: null,
4339  beforeActivate: null
4340  },
4341 
4342  hideProps: {
4343  borderTopWidth: "hide",
4344  borderBottomWidth: "hide",
4345  paddingTop: "hide",
4346  paddingBottom: "hide",
4347  height: "hide"
4348  },
4349 
4350  showProps: {
4351  borderTopWidth: "show",
4352  borderBottomWidth: "show",
4353  paddingTop: "show",
4354  paddingBottom: "show",
4355  height: "show"
4356  },
4357 
4358  _create: function() {
4359  var options = this.options;
4360 
4361  this.prevShow = this.prevHide = $();
4362  this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4363  this.element.attr( "role", "tablist" );
4364 
4365  // Don't allow collapsible: false and active: false / null
4366  if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4367  options.active = 0;
4368  }
4369 
4370  this._processPanels();
4371 
4372  // handle negative values
4373  if ( options.active < 0 ) {
4374  options.active += this.headers.length;
4375  }
4376  this._refresh();
4377  },
4378 
4379  _getCreateEventData: function() {
4380  return {
4381  header: this.active,
4382  panel: !this.active.length ? $() : this.active.next()
4383  };
4384  },
4385 
4386  _createIcons: function() {
4387  var icon, children,
4388  icons = this.options.icons;
4389 
4390  if ( icons ) {
4391  icon = $( "<span>" );
4392  this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4393  icon.prependTo( this.headers );
4394  children = this.active.children( ".ui-accordion-header-icon" );
4395  this._removeClass( children, icons.header )
4396  ._addClass( children, null, icons.activeHeader )
4397  ._addClass( this.headers, "ui-accordion-icons" );
4398  }
4399  },
4400 
4401  _destroyIcons: function() {
4402  this._removeClass( this.headers, "ui-accordion-icons" );
4403  this.headers.children( ".ui-accordion-header-icon" ).remove();
4404  },
4405 
4406  _destroy: function() {
4407  var contents;
4408 
4409  // Clean up main element
4410  this.element.removeAttr( "role" );
4411 
4412  // Clean up headers
4413  this.headers
4414  .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4415  .removeUniqueId();
4416 
4417  this._destroyIcons();
4418 
4419  // Clean up content panels
4420  contents = this.headers.next()
4421  .css( "display", "" )
4422  .removeAttr( "role aria-hidden aria-labelledby" )
4423  .removeUniqueId();
4424 
4425  if ( this.options.heightStyle !== "content" ) {
4426  contents.css( "height", "" );
4427  }
4428  },
4429 
4430  _setOption: function( key, value ) {
4431  if ( key === "active" ) {
4432 
4433  // _activate() will handle invalid values and update this.options
4434  this._activate( value );
4435  return;
4436  }
4437 
4438  if ( key === "event" ) {
4439  if ( this.options.event ) {
4440  this._off( this.headers, this.options.event );
4441  }
4442  this._setupEvents( value );
4443  }
4444 
4445  this._super( key, value );
4446 
4447  // Setting collapsible: false while collapsed; open first panel
4448  if ( key === "collapsible" && !value && this.options.active === false ) {
4449  this._activate( 0 );
4450  }
4451 
4452  if ( key === "icons" ) {
4453  this._destroyIcons();
4454  if ( value ) {
4455  this._createIcons();
4456  }
4457  }
4458  },
4459 
4460  _setOptionDisabled: function( value ) {
4461  this._super( value );
4462 
4463  this.element.attr( "aria-disabled", value );
4464 
4465  // Support: IE8 Only
4466  // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
4467  // so we need to add the disabled class to the headers and panels
4468  this._toggleClass( null, "ui-state-disabled", !!value );
4469  this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
4470  !!value );
4471  },
4472 
4473  _keydown: function( event ) {
4474  if ( event.altKey || event.ctrlKey ) {
4475  return;
4476  }
4477 
4478  var keyCode = $.ui.keyCode,
4479  length = this.headers.length,
4480  currentIndex = this.headers.index( event.target ),
4481  toFocus = false;
4482 
4483  switch ( event.keyCode ) {
4484  case keyCode.RIGHT:
4485  case keyCode.DOWN:
4486  toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4487  break;
4488  case keyCode.LEFT:
4489  case keyCode.UP:
4490  toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4491  break;
4492  case keyCode.SPACE:
4493  case keyCode.ENTER:
4494  this._eventHandler( event );
4495  break;
4496  case keyCode.HOME:
4497  toFocus = this.headers[ 0 ];
4498  break;
4499  case keyCode.END:
4500  toFocus = this.headers[ length - 1 ];
4501  break;
4502  }
4503 
4504  if ( toFocus ) {
4505  $( event.target ).attr( "tabIndex", -1 );
4506  $( toFocus ).attr( "tabIndex", 0 );
4507  $( toFocus ).trigger( "focus" );
4508  event.preventDefault();
4509  }
4510  },
4511 
4512  _panelKeyDown: function( event ) {
4513  if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4514  $( event.currentTarget ).prev().trigger( "focus" );
4515  }
4516  },
4517 
4518  refresh: function() {
4519  var options = this.options;
4520  this._processPanels();
4521 
4522  // Was collapsed or no panel
4523  if ( ( options.active === false && options.collapsible === true ) ||
4524  !this.headers.length ) {
4525  options.active = false;
4526  this.active = $();
4527 
4528  // active false only when collapsible is true
4529  } else if ( options.active === false ) {
4530  this._activate( 0 );
4531 
4532  // was active, but active panel is gone
4533  } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4534 
4535  // all remaining panel are disabled
4536  if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4537  options.active = false;
4538  this.active = $();
4539 
4540  // activate previous panel
4541  } else {
4542  this._activate( Math.max( 0, options.active - 1 ) );
4543  }
4544 
4545  // was active, active panel still exists
4546  } else {
4547 
4548  // make sure active index is correct
4549  options.active = this.headers.index( this.active );
4550  }
4551 
4552  this._destroyIcons();
4553 
4554  this._refresh();
4555  },
4556 
4557  _processPanels: function() {
4558  var prevHeaders = this.headers,
4559  prevPanels = this.panels;
4560 
4561  this.headers = this.element.find( this.options.header );
4562  this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4563  "ui-state-default" );
4564 
4565  this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4566  this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4567 
4568  // Avoid memory leaks (#10056)
4569  if ( prevPanels ) {
4570  this._off( prevHeaders.not( this.headers ) );
4571  this._off( prevPanels.not( this.panels ) );
4572  }
4573  },
4574 
4575  _refresh: function() {
4576  var maxHeight,
4577  options = this.options,
4578  heightStyle = options.heightStyle,
4579  parent = this.element.parent();
4580 
4581  this.active = this._findActive( options.active );
4582  this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4583  ._removeClass( this.active, "ui-accordion-header-collapsed" );
4584  this._addClass( this.active.next(), "ui-accordion-content-active" );
4585  this.active.next().show();
4586 
4587  this.headers
4588  .attr( "role", "tab" )
4589  .each( function() {
4590  var header = $( this ),
4591  headerId = header.uniqueId().attr( "id" ),
4592  panel = header.next(),
4593  panelId = panel.uniqueId().attr( "id" );
4594  header.attr( "aria-controls", panelId );
4595  panel.attr( "aria-labelledby", headerId );
4596  } )
4597  .next()
4598  .attr( "role", "tabpanel" );
4599 
4600  this.headers
4601  .not( this.active )
4602  .attr( {
4603  "aria-selected": "false",
4604  "aria-expanded": "false",
4605  tabIndex: -1
4606  } )
4607  .next()
4608  .attr( {
4609  "aria-hidden": "true"
4610  } )
4611  .hide();
4612 
4613  // Make sure at least one header is in the tab order
4614  if ( !this.active.length ) {
4615  this.headers.eq( 0 ).attr( "tabIndex", 0 );
4616  } else {
4617  this.active.attr( {
4618  "aria-selected": "true",
4619  "aria-expanded": "true",
4620  tabIndex: 0
4621  } )
4622  .next()
4623  .attr( {
4624  "aria-hidden": "false"
4625  } );
4626  }
4627 
4628  this._createIcons();
4629 
4630  this._setupEvents( options.event );
4631 
4632  if ( heightStyle === "fill" ) {
4633  maxHeight = parent.height();
4634  this.element.siblings( ":visible" ).each( function() {
4635  var elem = $( this ),
4636  position = elem.css( "position" );
4637 
4638  if ( position === "absolute" || position === "fixed" ) {
4639  return;
4640  }
4641  maxHeight -= elem.outerHeight( true );
4642  } );
4643 
4644  this.headers.each( function() {
4645  maxHeight -= $( this ).outerHeight( true );
4646  } );
4647 
4648  this.headers.next()
4649  .each( function() {
4650  $( this ).height( Math.max( 0, maxHeight -
4651  $( this ).innerHeight() + $( this ).height() ) );
4652  } )
4653  .css( "overflow", "auto" );
4654  } else if ( heightStyle === "auto" ) {
4655  maxHeight = 0;
4656  this.headers.next()
4657  .each( function() {
4658  var isVisible = $( this ).is( ":visible" );
4659  if ( !isVisible ) {
4660  $( this ).show();
4661  }
4662  maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4663  if ( !isVisible ) {
4664  $( this ).hide();
4665  }
4666  } )
4667  .height( maxHeight );
4668  }
4669  },
4670 
4671  _activate: function( index ) {
4672  var active = this._findActive( index )[ 0 ];
4673 
4674  // Trying to activate the already active panel
4675  if ( active === this.active[ 0 ] ) {
4676  return;
4677  }
4678 
4679  // Trying to collapse, simulate a click on the currently active header
4680  active = active || this.active[ 0 ];
4681 
4682  this._eventHandler( {
4683  target: active,
4684  currentTarget: active,
4685  preventDefault: $.noop
4686  } );
4687  },
4688 
4689  _findActive: function( selector ) {
4690  return typeof selector === "number" ? this.headers.eq( selector ) : $();
4691  },
4692 
4693  _setupEvents: function( event ) {
4694  var events = {
4695  keydown: "_keydown"
4696  };
4697  if ( event ) {
4698  $.each( event.split( " " ), function( index, eventName ) {
4699  events[ eventName ] = "_eventHandler";
4700  } );
4701  }
4702 
4703  this._off( this.headers.add( this.headers.next() ) );
4704  this._on( this.headers, events );
4705  this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4706  this._hoverable( this.headers );
4707  this._focusable( this.headers );
4708  },
4709 
4710  _eventHandler: function( event ) {
4711  var activeChildren, clickedChildren,
4712  options = this.options,
4713  active = this.active,
4714  clicked = $( event.currentTarget ),
4715  clickedIsActive = clicked[ 0 ] === active[ 0 ],
4716  collapsing = clickedIsActive && options.collapsible,
4717  toShow = collapsing ? $() : clicked.next(),
4718  toHide = active.next(),
4719  eventData = {
4720  oldHeader: active,
4721  oldPanel: toHide,
4722  newHeader: collapsing ? $() : clicked,
4723  newPanel: toShow
4724  };
4725 
4726  event.preventDefault();
4727 
4728  if (
4729 
4730  // click on active header, but not collapsible
4731  ( clickedIsActive && !options.collapsible ) ||
4732 
4733  // allow canceling activation
4734  ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4735  return;
4736  }
4737 
4738  options.active = collapsing ? false : this.headers.index( clicked );
4739 
4740  // When the call to ._toggle() comes after the class changes
4741  // it causes a very odd bug in IE 8 (see #6720)
4742  this.active = clickedIsActive ? $() : clicked;
4743  this._toggle( eventData );
4744 
4745  // Switch classes
4746  // corner classes on the previously active header stay after the animation
4747  this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4748  if ( options.icons ) {
4749  activeChildren = active.children( ".ui-accordion-header-icon" );
4750  this._removeClass( activeChildren, null, options.icons.activeHeader )
4751  ._addClass( activeChildren, null, options.icons.header );
4752  }
4753 
4754  if ( !clickedIsActive ) {
4755  this._removeClass( clicked, "ui-accordion-header-collapsed" )
4756  ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4757  if ( options.icons ) {
4758  clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4759  this._removeClass( clickedChildren, null, options.icons.header )
4760  ._addClass( clickedChildren, null, options.icons.activeHeader );
4761  }
4762 
4763  this._addClass( clicked.next(), "ui-accordion-content-active" );
4764  }
4765  },
4766 
4767  _toggle: function( data ) {
4768  var toShow = data.newPanel,
4769  toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4770 
4771  // Handle activating a panel during the animation for another activation
4772  this.prevShow.add( this.prevHide ).stop( true, true );
4773  this.prevShow = toShow;
4774  this.prevHide = toHide;
4775 
4776  if ( this.options.animate ) {
4777  this._animate( toShow, toHide, data );
4778  } else {
4779  toHide.hide();
4780  toShow.show();
4781  this._toggleComplete( data );
4782  }
4783 
4784  toHide.attr( {
4785  "aria-hidden": "true"
4786  } );
4787  toHide.prev().attr( {
4788  "aria-selected": "false",
4789  "aria-expanded": "false"
4790  } );
4791 
4792  // if we're switching panels, remove the old header from the tab order
4793  // if we're opening from collapsed state, remove the previous header from the tab order
4794  // if we're collapsing, then keep the collapsing header in the tab order
4795  if ( toShow.length && toHide.length ) {
4796  toHide.prev().attr( {
4797  "tabIndex": -1,
4798  "aria-expanded": "false"
4799  } );
4800  } else if ( toShow.length ) {
4801  this.headers.filter( function() {
4802  return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4803  } )
4804  .attr( "tabIndex", -1 );
4805  }
4806 
4807  toShow
4808  .attr( "aria-hidden", "false" )
4809  .prev()
4810  .attr( {
4811  "aria-selected": "true",
4812  "aria-expanded": "true",
4813  tabIndex: 0
4814  } );
4815  },
4816 
4817  _animate: function( toShow, toHide, data ) {
4818  var total, easing, duration,
4819  that = this,
4820  adjust = 0,
4821  boxSizing = toShow.css( "box-sizing" ),
4822  down = toShow.length &&
4823  ( !toHide.length || ( toShow.index() < toHide.index() ) ),
4824  animate = this.options.animate || {},
4825  options = down && animate.down || animate,
4826  complete = function() {
4827  that._toggleComplete( data );
4828  };
4829 
4830  if ( typeof options === "number" ) {
4831  duration = options;
4832  }
4833  if ( typeof options === "string" ) {
4834  easing = options;
4835  }
4836 
4837  // fall back from options to animation in case of partial down settings
4838  easing = easing || options.easing || animate.easing;
4839  duration = duration || options.duration || animate.duration;
4840 
4841  if ( !toHide.length ) {
4842  return toShow.animate( this.showProps, duration, easing, complete );
4843  }
4844  if ( !toShow.length ) {
4845  return toHide.animate( this.hideProps, duration, easing, complete );
4846  }
4847 
4848  total = toShow.show().outerHeight();
4849  toHide.animate( this.hideProps, {
4850  duration: duration,
4851  easing: easing,
4852  step: function( now, fx ) {
4853  fx.now = Math.round( now );
4854  }
4855  } );
4856  toShow
4857  .hide()
4858  .animate( this.showProps, {
4859  duration: duration,
4860  easing: easing,
4861  complete: complete,
4862  step: function( now, fx ) {
4863  fx.now = Math.round( now );
4864  if ( fx.prop !== "height" ) {
4865  if ( boxSizing === "content-box" ) {
4866  adjust += fx.now;
4867  }
4868  } else if ( that.options.heightStyle !== "content" ) {
4869  fx.now = Math.round( total - toHide.outerHeight() - adjust );
4870  adjust = 0;
4871  }
4872  }
4873  } );
4874  },
4875 
4876  _toggleComplete: function( data ) {
4877  var toHide = data.oldPanel,
4878  prev = toHide.prev();
4879 
4880  this._removeClass( toHide, "ui-accordion-content-active" );
4881  this._removeClass( prev, "ui-accordion-header-active" )
4882  ._addClass( prev, "ui-accordion-header-collapsed" );
4883 
4884  // Work around for rendering bug in IE (#5421)
4885  if ( toHide.length ) {
4886  toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
4887  }
4888  this._trigger( "activate", null, data );
4889  }
4890 } );
4891 
4892 
4893 
4894 var safeActiveElement = $.ui.safeActiveElement = function( document ) {
4895  var activeElement;
4896 
4897  // Support: IE 9 only
4898  // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
4899  try {
4900  activeElement = document.activeElement;
4901  } catch ( error ) {
4902  activeElement = document.body;
4903  }
4904 
4905  // Support: IE 9 - 11 only
4906  // IE may return null instead of an element
4907  // Interestingly, this only seems to occur when NOT in an iframe
4908  if ( !activeElement ) {
4909  activeElement = document.body;
4910  }
4911 
4912  // Support: IE 11 only
4913  // IE11 returns a seemingly empty object in some cases when accessing
4914  // document.activeElement from an <iframe>
4915  if ( !activeElement.nodeName ) {
4916  activeElement = document.body;
4917  }
4918 
4919  return activeElement;
4920 };
4921 
4922 
4932 //>>label: Menu
4933 //>>group: Widgets
4934 //>>description: Creates nestable menus.
4935 //>>docs: http://api.jqueryui.com/menu/
4936 //>>demos: http://jqueryui.com/menu/
4937 //>>css.structure: ../../themes/base/core.css
4938 //>>css.structure: ../../themes/base/menu.css
4939 //>>css.theme: ../../themes/base/theme.css
4940 
4941 
4942 
4943 var widgetsMenu = $.widget( "ui.menu", {
4944  version: "1.12.1",
4945  defaultElement: "<ul>",
4946  delay: 300,
4947  options: {
4948  icons: {
4949  submenu: "ui-icon-caret-1-e"
4950  },
4951  items: "> *",
4952  menus: "ul",
4953  position: {
4954  my: "left top",
4955  at: "right top"
4956  },
4957  role: "menu",
4958 
4959  // Callbacks
4960  blur: null,
4961  focus: null,
4962  select: null
4963  },
4964 
4965  _create: function() {
4966  this.activeMenu = this.element;
4967 
4968  // Flag used to prevent firing of the click handler
4969  // as the event bubbles up through nested menus
4970  this.mouseHandled = false;
4971  this.element
4972  .uniqueId()
4973  .attr( {
4974  role: this.options.role,
4975  tabIndex: 0
4976  } );
4977 
4978  this._addClass( "ui-menu", "ui-widget ui-widget-content" );
4979  this._on( {
4980 
4981  // Prevent focus from sticking to links inside menu after clicking
4982  // them (focus should always stay on UL during navigation).
4983  "mousedown .ui-menu-item": function( event ) {
4984  event.preventDefault();
4985  },
4986  "click .ui-menu-item": function( event ) {
4987  var target = $( event.target );
4988  var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
4989  if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
4990  this.select( event );
4991 
4992  // Only set the mouseHandled flag if the event will bubble, see #9469.
4993  if ( !event.isPropagationStopped() ) {
4994  this.mouseHandled = true;
4995  }
4996 
4997  // Open submenu on click
4998  if ( target.has( ".ui-menu" ).length ) {
4999  this.expand( event );
5000  } else if ( !this.element.is( ":focus" ) &&
5001  active.closest( ".ui-menu" ).length ) {
5002 
5003  // Redirect focus to the menu
5004  this.element.trigger( "focus", [ true ] );
5005 
5006  // If the active item is on the top level, let it stay active.
5007  // Otherwise, blur the active item since it is no longer visible.
5008  if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
5009  clearTimeout( this.timer );
5010  }
5011  }
5012  }
5013  },
5014  "mouseenter .ui-menu-item": function( event ) {
5015 
5016  // Ignore mouse events while typeahead is active, see #10458.
5017  // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
5018  // is over an item in the menu
5019  if ( this.previousFilter ) {
5020  return;
5021  }
5022 
5023  var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
5024  target = $( event.currentTarget );
5025 
5026  // Ignore bubbled events on parent items, see #11641
5027  if ( actualTarget[ 0 ] !== target[ 0 ] ) {
5028  return;
5029  }
5030 
5031  // Remove ui-state-active class from siblings of the newly focused menu item
5032  // to avoid a jump caused by adjacent elements both having a class with a border
5033  this._removeClass( target.siblings().children( ".ui-state-active" ),
5034  null, "ui-state-active" );
5035  this.focus( event, target );
5036  },
5037  mouseleave: "collapseAll",
5038  "mouseleave .ui-menu": "collapseAll",
5039  focus: function( event, keepActiveItem ) {
5040 
5041  // If there's already an active item, keep it active
5042  // If not, activate the first item
5043  var item = this.active || this.element.find( this.options.items ).eq( 0 );
5044 
5045  if ( !keepActiveItem ) {
5046  this.focus( event, item );
5047  }
5048  },
5049  blur: function( event ) {
5050  this._delay( function() {
5051  var notContained = !$.contains(
5052  this.element[ 0 ],
5053  $.ui.safeActiveElement( this.document[ 0 ] )
5054  );
5055  if ( notContained ) {
5056  this.collapseAll( event );
5057  }
5058  } );
5059  },
5060  keydown: "_keydown"
5061  } );
5062 
5063  this.refresh();
5064 
5065  // Clicks outside of a menu collapse any open menus
5066  this._on( this.document, {
5067  click: function( event ) {
5068  if ( this._closeOnDocumentClick( event ) ) {
5069  this.collapseAll( event );
5070  }
5071 
5072  // Reset the mouseHandled flag
5073  this.mouseHandled = false;
5074  }
5075  } );
5076  },
5077 
5078  _destroy: function() {
5079  var items = this.element.find( ".ui-menu-item" )
5080  .removeAttr( "role aria-disabled" ),
5081  submenus = items.children( ".ui-menu-item-wrapper" )
5082  .removeUniqueId()
5083  .removeAttr( "tabIndex role aria-haspopup" );
5084 
5085  // Destroy (sub)menus
5086  this.element
5087  .removeAttr( "aria-activedescendant" )
5088  .find( ".ui-menu" ).addBack()
5089  .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5090  "tabIndex" )
5091  .removeUniqueId()
5092  .show();
5093 
5094  submenus.children().each( function() {
5095  var elem = $( this );
5096  if ( elem.data( "ui-menu-submenu-caret" ) ) {
5097  elem.remove();
5098  }
5099  } );
5100  },
5101 
5102  _keydown: function( event ) {
5103  var match, prev, character, skip,
5104  preventDefault = true;
5105 
5106  switch ( event.keyCode ) {
5107  case $.ui.keyCode.PAGE_UP:
5108  this.previousPage( event );
5109  break;
5110  case $.ui.keyCode.PAGE_DOWN:
5111  this.nextPage( event );
5112  break;
5113  case $.ui.keyCode.HOME:
5114  this._move( "first", "first", event );
5115  break;
5116  case $.ui.keyCode.END:
5117  this._move( "last", "last", event );
5118  break;
5119  case $.ui.keyCode.UP:
5120  this.previous( event );
5121  break;
5122  case $.ui.keyCode.DOWN:
5123  this.next( event );
5124  break;
5125  case $.ui.keyCode.LEFT:
5126  this.collapse( event );
5127  break;
5128  case $.ui.keyCode.RIGHT:
5129  if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5130  this.expand( event );
5131  }
5132  break;
5133  case $.ui.keyCode.ENTER:
5134  case $.ui.keyCode.SPACE:
5135  this._activate( event );
5136  break;
5137  case $.ui.keyCode.ESCAPE:
5138  this.collapse( event );
5139  break;
5140  default:
5141  preventDefault = false;
5142  prev = this.previousFilter || "";
5143  skip = false;
5144 
5145  // Support number pad values
5146  character = event.keyCode >= 96 && event.keyCode <= 105 ?
5147  ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5148 
5149  clearTimeout( this.filterTimer );
5150 
5151  if ( character === prev ) {
5152  skip = true;
5153  } else {
5154  character = prev + character;
5155  }
5156 
5157  match = this._filterMenuItems( character );
5158  match = skip && match.index( this.active.next() ) !== -1 ?
5159  this.active.nextAll( ".ui-menu-item" ) :
5160  match;
5161 
5162  // If no matches on the current filter, reset to the last character pressed
5163  // to move down the menu to the first item that starts with that character
5164  if ( !match.length ) {
5165  character = String.fromCharCode( event.keyCode );
5166  match = this._filterMenuItems( character );
5167  }
5168 
5169  if ( match.length ) {
5170  this.focus( event, match );
5171  this.previousFilter = character;
5172  this.filterTimer = this._delay( function() {
5173  delete this.previousFilter;
5174  }, 1000 );
5175  } else {
5176  delete this.previousFilter;
5177  }
5178  }
5179 
5180  if ( preventDefault ) {
5181  event.preventDefault();
5182  }
5183  },
5184 
5185  _activate: function( event ) {
5186  if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5187  if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5188  this.expand( event );
5189  } else {
5190  this.select( event );
5191  }
5192  }
5193  },
5194 
5195  refresh: function() {
5196  var menus, items, newSubmenus, newItems, newWrappers,
5197  that = this,
5198  icon = this.options.icons.submenu,
5199  submenus = this.element.find( this.options.menus );
5200 
5201  this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5202 
5203  // Initialize nested menus
5204  newSubmenus = submenus.filter( ":not(.ui-menu)" )
5205  .hide()
5206  .attr( {
5207  role: this.options.role,
5208  "aria-hidden": "true",
5209  "aria-expanded": "false"
5210  } )
5211  .each( function() {
5212  var menu = $( this ),
5213  item = menu.prev(),
5214  submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5215 
5216  that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5217  item
5218  .attr( "aria-haspopup", "true" )
5219  .prepend( submenuCaret );
5220  menu.attr( "aria-labelledby", item.attr( "id" ) );
5221  } );
5222 
5223  this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5224 
5225  menus = submenus.add( this.element );
5226  items = menus.find( this.options.items );
5227 
5228  // Initialize menu-items containing spaces and/or dashes only as dividers
5229  items.not( ".ui-menu-item" ).each( function() {
5230  var item = $( this );
5231  if ( that._isDivider( item ) ) {
5232  that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5233  }
5234  } );
5235 
5236  // Don't refresh list items that are already adapted
5237  newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5238  newWrappers = newItems.children()
5239  .not( ".ui-menu" )
5240  .uniqueId()
5241  .attr( {
5242  tabIndex: -1,
5243  role: this._itemRole()
5244  } );
5245  this._addClass( newItems, "ui-menu-item" )
5246  ._addClass( newWrappers, "ui-menu-item-wrapper" );
5247 
5248  // Add aria-disabled attribute to any disabled menu item
5249  items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5250 
5251  // If the active item has been removed, blur the menu
5252  if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5253  this.blur();
5254  }
5255  },
5256 
5257  _itemRole: function() {
5258  return {
5259  menu: "menuitem",
5260  listbox: "option"
5261  }[ this.options.role ];
5262  },
5263 
5264  _setOption: function( key, value ) {
5265  if ( key === "icons" ) {
5266  var icons = this.element.find( ".ui-menu-icon" );
5267  this._removeClass( icons, null, this.options.icons.submenu )
5268  ._addClass( icons, null, value.submenu );
5269  }
5270  this._super( key, value );
5271  },
5272 
5273  _setOptionDisabled: function( value ) {
5274  this._super( value );
5275 
5276  this.element.attr( "aria-disabled", String( value ) );
5277  this._toggleClass( null, "ui-state-disabled", !!value );
5278  },
5279 
5280  focus: function( event, item ) {
5281  var nested, focused, activeParent;
5282  this.blur( event, event && event.type === "focus" );
5283 
5284  this._scrollIntoView( item );
5285 
5286  this.active = item.first();
5287 
5288  focused = this.active.children( ".ui-menu-item-wrapper" );
5289  this._addClass( focused, null, "ui-state-active" );
5290 
5291  // Only update aria-activedescendant if there's a role
5292  // otherwise we assume focus is managed elsewhere
5293  if ( this.options.role ) {
5294  this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5295  }
5296 
5297  // Highlight active parent menu item, if any
5298  activeParent = this.active
5299  .parent()
5300  .closest( ".ui-menu-item" )
5301  .children( ".ui-menu-item-wrapper" );
5302  this._addClass( activeParent, null, "ui-state-active" );
5303 
5304  if ( event && event.type === "keydown" ) {
5305  this._close();
5306  } else {
5307  this.timer = this._delay( function() {
5308  this._close();
5309  }, this.delay );
5310  }
5311 
5312  nested = item.children( ".ui-menu" );
5313  if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5314  this._startOpening( nested );
5315  }
5316  this.activeMenu = item.parent();
5317 
5318  this._trigger( "focus", event, { item: item } );
5319  },
5320 
5321  _scrollIntoView: function( item ) {
5322  var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5323  if ( this._hasScroll() ) {
5324  borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5325  paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5326  offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5327  scroll = this.activeMenu.scrollTop();
5328  elementHeight = this.activeMenu.height();
5329  itemHeight = item.outerHeight();
5330 
5331  if ( offset < 0 ) {
5332  this.activeMenu.scrollTop( scroll + offset );
5333  } else if ( offset + itemHeight > elementHeight ) {
5334  this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5335  }
5336  }
5337  },
5338 
5339  blur: function( event, fromFocus ) {
5340  if ( !fromFocus ) {
5341  clearTimeout( this.timer );
5342  }
5343 
5344  if ( !this.active ) {
5345  return;
5346  }
5347 
5348  this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5349  null, "ui-state-active" );
5350 
5351  this._trigger( "blur", event, { item: this.active } );
5352  this.active = null;
5353  },
5354 
5355  _startOpening: function( submenu ) {
5356  clearTimeout( this.timer );
5357 
5358  // Don't open if already open fixes a Firefox bug that caused a .5 pixel
5359  // shift in the submenu position when mousing over the caret icon
5360  if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5361  return;
5362  }
5363 
5364  this.timer = this._delay( function() {
5365  this._close();
5366  this._open( submenu );
5367  }, this.delay );
5368  },
5369 
5370  _open: function( submenu ) {
5371  var position = $.extend( {
5372  of: this.active
5373  }, this.options.position );
5374 
5375  clearTimeout( this.timer );
5376  this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5377  .hide()
5378  .attr( "aria-hidden", "true" );
5379 
5380  submenu
5381  .show()
5382  .removeAttr( "aria-hidden" )
5383  .attr( "aria-expanded", "true" )
5384  .position( position );
5385  },
5386 
5387  collapseAll: function( event, all ) {
5388  clearTimeout( this.timer );
5389  this.timer = this._delay( function() {
5390 
5391  // If we were passed an event, look for the submenu that contains the event
5392  var currentMenu = all ? this.element :
5393  $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5394 
5395  // If we found no valid submenu ancestor, use the main menu to close all
5396  // sub menus anyway
5397  if ( !currentMenu.length ) {
5398  currentMenu = this.element;
5399  }
5400 
5401  this._close( currentMenu );
5402 
5403  this.blur( event );
5404 
5405  // Work around active item staying active after menu is blurred
5406  this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5407 
5408  this.activeMenu = currentMenu;
5409  }, this.delay );
5410  },
5411 
5412  // With no arguments, closes the currently active menu - if nothing is active
5413  // it closes all menus. If passed an argument, it will search for menus BELOW
5414  _close: function( startMenu ) {
5415  if ( !startMenu ) {
5416  startMenu = this.active ? this.active.parent() : this.element;
5417  }
5418 
5419  startMenu.find( ".ui-menu" )
5420  .hide()
5421  .attr( "aria-hidden", "true" )
5422  .attr( "aria-expanded", "false" );
5423  },
5424 
5425  _closeOnDocumentClick: function( event ) {
5426  return !$( event.target ).closest( ".ui-menu" ).length;
5427  },
5428 
5429  _isDivider: function( item ) {
5430 
5431  // Match hyphen, em dash, en dash
5432  return !/[^\-\u2014\u2013\s]/.test( item.text() );
5433  },
5434 
5435  collapse: function( event ) {
5436  var newItem = this.active &&
5437  this.active.parent().closest( ".ui-menu-item", this.element );
5438  if ( newItem && newItem.length ) {
5439  this._close();
5440  this.focus( event, newItem );
5441  }
5442  },
5443 
5444  expand: function( event ) {
5445  var newItem = this.active &&
5446  this.active
5447  .children( ".ui-menu " )
5448  .find( this.options.items )
5449  .first();
5450 
5451  if ( newItem && newItem.length ) {
5452  this._open( newItem.parent() );
5453 
5454  // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5455  this._delay( function() {
5456  this.focus( event, newItem );
5457  } );
5458  }
5459  },
5460 
5461  next: function( event ) {
5462  this._move( "next", "first", event );
5463  },
5464 
5465  previous: function( event ) {
5466  this._move( "prev", "last", event );
5467  },
5468 
5469  isFirstItem: function() {
5470  return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5471  },
5472 
5473  isLastItem: function() {
5474  return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5475  },
5476 
5477  _move: function( direction, filter, event ) {
5478  var next;
5479  if ( this.active ) {
5480  if ( direction === "first" || direction === "last" ) {
5481  next = this.active
5482  [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5483  .eq( -1 );
5484  } else {
5485  next = this.active
5486  [ direction + "All" ]( ".ui-menu-item" )
5487  .eq( 0 );
5488  }
5489  }
5490  if ( !next || !next.length || !this.active ) {
5491  next = this.activeMenu.find( this.options.items )[ filter ]();
5492  }
5493 
5494  this.focus( event, next );
5495  },
5496 
5497  nextPage: function( event ) {
5498  var item, base, height;
5499 
5500  if ( !this.active ) {
5501  this.next( event );
5502  return;
5503  }
5504  if ( this.isLastItem() ) {
5505  return;
5506  }
5507  if ( this._hasScroll() ) {
5508  base = this.active.offset().top;
5509  height = this.element.height();
5510  this.active.nextAll( ".ui-menu-item" ).each( function() {
5511  item = $( this );
5512  return item.offset().top - base - height < 0;
5513  } );
5514 
5515  this.focus( event, item );
5516  } else {
5517  this.focus( event, this.activeMenu.find( this.options.items )
5518  [ !this.active ? "first" : "last" ]() );
5519  }
5520  },
5521 
5522  previousPage: function( event ) {
5523  var item, base, height;
5524  if ( !this.active ) {
5525  this.next( event );
5526  return;
5527  }
5528  if ( this.isFirstItem() ) {
5529  return;
5530  }
5531  if ( this._hasScroll() ) {
5532  base = this.active.offset().top;
5533  height = this.element.height();
5534  this.active.prevAll( ".ui-menu-item" ).each( function() {
5535  item = $( this );
5536  return item.offset().top - base + height > 0;
5537  } );
5538 
5539  this.focus( event, item );
5540  } else {
5541  this.focus( event, this.activeMenu.find( this.options.items ).first() );
5542  }
5543  },
5544 
5545  _hasScroll: function() {
5546  return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5547  },
5548 
5549  select: function( event ) {
5550 
5551  // TODO: It should never be possible to not have an active item at this
5552  // point, but the tests don't trigger mouseenter before click.
5553  this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5554  var ui = { item: this.active };
5555  if ( !this.active.has( ".ui-menu" ).length ) {
5556  this.collapseAll( event, true );
5557  }
5558  this._trigger( "select", event, ui );
5559  },
5560 
5561  _filterMenuItems: function( character ) {
5562  var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5563  regex = new RegExp( "^" + escapedCharacter, "i" );
5564 
5565  return this.activeMenu
5566  .find( this.options.items )
5567 
5568  // Only match on items, not dividers or other content (#10571)
5569  .filter( ".ui-menu-item" )
5570  .filter( function() {
5571  return regex.test(
5572  $.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5573  } );
5574  }
5575 } );
5576 
5577 
5587 //>>label: Autocomplete
5588 //>>group: Widgets
5589 //>>description: Lists suggested words as the user is typing.
5590 //>>docs: http://api.jqueryui.com/autocomplete/
5591 //>>demos: http://jqueryui.com/autocomplete/
5592 //>>css.structure: ../../themes/base/core.css
5593 //>>css.structure: ../../themes/base/autocomplete.css
5594 //>>css.theme: ../../themes/base/theme.css
5595 
5596 
5597 
5598 $.widget( "ui.autocomplete", {
5599  version: "1.12.1",
5600  defaultElement: "<input>",
5601  options: {
5602  appendTo: null,
5603  autoFocus: false,
5604  delay: 300,
5605  minLength: 1,
5606  position: {
5607  my: "left top",
5608  at: "left bottom",
5609  collision: "none"
5610  },
5611  source: null,
5612 
5613  // Callbacks
5614  change: null,
5615  close: null,
5616  focus: null,
5617  open: null,
5618  response: null,
5619  search: null,
5620  select: null
5621  },
5622 
5623  requestIndex: 0,
5624  pending: 0,
5625 
5626  _create: function() {
5627 
5628  // Some browsers only repeat keydown events, not keypress events,
5629  // so we use the suppressKeyPress flag to determine if we've already
5630  // handled the keydown event. #7269
5631  // Unfortunately the code for & in keypress is the same as the up arrow,
5632  // so we use the suppressKeyPressRepeat flag to avoid handling keypress
5633  // events when we know the keydown event was used to modify the
5634  // search term. #7799
5635  var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5636  nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5637  isTextarea = nodeName === "textarea",
5638  isInput = nodeName === "input";
5639 
5640  // Textareas are always multi-line
5641  // Inputs are always single-line, even if inside a contentEditable element
5642  // IE also treats inputs as contentEditable
5643  // All other element types are determined by whether or not they're contentEditable
5644  this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
5645 
5646  this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5647  this.isNewMenu = true;
5648 
5649  this._addClass( "ui-autocomplete-input" );
5650  this.element.attr( "autocomplete", "off" );
5651 
5652  this._on( this.element, {
5653  keydown: function( event ) {
5654  if ( this.element.prop( "readOnly" ) ) {
5655  suppressKeyPress = true;
5656  suppressInput = true;
5657  suppressKeyPressRepeat = true;
5658  return;
5659  }
5660 
5661  suppressKeyPress = false;
5662  suppressInput = false;
5663  suppressKeyPressRepeat = false;
5664  var keyCode = $.ui.keyCode;
5665  switch ( event.keyCode ) {
5666  case keyCode.PAGE_UP:
5667  suppressKeyPress = true;
5668  this._move( "previousPage", event );
5669  break;
5670  case keyCode.PAGE_DOWN:
5671  suppressKeyPress = true;
5672  this._move( "nextPage", event );
5673  break;
5674  case keyCode.UP:
5675  suppressKeyPress = true;
5676  this._keyEvent( "previous", event );
5677  break;
5678  case keyCode.DOWN:
5679  suppressKeyPress = true;
5680  this._keyEvent( "next", event );
5681  break;
5682  case keyCode.ENTER:
5683 
5684  // when menu is open and has focus
5685  if ( this.menu.active ) {
5686 
5687  // #6055 - Opera still allows the keypress to occur
5688  // which causes forms to submit
5689  suppressKeyPress = true;
5690  event.preventDefault();
5691  this.menu.select( event );
5692  }
5693  break;
5694  case keyCode.TAB:
5695  if ( this.menu.active ) {
5696  this.menu.select( event );
5697  }
5698  break;
5699  case keyCode.ESCAPE:
5700  if ( this.menu.element.is( ":visible" ) ) {
5701  if ( !this.isMultiLine ) {
5702  this._value( this.term );
5703  }
5704  this.close( event );
5705 
5706  // Different browsers have different default behavior for escape
5707  // Single press can mean undo or clear
5708  // Double press in IE means clear the whole form
5709  event.preventDefault();
5710  }
5711  break;
5712  default:
5713  suppressKeyPressRepeat = true;
5714 
5715  // search timeout should be triggered before the input value is changed
5716  this._searchTimeout( event );
5717  break;
5718  }
5719  },
5720  keypress: function( event ) {
5721  if ( suppressKeyPress ) {
5722  suppressKeyPress = false;
5723  if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5724  event.preventDefault();
5725  }
5726  return;
5727  }
5728  if ( suppressKeyPressRepeat ) {
5729  return;
5730  }
5731 
5732  // Replicate some key handlers to allow them to repeat in Firefox and Opera
5733  var keyCode = $.ui.keyCode;
5734  switch ( event.keyCode ) {
5735  case keyCode.PAGE_UP:
5736  this._move( "previousPage", event );
5737  break;
5738  case keyCode.PAGE_DOWN:
5739  this._move( "nextPage", event );
5740  break;
5741  case keyCode.UP:
5742  this._keyEvent( "previous", event );
5743  break;
5744  case keyCode.DOWN:
5745  this._keyEvent( "next", event );
5746  break;
5747  }
5748  },
5749  input: function( event ) {
5750  if ( suppressInput ) {
5751  suppressInput = false;
5752  event.preventDefault();
5753  return;
5754  }
5755  this._searchTimeout( event );
5756  },
5757  focus: function() {
5758  this.selectedItem = null;
5759  this.previous = this._value();
5760  },
5761  blur: function( event ) {
5762  if ( this.cancelBlur ) {
5763  delete this.cancelBlur;
5764  return;
5765  }
5766 
5767  clearTimeout( this.searching );
5768  this.close( event );
5769  this._change( event );
5770  }
5771  } );
5772 
5773  this._initSource();
5774  this.menu = $( "<ul>" )
5775  .appendTo( this._appendTo() )
5776  .menu( {
5777 
5778  // disable ARIA support, the live region takes care of that
5779  role: null
5780  } )
5781  .hide()
5782  .menu( "instance" );
5783 
5784  this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5785  this._on( this.menu.element, {
5786  mousedown: function( event ) {
5787 
5788  // prevent moving focus out of the text field
5789  event.preventDefault();
5790 
5791  // IE doesn't prevent moving focus even with event.preventDefault()
5792  // so we set a flag to know when we should ignore the blur event
5793  this.cancelBlur = true;
5794  this._delay( function() {
5795  delete this.cancelBlur;
5796 
5797  // Support: IE 8 only
5798  // Right clicking a menu item or selecting text from the menu items will
5799  // result in focus moving out of the input. However, we've already received
5800  // and ignored the blur event because of the cancelBlur flag set above. So
5801  // we restore focus to ensure that the menu closes properly based on the user's
5802  // next actions.
5803  if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5804  this.element.trigger( "focus" );
5805  }
5806  } );
5807  },
5808  menufocus: function( event, ui ) {
5809  var label, item;
5810 
5811  // support: Firefox
5812  // Prevent accidental activation of menu items in Firefox (#7024 #9118)
5813  if ( this.isNewMenu ) {
5814  this.isNewMenu = false;
5815  if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5816  this.menu.blur();
5817 
5818  this.document.one( "mousemove", function() {
5819  $( event.target ).trigger( event.originalEvent );
5820  } );
5821 
5822  return;
5823  }
5824  }
5825 
5826  item = ui.item.data( "ui-autocomplete-item" );
5827  if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5828 
5829  // use value to match what will end up in the input, if it was a key event
5830  if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5831  this._value( item.value );
5832  }
5833  }
5834 
5835  // Announce the value in the liveRegion
5836  label = ui.item.attr( "aria-label" ) || item.value;
5837  if ( label && $.trim( label ).length ) {
5838  this.liveRegion.children().hide();
5839  $( "<div>" ).text( label ).appendTo( this.liveRegion );
5840  }
5841  },
5842  menuselect: function( event, ui ) {
5843  var item = ui.item.data( "ui-autocomplete-item" ),
5844  previous = this.previous;
5845 
5846  // Only trigger when focus was lost (click on menu)
5847  if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5848  this.element.trigger( "focus" );
5849  this.previous = previous;
5850 
5851  // #6109 - IE triggers two focus events and the second
5852  // is asynchronous, so we need to reset the previous
5853  // term synchronously and asynchronously :-(
5854  this._delay( function() {
5855  this.previous = previous;
5856  this.selectedItem = item;
5857  } );
5858  }
5859 
5860  if ( false !== this._trigger( "select", event, { item: item } ) ) {
5861  this._value( item.value );
5862  }
5863 
5864  // reset the term after the select event
5865  // this allows custom select handling to work properly
5866  this.term = this._value();
5867 
5868  this.close( event );
5869  this.selectedItem = item;
5870  }
5871  } );
5872 
5873  this.liveRegion = $( "<div>", {
5874  role: "status",
5875  "aria-live": "assertive",
5876  "aria-relevant": "additions"
5877  } )
5878  .appendTo( this.document[ 0 ].body );
5879 
5880  this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5881 
5882  // Turning off autocomplete prevents the browser from remembering the
5883  // value when navigating through history, so we re-enable autocomplete
5884  // if the page is unloaded before the widget is destroyed. #7790
5885  this._on( this.window, {
5886  beforeunload: function() {
5887  this.element.removeAttr( "autocomplete" );
5888  }
5889  } );
5890  },
5891 
5892  _destroy: function() {
5893  clearTimeout( this.searching );
5894  this.element.removeAttr( "autocomplete" );
5895  this.menu.element.remove();
5896  this.liveRegion.remove();
5897  },
5898 
5899  _setOption: function( key, value ) {
5900  this._super( key, value );
5901  if ( key === "source" ) {
5902  this._initSource();
5903  }
5904  if ( key === "appendTo" ) {
5905  this.menu.element.appendTo( this._appendTo() );
5906  }
5907  if ( key === "disabled" && value && this.xhr ) {
5908  this.xhr.abort();
5909  }
5910  },
5911 
5912  _isEventTargetInWidget: function( event ) {
5913  var menuElement = this.menu.element[ 0 ];
5914 
5915  return event.target === this.element[ 0 ] ||
5916  event.target === menuElement ||
5917  $.contains( menuElement, event.target );
5918  },
5919 
5920  _closeOnClickOutside: function( event ) {
5921  if ( !this._isEventTargetInWidget( event ) ) {
5922  this.close();
5923  }
5924  },
5925 
5926  _appendTo: function() {
5927  var element = this.options.appendTo;
5928 
5929  if ( element ) {
5930  element = element.jquery || element.nodeType ?
5931  $( element ) :
5932  this.document.find( element ).eq( 0 );
5933  }
5934 
5935  if ( !element || !element[ 0 ] ) {
5936  element = this.element.closest( ".ui-front, dialog" );
5937  }
5938 
5939  if ( !element.length ) {
5940  element = this.document[ 0 ].body;
5941  }
5942 
5943  return element;
5944  },
5945 
5946  _initSource: function() {
5947  var array, url,
5948  that = this;
5949  if ( $.isArray( this.options.source ) ) {
5950  array = this.options.source;
5951  this.source = function( request, response ) {
5952  response( $.ui.autocomplete.filter( array, request.term ) );
5953  };
5954  } else if ( typeof this.options.source === "string" ) {
5955  url = this.options.source;
5956  this.source = function( request, response ) {
5957  if ( that.xhr ) {
5958  that.xhr.abort();
5959  }
5960  that.xhr = $.ajax( {
5961  url: url,
5962  data: request,
5963  dataType: "json",
5964  success: function( data ) {
5965  response( data );
5966  },
5967  error: function() {
5968  response( [] );
5969  }
5970  } );
5971  };
5972  } else {
5973  this.source = this.options.source;
5974  }
5975  },
5976 
5977  _searchTimeout: function( event ) {
5978  clearTimeout( this.searching );
5979  this.searching = this._delay( function() {
5980 
5981  // Search if the value has changed, or if the user retypes the same value (see #7434)
5982  var equalValues = this.term === this._value(),
5983  menuVisible = this.menu.element.is( ":visible" ),
5984  modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
5985 
5986  if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
5987  this.selectedItem = null;
5988  this.search( null, event );
5989  }
5990  }, this.options.delay );
5991  },
5992 
5993  search: function( value, event ) {
5994  value = value != null ? value : this._value();
5995 
5996  // Always save the actual value, not the one passed as an argument
5997  this.term = this._value();
5998 
5999  if ( value.length < this.options.minLength ) {
6000  return this.close( event );
6001  }
6002 
6003  if ( this._trigger( "search", event ) === false ) {
6004  return;
6005  }
6006 
6007  return this._search( value );
6008  },
6009 
6010  _search: function( value ) {
6011  this.pending++;
6012  this._addClass( "ui-autocomplete-loading" );
6013  this.cancelSearch = false;
6014 
6015  this.source( { term: value }, this._response() );
6016  },
6017 
6018  _response: function() {
6019  var index = ++this.requestIndex;
6020 
6021  return $.proxy( function( content ) {
6022  if ( index === this.requestIndex ) {
6023  this.__response( content );
6024  }
6025 
6026  this.pending--;
6027  if ( !this.pending ) {
6028  this._removeClass( "ui-autocomplete-loading" );
6029  }
6030  }, this );
6031  },
6032 
6033  __response: function( content ) {
6034  if ( content ) {
6035  content = this._normalize( content );
6036  }
6037  this._trigger( "response", null, { content: content } );
6038  if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6039  this._suggest( content );
6040  this._trigger( "open" );
6041  } else {
6042 
6043  // use ._close() instead of .close() so we don't cancel future searches
6044  this._close();
6045  }
6046  },
6047 
6048  close: function( event ) {
6049  this.cancelSearch = true;
6050  this._close( event );
6051  },
6052 
6053  _close: function( event ) {
6054 
6055  // Remove the handler that closes the menu on outside clicks
6056  this._off( this.document, "mousedown" );
6057 
6058  if ( this.menu.element.is( ":visible" ) ) {
6059  this.menu.element.hide();
6060  this.menu.blur();
6061  this.isNewMenu = true;
6062  this._trigger( "close", event );
6063  }
6064  },
6065 
6066  _change: function( event ) {
6067  if ( this.previous !== this._value() ) {
6068  this._trigger( "change", event, { item: this.selectedItem } );
6069  }
6070  },
6071 
6072  _normalize: function( items ) {
6073 
6074  // assume all items have the right format when the first item is complete
6075  if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
6076  return items;
6077  }
6078  return $.map( items, function( item ) {
6079  if ( typeof item === "string" ) {
6080  return {
6081  label: item,
6082  value: item
6083  };
6084  }
6085  return $.extend( {}, item, {
6086  label: item.label || item.value,
6087  value: item.value || item.label
6088  } );
6089  } );
6090  },
6091 
6092  _suggest: function( items ) {
6093  var ul = this.menu.element.empty();
6094  this._renderMenu( ul, items );
6095  this.isNewMenu = true;
6096  this.menu.refresh();
6097 
6098  // Size and position menu
6099  ul.show();
6100  this._resizeMenu();
6101  ul.position( $.extend( {
6102  of: this.element
6103  }, this.options.position ) );
6104 
6105  if ( this.options.autoFocus ) {
6106  this.menu.next();
6107  }
6108 
6109  // Listen for interactions outside of the widget (#6642)
6110  this._on( this.document, {
6111  mousedown: "_closeOnClickOutside"
6112  } );
6113  },
6114 
6115  _resizeMenu: function() {
6116  var ul = this.menu.element;
6117  ul.outerWidth( Math.max(
6118 
6119  // Firefox wraps long text (possibly a rounding bug)
6120  // so we add 1px to avoid the wrapping (#7513)
6121  ul.width( "" ).outerWidth() + 1,
6122  this.element.outerWidth()
6123  ) );
6124  },
6125 
6126  _renderMenu: function( ul, items ) {
6127  var that = this;
6128  $.each( items, function( index, item ) {
6129  that._renderItemData( ul, item );
6130  } );
6131  },
6132 
6133  _renderItemData: function( ul, item ) {
6134  return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6135  },
6136 
6137  _renderItem: function( ul, item ) {
6138  return $( "<li>" )
6139  .append( $( "<div>" ).text( item.label ) )
6140  .appendTo( ul );
6141  },
6142 
6143  _move: function( direction, event ) {
6144  if ( !this.menu.element.is( ":visible" ) ) {
6145  this.search( null, event );
6146  return;
6147  }
6148  if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6149  this.menu.isLastItem() && /^next/.test( direction ) ) {
6150 
6151  if ( !this.isMultiLine ) {
6152  this._value( this.term );
6153  }
6154 
6155  this.menu.blur();
6156  return;
6157  }
6158  this.menu[ direction ]( event );
6159  },
6160 
6161  widget: function() {
6162  return this.menu.element;
6163  },
6164 
6165  _value: function() {
6166  return this.valueMethod.apply( this.element, arguments );
6167  },
6168 
6169  _keyEvent: function( keyEvent, event ) {
6170  if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6171  this._move( keyEvent, event );
6172 
6173  // Prevents moving cursor to beginning/end of the text field in some browsers
6174  event.preventDefault();
6175  }
6176  },
6177 
6178  // Support: Chrome <=50
6179  // We should be able to just use this.element.prop( "isContentEditable" )
6180  // but hidden elements always report false in Chrome.
6181  // https://code.google.com/p/chromium/issues/detail?id=313082
6182  _isContentEditable: function( element ) {
6183  if ( !element.length ) {
6184  return false;
6185  }
6186 
6187  var editable = element.prop( "contentEditable" );
6188 
6189  if ( editable === "inherit" ) {
6190  return this._isContentEditable( element.parent() );
6191  }
6192 
6193  return editable === "true";
6194  }
6195 } );
6196 
6197 $.extend( $.ui.autocomplete, {
6198  escapeRegex: function( value ) {
6199  return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6200  },
6201  filter: function( array, term ) {
6202  var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6203  return $.grep( array, function( value ) {
6204  return matcher.test( value.label || value.value || value );
6205  } );
6206  }
6207 } );
6208 
6209 // Live region extension, adding a `messages` option
6210 // NOTE: This is an experimental API. We are still investigating
6211 // a full solution for string manipulation and internationalization.
6212 $.widget( "ui.autocomplete", $.ui.autocomplete, {
6213  options: {
6214  messages: {
6215  noResults: "No search results.",
6216  results: function( amount ) {
6217  return amount + ( amount > 1 ? " results are" : " result is" ) +
6218  " available, use up and down arrow keys to navigate.";
6219  }
6220  }
6221  },
6222 
6223  __response: function( content ) {
6224  var message;
6225  this._superApply( arguments );
6226  if ( this.options.disabled || this.cancelSearch ) {
6227  return;
6228  }
6229  if ( content && content.length ) {
6230  message = this.options.messages.results( content.length );
6231  } else {
6232  message = this.options.messages.noResults;
6233  }
6234  this.liveRegion.children().hide();
6235  $( "<div>" ).text( message ).appendTo( this.liveRegion );
6236  }
6237 } );
6238 
6239 var widgetsAutocomplete = $.ui.autocomplete;
6240 
6241 
6251 //>>label: Controlgroup
6252 //>>group: Widgets
6253 //>>description: Visually groups form control widgets
6254 //>>docs: http://api.jqueryui.com/controlgroup/
6255 //>>demos: http://jqueryui.com/controlgroup/
6256 //>>css.structure: ../../themes/base/core.css
6257 //>>css.structure: ../../themes/base/controlgroup.css
6258 //>>css.theme: ../../themes/base/theme.css
6259 
6260 
6261 var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6262 
6263 var widgetsControlgroup = $.widget( "ui.controlgroup", {
6264  version: "1.12.1",
6265  defaultElement: "<div>",
6266  options: {
6267  direction: "horizontal",
6268  disabled: null,
6269  onlyVisible: true,
6270  items: {
6271  "button": "input[type=button], input[type=submit], input[type=reset], button, a",
6272  "controlgroupLabel": ".ui-controlgroup-label",
6273  "checkboxradio": "input[type='checkbox'], input[type='radio']",
6274  "selectmenu": "select",
6275  "spinner": ".ui-spinner-input"
6276  }
6277  },
6278 
6279  _create: function() {
6280  this._enhance();
6281  },
6282 
6283  // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6284  _enhance: function() {
6285  this.element.attr( "role", "toolbar" );
6286  this.refresh();
6287  },
6288 
6289  _destroy: function() {
6290  this._callChildMethod( "destroy" );
6291  this.childWidgets.removeData( "ui-controlgroup-data" );
6292  this.element.removeAttr( "role" );
6293  if ( this.options.items.controlgroupLabel ) {
6294  this.element
6295  .find( this.options.items.controlgroupLabel )
6296  .find( ".ui-controlgroup-label-contents" )
6297  .contents().unwrap();
6298  }
6299  },
6300 
6301  _initWidgets: function() {
6302  var that = this,
6303  childWidgets = [];
6304 
6305  // First we iterate over each of the items options
6306  $.each( this.options.items, function( widget, selector ) {
6307  var labels;
6308  var options = {};
6309 
6310  // Make sure the widget has a selector set
6311  if ( !selector ) {
6312  return;
6313  }
6314 
6315  if ( widget === "controlgroupLabel" ) {
6316  labels = that.element.find( selector );
6317  labels.each( function() {
6318  var element = $( this );
6319 
6320  if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6321  return;
6322  }
6323  element.contents()
6324  .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6325  } );
6326  that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6327  childWidgets = childWidgets.concat( labels.get() );
6328  return;
6329  }
6330 
6331  // Make sure the widget actually exists
6332  if ( !$.fn[ widget ] ) {
6333  return;
6334  }
6335 
6336  // We assume everything is in the middle to start because we can't determine
6337  // first / last elements until all enhancments are done.
6338  if ( that[ "_" + widget + "Options" ] ) {
6339  options = that[ "_" + widget + "Options" ]( "middle" );
6340  } else {
6341  options = { classes: {} };
6342  }
6343 
6344  // Find instances of this widget inside controlgroup and init them
6345  that.element
6346  .find( selector )
6347  .each( function() {
6348  var element = $( this );
6349  var instance = element[ widget ]( "instance" );
6350 
6351  // We need to clone the default options for this type of widget to avoid
6352  // polluting the variable options which has a wider scope than a single widget.
6353  var instanceOptions = $.widget.extend( {}, options );
6354 
6355  // If the button is the child of a spinner ignore it
6356  // TODO: Find a more generic solution
6357  if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6358  return;
6359  }
6360 
6361  // Create the widget if it doesn't exist
6362  if ( !instance ) {
6363  instance = element[ widget ]()[ widget ]( "instance" );
6364  }
6365  if ( instance ) {
6366  instanceOptions.classes =
6367  that._resolveClassesValues( instanceOptions.classes, instance );
6368  }
6369  element[ widget ]( instanceOptions );
6370 
6371  // Store an instance of the controlgroup to be able to reference
6372  // from the outermost element for changing options and refresh
6373  var widgetElement = element[ widget ]( "widget" );
6374  $.data( widgetElement[ 0 ], "ui-controlgroup-data",
6375  instance ? instance : element[ widget ]( "instance" ) );
6376 
6377  childWidgets.push( widgetElement[ 0 ] );
6378  } );
6379  } );
6380 
6381  this.childWidgets = $( $.unique( childWidgets ) );
6382  this._addClass( this.childWidgets, "ui-controlgroup-item" );
6383  },
6384 
6385  _callChildMethod: function( method ) {
6386  this.childWidgets.each( function() {
6387  var element = $( this ),
6388  data = element.data( "ui-controlgroup-data" );
6389  if ( data && data[ method ] ) {
6390  data[ method ]();
6391  }
6392  } );
6393  },
6394 
6395  _updateCornerClass: function( element, position ) {
6396  var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6397  var add = this._buildSimpleOptions( position, "label" ).classes.label;
6398 
6399  this._removeClass( element, null, remove );
6400  this._addClass( element, null, add );
6401  },
6402 
6403  _buildSimpleOptions: function( position, key ) {
6404  var direction = this.options.direction === "vertical";
6405  var result = {
6406  classes: {}
6407  };
6408  result.classes[ key ] = {
6409  "middle": "",
6410  "first": "ui-corner-" + ( direction ? "top" : "left" ),
6411  "last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6412  "only": "ui-corner-all"
6413  }[ position ];
6414 
6415  return result;
6416  },
6417 
6418  _spinnerOptions: function( position ) {
6419  var options = this._buildSimpleOptions( position, "ui-spinner" );
6420 
6421  options.classes[ "ui-spinner-up" ] = "";
6422  options.classes[ "ui-spinner-down" ] = "";
6423 
6424  return options;
6425  },
6426 
6427  _buttonOptions: function( position ) {
6428  return this._buildSimpleOptions( position, "ui-button" );
6429  },
6430 
6431  _checkboxradioOptions: function( position ) {
6432  return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6433  },
6434 
6435  _selectmenuOptions: function( position ) {
6436  var direction = this.options.direction === "vertical";
6437  return {
6438  width: direction ? "auto" : false,
6439  classes: {
6440  middle: {
6441  "ui-selectmenu-button-open": "",
6442  "ui-selectmenu-button-closed": ""
6443  },
6444  first: {
6445  "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6446  "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6447  },
6448  last: {
6449  "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6450  "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6451  },
6452  only: {
6453  "ui-selectmenu-button-open": "ui-corner-top",
6454  "ui-selectmenu-button-closed": "ui-corner-all"
6455  }
6456 
6457  }[ position ]
6458  };
6459  },
6460 
6461  _resolveClassesValues: function( classes, instance ) {
6462  var result = {};
6463  $.each( classes, function( key ) {
6464  var current = instance.options.classes[ key ] || "";
6465  current = $.trim( current.replace( controlgroupCornerRegex, "" ) );
6466  result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6467  } );
6468  return result;
6469  },
6470 
6471  _setOption: function( key, value ) {
6472  if ( key === "direction" ) {
6473  this._removeClass( "ui-controlgroup-" + this.options.direction );
6474  }
6475 
6476  this._super( key, value );
6477  if ( key === "disabled" ) {
6478  this._callChildMethod( value ? "disable" : "enable" );
6479  return;
6480  }
6481 
6482  this.refresh();
6483  },
6484 
6485  refresh: function() {
6486  var children,
6487  that = this;
6488 
6489  this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6490 
6491  if ( this.options.direction === "horizontal" ) {
6492  this._addClass( null, "ui-helper-clearfix" );
6493  }
6494  this._initWidgets();
6495 
6496  children = this.childWidgets;
6497 
6498  // We filter here because we need to track all childWidgets not just the visible ones
6499  if ( this.options.onlyVisible ) {
6500  children = children.filter( ":visible" );
6501  }
6502 
6503  if ( children.length ) {
6504 
6505  // We do this last because we need to make sure all enhancment is done
6506  // before determining first and last
6507  $.each( [ "first", "last" ], function( index, value ) {
6508  var instance = children[ value ]().data( "ui-controlgroup-data" );
6509 
6510  if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6511  var options = that[ "_" + instance.widgetName + "Options" ](
6512  children.length === 1 ? "only" : value
6513  );
6514  options.classes = that._resolveClassesValues( options.classes, instance );
6515  instance.element[ instance.widgetName ]( options );
6516  } else {
6517  that._updateCornerClass( children[ value ](), value );
6518  }
6519  } );
6520 
6521  // Finally call the refresh method on each of the child widgets.
6522  this._callChildMethod( "refresh" );
6523  }
6524  }
6525 } );
6526 
6536 //>>label: Checkboxradio
6537 //>>group: Widgets
6538 //>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6539 //>>docs: http://api.jqueryui.com/checkboxradio/
6540 //>>demos: http://jqueryui.com/checkboxradio/
6541 //>>css.structure: ../../themes/base/core.css
6542 //>>css.structure: ../../themes/base/button.css
6543 //>>css.structure: ../../themes/base/checkboxradio.css
6544 //>>css.theme: ../../themes/base/theme.css
6545 
6546 
6547 
6548 $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6549  version: "1.12.1",
6550  options: {
6551  disabled: null,
6552  label: null,
6553  icon: true,
6554  classes: {
6555  "ui-checkboxradio-label": "ui-corner-all",
6556  "ui-checkboxradio-icon": "ui-corner-all"
6557  }
6558  },
6559 
6560  _getCreateOptions: function() {
6561  var disabled, labels;
6562  var that = this;
6563  var options = this._super() || {};
6564 
6565  // We read the type here, because it makes more sense to throw a element type error first,
6566  // rather then the error for lack of a label. Often if its the wrong type, it
6567  // won't have a label (e.g. calling on a div, btn, etc)
6568  this._readType();
6569 
6570  labels = this.element.labels();
6571 
6572  // If there are multiple labels, use the last one
6573  this.label = $( labels[ labels.length - 1 ] );
6574  if ( !this.label.length ) {
6575  $.error( "No label found for checkboxradio widget" );
6576  }
6577 
6578  this.originalLabel = "";
6579 
6580  // We need to get the label text but this may also need to make sure it does not contain the
6581  // input itself.
6582  this.label.contents().not( this.element[ 0 ] ).each( function() {
6583 
6584  // The label contents could be text, html, or a mix. We concat each element to get a
6585  // string representation of the label, without the input as part of it.
6586  that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
6587  } );
6588 
6589  // Set the label option if we found label text
6590  if ( this.originalLabel ) {
6591  options.label = this.originalLabel;
6592  }
6593 
6594  disabled = this.element[ 0 ].disabled;
6595  if ( disabled != null ) {
6596  options.disabled = disabled;
6597  }
6598  return options;
6599  },
6600 
6601  _create: function() {
6602  var checked = this.element[ 0 ].checked;
6603 
6604  this._bindFormResetHandler();
6605 
6606  if ( this.options.disabled == null ) {
6607  this.options.disabled = this.element[ 0 ].disabled;
6608  }
6609 
6610  this._setOption( "disabled", this.options.disabled );
6611  this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6612  this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6613 
6614  if ( this.type === "radio" ) {
6615  this._addClass( this.label, "ui-checkboxradio-radio-label" );
6616  }
6617 
6618  if ( this.options.label && this.options.label !== this.originalLabel ) {
6619  this._updateLabel();
6620  } else if ( this.originalLabel ) {
6621  this.options.label = this.originalLabel;
6622  }
6623 
6624  this._enhance();
6625 
6626  if ( checked ) {
6627  this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6628  if ( this.icon ) {
6629  this._addClass( this.icon, null, "ui-state-hover" );
6630  }
6631  }
6632 
6633  this._on( {
6634  change: "_toggleClasses",
6635  focus: function() {
6636  this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6637  },
6638  blur: function() {
6639  this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6640  }
6641  } );
6642  },
6643 
6644  _readType: function() {
6645  var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6646  this.type = this.element[ 0 ].type;
6647  if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6648  $.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6649  " and element.type=" + this.type );
6650  }
6651  },
6652 
6653  // Support jQuery Mobile enhanced option
6654  _enhance: function() {
6655  this._updateIcon( this.element[ 0 ].checked );
6656  },
6657 
6658  widget: function() {
6659  return this.label;
6660  },
6661 
6662  _getRadioGroup: function() {
6663  var group;
6664  var name = this.element[ 0 ].name;
6665  var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']";
6666 
6667  if ( !name ) {
6668  return $( [] );
6669  }
6670 
6671  if ( this.form.length ) {
6672  group = $( this.form[ 0 ].elements ).filter( nameSelector );
6673  } else {
6674 
6675  // Not inside a form, check all inputs that also are not inside a form
6676  group = $( nameSelector ).filter( function() {
6677  return $( this ).form().length === 0;
6678  } );
6679  }
6680 
6681  return group.not( this.element );
6682  },
6683 
6684  _toggleClasses: function() {
6685  var checked = this.element[ 0 ].checked;
6686  this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6687 
6688  if ( this.options.icon && this.type === "checkbox" ) {
6689  this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6690  ._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6691  }
6692 
6693  if ( this.type === "radio" ) {
6694  this._getRadioGroup()
6695  .each( function() {
6696  var instance = $( this ).checkboxradio( "instance" );
6697 
6698  if ( instance ) {
6699  instance._removeClass( instance.label,
6700  "ui-checkboxradio-checked", "ui-state-active" );
6701  }
6702  } );
6703  }
6704  },
6705 
6706  _destroy: function() {
6707  this._unbindFormResetHandler();
6708 
6709  if ( this.icon ) {
6710  this.icon.remove();
6711  this.iconSpace.remove();
6712  }
6713  },
6714 
6715  _setOption: function( key, value ) {
6716 
6717  // We don't allow the value to be set to nothing
6718  if ( key === "label" && !value ) {
6719  return;
6720  }
6721 
6722  this._super( key, value );
6723 
6724  if ( key === "disabled" ) {
6725  this._toggleClass( this.label, null, "ui-state-disabled", value );
6726  this.element[ 0 ].disabled = value;
6727 
6728  // Don't refresh when setting disabled
6729  return;
6730  }
6731  this.refresh();
6732  },
6733 
6734  _updateIcon: function( checked ) {
6735  var toAdd = "ui-icon ui-icon-background ";
6736 
6737  if ( this.options.icon ) {
6738  if ( !this.icon ) {
6739  this.icon = $( "<span>" );
6740  this.iconSpace = $( "<span> </span>" );
6741  this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6742  }
6743 
6744  if ( this.type === "checkbox" ) {
6745  toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6746  this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6747  } else {
6748  toAdd += "ui-icon-blank";
6749  }
6750  this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6751  if ( !checked ) {
6752  this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6753  }
6754  this.icon.prependTo( this.label ).after( this.iconSpace );
6755  } else if ( this.icon !== undefined ) {
6756  this.icon.remove();
6757  this.iconSpace.remove();
6758  delete this.icon;
6759  }
6760  },
6761 
6762  _updateLabel: function() {
6763 
6764  // Remove the contents of the label ( minus the icon, icon space, and input )
6765  var contents = this.label.contents().not( this.element[ 0 ] );
6766  if ( this.icon ) {
6767  contents = contents.not( this.icon[ 0 ] );
6768  }
6769  if ( this.iconSpace ) {
6770  contents = contents.not( this.iconSpace[ 0 ] );
6771  }
6772  contents.remove();
6773 
6774  this.label.append( this.options.label );
6775  },
6776 
6777  refresh: function() {
6778  var checked = this.element[ 0 ].checked,
6779  isDisabled = this.element[ 0 ].disabled;
6780 
6781  this._updateIcon( checked );
6782  this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6783  if ( this.options.label !== null ) {
6784  this._updateLabel();
6785  }
6786 
6787  if ( isDisabled !== this.options.disabled ) {
6788  this._setOptions( { "disabled": isDisabled } );
6789  }
6790  }
6791 
6792 } ] );
6793 
6794 var widgetsCheckboxradio = $.ui.checkboxradio;
6795 
6796 
6806 //>>label: Button
6807 //>>group: Widgets
6808 //>>description: Enhances a form with themeable buttons.
6809 //>>docs: http://api.jqueryui.com/button/
6810 //>>demos: http://jqueryui.com/button/
6811 //>>css.structure: ../../themes/base/core.css
6812 //>>css.structure: ../../themes/base/button.css
6813 //>>css.theme: ../../themes/base/theme.css
6814 
6815 
6816 
6817 $.widget( "ui.button", {
6818  version: "1.12.1",
6819  defaultElement: "<button>",
6820  options: {
6821  classes: {
6822  "ui-button": "ui-corner-all"
6823  },
6824  disabled: null,
6825  icon: null,
6826  iconPosition: "beginning",
6827  label: null,
6828  showLabel: true
6829  },
6830 
6831  _getCreateOptions: function() {
6832  var disabled,
6833 
6834  // This is to support cases like in jQuery Mobile where the base widget does have
6835  // an implementation of _getCreateOptions
6836  options = this._super() || {};
6837 
6838  this.isInput = this.element.is( "input" );
6839 
6840  disabled = this.element[ 0 ].disabled;
6841  if ( disabled != null ) {
6842  options.disabled = disabled;
6843  }
6844 
6845  this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6846  if ( this.originalLabel ) {
6847  options.label = this.originalLabel;
6848  }
6849 
6850  return options;
6851  },
6852 
6853  _create: function() {
6854  if ( !this.option.showLabel & !this.options.icon ) {
6855  this.options.showLabel = true;
6856  }
6857 
6858  // We have to check the option again here even though we did in _getCreateOptions,
6859  // because null may have been passed on init which would override what was set in
6860  // _getCreateOptions
6861  if ( this.options.disabled == null ) {
6862  this.options.disabled = this.element[ 0 ].disabled || false;
6863  }
6864 
6865  this.hasTitle = !!this.element.attr( "title" );
6866 
6867  // Check to see if the label needs to be set or if its already correct
6868  if ( this.options.label && this.options.label !== this.originalLabel ) {
6869  if ( this.isInput ) {
6870  this.element.val( this.options.label );
6871  } else {
6872  this.element.html( this.options.label );
6873  }
6874  }
6875  this._addClass( "ui-button", "ui-widget" );
6876  this._setOption( "disabled", this.options.disabled );
6877  this._enhance();
6878 
6879  if ( this.element.is( "a" ) ) {
6880  this._on( {
6881  "keyup": function( event ) {
6882  if ( event.keyCode === $.ui.keyCode.SPACE ) {
6883  event.preventDefault();
6884 
6885  // Support: PhantomJS <= 1.9, IE 8 Only
6886  // If a native click is available use it so we actually cause navigation
6887  // otherwise just trigger a click event
6888  if ( this.element[ 0 ].click ) {
6889  this.element[ 0 ].click();
6890  } else {
6891  this.element.trigger( "click" );
6892  }
6893  }
6894  }
6895  } );
6896  }
6897  },
6898 
6899  _enhance: function() {
6900  if ( !this.element.is( "button" ) ) {
6901  this.element.attr( "role", "button" );
6902  }
6903 
6904  if ( this.options.icon ) {
6905  this._updateIcon( "icon", this.options.icon );
6906  this._updateTooltip();
6907  }
6908  },
6909 
6910  _updateTooltip: function() {
6911  this.title = this.element.attr( "title" );
6912 
6913  if ( !this.options.showLabel && !this.title ) {
6914  this.element.attr( "title", this.options.label );
6915  }
6916  },
6917 
6918  _updateIcon: function( option, value ) {
6919  var icon = option !== "iconPosition",
6920  position = icon ? this.options.iconPosition : value,
6921  displayBlock = position === "top" || position === "bottom";
6922 
6923  // Create icon
6924  if ( !this.icon ) {
6925  this.icon = $( "<span>" );
6926 
6927  this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6928 
6929  if ( !this.options.showLabel ) {
6930  this._addClass( "ui-button-icon-only" );
6931  }
6932  } else if ( icon ) {
6933 
6934  // If we are updating the icon remove the old icon class
6935  this._removeClass( this.icon, null, this.options.icon );
6936  }
6937 
6938  // If we are updating the icon add the new icon class
6939  if ( icon ) {
6940  this._addClass( this.icon, null, value );
6941  }
6942 
6943  this._attachIcon( position );
6944 
6945  // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
6946  // the iconSpace if there is one.
6947  if ( displayBlock ) {
6948  this._addClass( this.icon, null, "ui-widget-icon-block" );
6949  if ( this.iconSpace ) {
6950  this.iconSpace.remove();
6951  }
6952  } else {
6953 
6954  // Position is beginning or end so remove the ui-widget-icon-block class and add the
6955  // space if it does not exist
6956  if ( !this.iconSpace ) {
6957  this.iconSpace = $( "<span> </span>" );
6958  this._addClass( this.iconSpace, "ui-button-icon-space" );
6959  }
6960  this._removeClass( this.icon, null, "ui-wiget-icon-block" );
6961  this._attachIconSpace( position );
6962  }
6963  },
6964 
6965  _destroy: function() {
6966  this.element.removeAttr( "role" );
6967 
6968  if ( this.icon ) {
6969  this.icon.remove();
6970  }
6971  if ( this.iconSpace ) {
6972  this.iconSpace.remove();
6973  }
6974  if ( !this.hasTitle ) {
6975  this.element.removeAttr( "title" );
6976  }
6977  },
6978 
6979  _attachIconSpace: function( iconPosition ) {
6980  this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
6981  },
6982 
6983  _attachIcon: function( iconPosition ) {
6984  this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
6985  },
6986 
6987  _setOptions: function( options ) {
6988  var newShowLabel = options.showLabel === undefined ?
6989  this.options.showLabel :
6990  options.showLabel,
6991  newIcon = options.icon === undefined ? this.options.icon : options.icon;
6992 
6993  if ( !newShowLabel && !newIcon ) {
6994  options.showLabel = true;
6995  }
6996  this._super( options );
6997  },
6998 
6999  _setOption: function( key, value ) {
7000  if ( key === "icon" ) {
7001  if ( value ) {
7002  this._updateIcon( key, value );
7003  } else if ( this.icon ) {
7004  this.icon.remove();
7005  if ( this.iconSpace ) {
7006  this.iconSpace.remove();
7007  }
7008  }
7009  }
7010 
7011  if ( key === "iconPosition" ) {
7012  this._updateIcon( key, value );
7013  }
7014 
7015  // Make sure we can't end up with a button that has neither text nor icon
7016  if ( key === "showLabel" ) {
7017  this._toggleClass( "ui-button-icon-only", null, !value );
7018  this._updateTooltip();
7019  }
7020 
7021  if ( key === "label" ) {
7022  if ( this.isInput ) {
7023  this.element.val( value );
7024  } else {
7025 
7026  // If there is an icon, append it, else nothing then append the value
7027  // this avoids removal of the icon when setting label text
7028  this.element.html( value );
7029  if ( this.icon ) {
7030  this._attachIcon( this.options.iconPosition );
7031  this._attachIconSpace( this.options.iconPosition );
7032  }
7033  }
7034  }
7035 
7036  this._super( key, value );
7037 
7038  if ( key === "disabled" ) {
7039  this._toggleClass( null, "ui-state-disabled", value );
7040  this.element[ 0 ].disabled = value;
7041  if ( value ) {
7042  this.element.blur();
7043  }
7044  }
7045  },
7046 
7047  refresh: function() {
7048 
7049  // Make sure to only check disabled if its an element that supports this otherwise
7050  // check for the disabled class to determine state
7051  var isDisabled = this.element.is( "input, button" ) ?
7052  this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
7053 
7054  if ( isDisabled !== this.options.disabled ) {
7055  this._setOptions( { disabled: isDisabled } );
7056  }
7057 
7058  this._updateTooltip();
7059  }
7060 } );
7061 
7062 // DEPRECATED
7063 if ( $.uiBackCompat !== false ) {
7064 
7065  // Text and Icons options
7066  $.widget( "ui.button", $.ui.button, {
7067  options: {
7068  text: true,
7069  icons: {
7070  primary: null,
7071  secondary: null
7072  }
7073  },
7074 
7075  _create: function() {
7076  if ( this.options.showLabel && !this.options.text ) {
7077  this.options.showLabel = this.options.text;
7078  }
7079  if ( !this.options.showLabel && this.options.text ) {
7080  this.options.text = this.options.showLabel;
7081  }
7082  if ( !this.options.icon && ( this.options.icons.primary ||
7083  this.options.icons.secondary ) ) {
7084  if ( this.options.icons.primary ) {
7085  this.options.icon = this.options.icons.primary;
7086  } else {
7087  this.options.icon = this.options.icons.secondary;
7088  this.options.iconPosition = "end";
7089  }
7090  } else if ( this.options.icon ) {
7091  this.options.icons.primary = this.options.icon;
7092  }
7093  this._super();
7094  },
7095 
7096  _setOption: function( key, value ) {
7097  if ( key === "text" ) {
7098  this._super( "showLabel", value );
7099  return;
7100  }
7101  if ( key === "showLabel" ) {
7102  this.options.text = value;
7103  }
7104  if ( key === "icon" ) {
7105  this.options.icons.primary = value;
7106  }
7107  if ( key === "icons" ) {
7108  if ( value.primary ) {
7109  this._super( "icon", value.primary );
7110  this._super( "iconPosition", "beginning" );
7111  } else if ( value.secondary ) {
7112  this._super( "icon", value.secondary );
7113  this._super( "iconPosition", "end" );
7114  }
7115  }
7116  this._superApply( arguments );
7117  }
7118  } );
7119 
7120  $.fn.button = ( function( orig ) {
7121  return function() {
7122  if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) ||
7123  ( this.length && this[ 0 ].tagName === "INPUT" && (
7124  this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio"
7125  ) ) ) {
7126  return orig.apply( this, arguments );
7127  }
7128  if ( !$.ui.checkboxradio ) {
7129  $.error( "Checkboxradio widget missing" );
7130  }
7131  if ( arguments.length === 0 ) {
7132  return this.checkboxradio( {
7133  "icon": false
7134  } );
7135  }
7136  return this.checkboxradio.apply( this, arguments );
7137  };
7138  } )( $.fn.button );
7139 
7140  $.fn.buttonset = function() {
7141  if ( !$.ui.controlgroup ) {
7142  $.error( "Controlgroup widget missing" );
7143  }
7144  if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7145  return this.controlgroup.apply( this,
7146  [ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7147  }
7148  if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7149  return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7150  }
7151  if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7152  arguments[ 0 ].items = {
7153  button: arguments[ 0 ].items
7154  };
7155  }
7156  return this.controlgroup.apply( this, arguments );
7157  };
7158 }
7159 
7160 var widgetsButton = $.ui.button;
7161 
7162 
7163 // jscs:disable maximumLineLength
7164 /* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
7174 //>>label: Datepicker
7175 //>>group: Widgets
7176 //>>description: Displays a calendar from an input or inline for selecting dates.
7177 //>>docs: http://api.jqueryui.com/datepicker/
7178 //>>demos: http://jqueryui.com/datepicker/
7179 //>>css.structure: ../../themes/base/core.css
7180 //>>css.structure: ../../themes/base/datepicker.css
7181 //>>css.theme: ../../themes/base/theme.css
7182 
7183 
7184 
7185 $.extend( $.ui, { datepicker: { version: "1.12.1" } } );
7186 
7187 var datepicker_instActive;
7188 
7189 function datepicker_getZindex( elem ) {
7190  var position, value;
7191  while ( elem.length && elem[ 0 ] !== document ) {
7192 
7193  // Ignore z-index if position is set to a value where z-index is ignored by the browser
7194  // This makes behavior of this function consistent across browsers
7195  // WebKit always returns auto if the element is positioned
7196  position = elem.css( "position" );
7197  if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7198 
7199  // IE returns 0 when zIndex is not specified
7200  // other browsers return a string
7201  // we ignore the case of nested elements with an explicit value of 0
7202  // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7203  value = parseInt( elem.css( "zIndex" ), 10 );
7204  if ( !isNaN( value ) && value !== 0 ) {
7205  return value;
7206  }
7207  }
7208  elem = elem.parent();
7209  }
7210 
7211  return 0;
7212 }
7213 /* Date picker manager.
7214  Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7215  Settings for (groups of) date pickers are maintained in an instance object,
7216  allowing multiple different settings on the same page. */
7217 
7218 function Datepicker() {
7219  this._curInst = null; // The current instance in use
7220  this._keyEvent = false; // If the last event was a key event
7221  this._disabledInputs = []; // List of date picker inputs that have been disabled
7222  this._datepickerShowing = false; // True if the popup picker is showing , false if not
7223  this._inDialog = false; // True if showing within a "dialog", false if not
7224  this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7225  this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7226  this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7227  this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7228  this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7229  this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7230  this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7231  this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7232  this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7233  this.regional = []; // Available regional settings, indexed by language code
7234  this.regional[ "" ] = { // Default regional settings
7235  closeText: "Done", // Display text for close link
7236  prevText: "Prev", // Display text for previous month link
7237  nextText: "Next", // Display text for next month link
7238  currentText: "Today", // Display text for current month link
7239  monthNames: [ "January","February","March","April","May","June",
7240  "July","August","September","October","November","December" ], // Names of months for drop-down and formatting
7241  monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7242  dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7243  dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7244  dayNamesMin: [ "Su","Mo","Tu","We","Th","Fr","Sa" ], // Column headings for days starting at Sunday
7245  weekHeader: "Wk", // Column header for week of the year
7246  dateFormat: "mm/dd/yy", // See format options on parseDate
7247  firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7248  isRTL: false, // True if right-to-left language, false if left-to-right
7249  showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7250  yearSuffix: "" // Additional text to append to the year in the month headers
7251  };
7252  this._defaults = { // Global defaults for all the date picker instances
7253  showOn: "focus", // "focus" for popup on focus,
7254  // "button" for trigger button, or "both" for either
7255  showAnim: "fadeIn", // Name of jQuery animation for popup
7256  showOptions: {}, // Options for enhanced animations
7257  defaultDate: null, // Used when field is blank: actual date,
7258  // +/-number for offset from today, null for today
7259  appendText: "", // Display text following the input box, e.g. showing the format
7260  buttonText: "...", // Text for trigger button
7261  buttonImage: "", // URL for trigger button image
7262  buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7263  hideIfNoPrevNext: false, // True to hide next/previous month links
7264  // if not applicable, false to just disable them
7265  navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7266  gotoCurrent: false, // True if today link goes back to current selection instead
7267  changeMonth: false, // True if month can be selected directly, false if only prev/next
7268  changeYear: false, // True if year can be selected directly, false if only prev/next
7269  yearRange: "c-10:c+10", // Range of years to display in drop-down,
7270  // either relative to today's year (-nn:+nn), relative to currently displayed year
7271  // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7272  showOtherMonths: false, // True to show dates in other months, false to leave blank
7273  selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7274  showWeek: false, // True to show week of the year, false to not show it
7275  calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7276  // takes a Date and returns the number of the week for it
7277  shortYearCutoff: "+10", // Short year values < this are in the current century,
7278  // > this are in the previous century,
7279  // string value starting with "+" for current year + value
7280  minDate: null, // The earliest selectable date, or null for no limit
7281  maxDate: null, // The latest selectable date, or null for no limit
7282  duration: "fast", // Duration of display/closure
7283  beforeShowDay: null, // Function that takes a date and returns an array with
7284  // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7285  // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7286  beforeShow: null, // Function that takes an input field and
7287  // returns a set of custom settings for the date picker
7288  onSelect: null, // Define a callback function when a date is selected
7289  onChangeMonthYear: null, // Define a callback function when the month or year is changed
7290  onClose: null, // Define a callback function when the datepicker is closed
7291  numberOfMonths: 1, // Number of months to show at a time
7292  showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7293  stepMonths: 1, // Number of months to step back/forward
7294  stepBigMonths: 12, // Number of months to step back/forward for the big links
7295  altField: "", // Selector for an alternate field to store selected dates into
7296  altFormat: "", // The date format to use for the alternate field
7297  constrainInput: true, // The input is constrained by the current date format
7298  showButtonPanel: false, // True to show button panel, false to not show it
7299  autoSize: false, // True to size the input for the date format, false to leave as is
7300  disabled: false // The initial disabled state
7301  };
7302  $.extend( this._defaults, this.regional[ "" ] );
7303  this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7304  this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7305  this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7306 }
7307 
7308 $.extend( Datepicker.prototype, {
7309  /* Class name added to elements to indicate already configured with a date picker. */
7310  markerClassName: "hasDatepicker",
7311 
7312  //Keep track of the maximum number of rows displayed (see #7043)
7313  maxRows: 4,
7314 
7315  // TODO rename to "widget" when switching to widget factory
7316  _widgetDatepicker: function() {
7317  return this.dpDiv;
7318  },
7319 
7320  /* Override the default settings for all instances of the date picker.
7321  * @param settings object - the new settings to use as defaults (anonymous object)
7322  * @return the manager object
7323  */
7324  setDefaults: function( settings ) {
7325  datepicker_extendRemove( this._defaults, settings || {} );
7326  return this;
7327  },
7328 
7329  /* Attach the date picker to a jQuery selection.
7330  * @param target element - the target input field or division or span
7331  * @param settings object - the new settings to use for this date picker instance (anonymous)
7332  */
7333  _attachDatepicker: function( target, settings ) {
7334  var nodeName, inline, inst;
7335  nodeName = target.nodeName.toLowerCase();
7336  inline = ( nodeName === "div" || nodeName === "span" );
7337  if ( !target.id ) {
7338  this.uuid += 1;
7339  target.id = "dp" + this.uuid;
7340  }
7341  inst = this._newInst( $( target ), inline );
7342  inst.settings = $.extend( {}, settings || {} );
7343  if ( nodeName === "input" ) {
7344  this._connectDatepicker( target, inst );
7345  } else if ( inline ) {
7346  this._inlineDatepicker( target, inst );
7347  }
7348  },
7349 
7350  /* Create a new instance object. */
7351  _newInst: function( target, inline ) {
7352  var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7353  return { id: id, input: target, // associated target
7354  selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7355  drawMonth: 0, drawYear: 0, // month being drawn
7356  inline: inline, // is datepicker inline or not
7357  dpDiv: ( !inline ? this.dpDiv : // presentation div
7358  datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7359  },
7360 
7361  /* Attach the date picker to an input field. */
7362  _connectDatepicker: function( target, inst ) {
7363  var input = $( target );
7364  inst.append = $( [] );
7365  inst.trigger = $( [] );
7366  if ( input.hasClass( this.markerClassName ) ) {
7367  return;
7368  }
7369  this._attachments( input, inst );
7370  input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7371  on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7372  this._autoSize( inst );
7373  $.data( target, "datepicker", inst );
7374 
7375  //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7376  if ( inst.settings.disabled ) {
7377  this._disableDatepicker( target );
7378  }
7379  },
7380 
7381  /* Make attachments based on settings. */
7382  _attachments: function( input, inst ) {
7383  var showOn, buttonText, buttonImage,
7384  appendText = this._get( inst, "appendText" ),
7385  isRTL = this._get( inst, "isRTL" );
7386 
7387  if ( inst.append ) {
7388  inst.append.remove();
7389  }
7390  if ( appendText ) {
7391  inst.append = $( "<span class='" + this._appendClass + "'>" + appendText + "</span>" );
7392  input[ isRTL ? "before" : "after" ]( inst.append );
7393  }
7394 
7395  input.off( "focus", this._showDatepicker );
7396 
7397  if ( inst.trigger ) {
7398  inst.trigger.remove();
7399  }
7400 
7401  showOn = this._get( inst, "showOn" );
7402  if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7403  input.on( "focus", this._showDatepicker );
7404  }
7405  if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7406  buttonText = this._get( inst, "buttonText" );
7407  buttonImage = this._get( inst, "buttonImage" );
7408  inst.trigger = $( this._get( inst, "buttonImageOnly" ) ?
7409  $( "<img/>" ).addClass( this._triggerClass ).
7410  attr( { src: buttonImage, alt: buttonText, title: buttonText } ) :
7411  $( "<button type='button'></button>" ).addClass( this._triggerClass ).
7412  html( !buttonImage ? buttonText : $( "<img/>" ).attr(
7413  { src:buttonImage, alt:buttonText, title:buttonText } ) ) );
7414  input[ isRTL ? "before" : "after" ]( inst.trigger );
7415  inst.trigger.on( "click", function() {
7416  if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7417  $.datepicker._hideDatepicker();
7418  } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7419  $.datepicker._hideDatepicker();
7420  $.datepicker._showDatepicker( input[ 0 ] );
7421  } else {
7422  $.datepicker._showDatepicker( input[ 0 ] );
7423  }
7424  return false;
7425  } );
7426  }
7427  },
7428 
7429  /* Apply the maximum length for the date format. */
7430  _autoSize: function( inst ) {
7431  if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7432  var findMax, max, maxI, i,
7433  date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7434  dateFormat = this._get( inst, "dateFormat" );
7435 
7436  if ( dateFormat.match( /[DM]/ ) ) {
7437  findMax = function( names ) {
7438  max = 0;
7439  maxI = 0;
7440  for ( i = 0; i < names.length; i++ ) {
7441  if ( names[ i ].length > max ) {
7442  max = names[ i ].length;
7443  maxI = i;
7444  }
7445  }
7446  return maxI;
7447  };
7448  date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7449  "monthNames" : "monthNamesShort" ) ) ) );
7450  date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7451  "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7452  }
7453  inst.input.attr( "size", this._formatDate( inst, date ).length );
7454  }
7455  },
7456 
7457  /* Attach an inline date picker to a div. */
7458  _inlineDatepicker: function( target, inst ) {
7459  var divSpan = $( target );
7460  if ( divSpan.hasClass( this.markerClassName ) ) {
7461  return;
7462  }
7463  divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7464  $.data( target, "datepicker", inst );
7465  this._setDate( inst, this._getDefaultDate( inst ), true );
7466  this._updateDatepicker( inst );
7467  this._updateAlternate( inst );
7468 
7469  //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7470  if ( inst.settings.disabled ) {
7471  this._disableDatepicker( target );
7472  }
7473 
7474  // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7475  // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7476  inst.dpDiv.css( "display", "block" );
7477  },
7478 
7479  /* Pop-up the date picker in a "dialog" box.
7480  * @param input element - ignored
7481  * @param date string or Date - the initial date to display
7482  * @param onSelect function - the function to call when a date is selected
7483  * @param settings object - update the dialog date picker instance's settings (anonymous object)
7484  * @param pos int[2] - coordinates for the dialog's position within the screen or
7485  * event - with x/y coordinates or
7486  * leave empty for default (screen centre)
7487  * @return the manager object
7488  */
7489  _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7490  var id, browserWidth, browserHeight, scrollX, scrollY,
7491  inst = this._dialogInst; // internal instance
7492 
7493  if ( !inst ) {
7494  this.uuid += 1;
7495  id = "dp" + this.uuid;
7496  this._dialogInput = $( "<input type='text' id='" + id +
7497  "' style='position: absolute; top: -100px; width: 0px;'/>" );
7498  this._dialogInput.on( "keydown", this._doKeyDown );
7499  $( "body" ).append( this._dialogInput );
7500  inst = this._dialogInst = this._newInst( this._dialogInput, false );
7501  inst.settings = {};
7502  $.data( this._dialogInput[ 0 ], "datepicker", inst );
7503  }
7504  datepicker_extendRemove( inst.settings, settings || {} );
7505  date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7506  this._dialogInput.val( date );
7507 
7508  this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7509  if ( !this._pos ) {
7510  browserWidth = document.documentElement.clientWidth;
7511  browserHeight = document.documentElement.clientHeight;
7512  scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7513  scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7514  this._pos = // should use actual width/height below
7515  [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7516  }
7517 
7518  // Move input on screen for focus, but hidden behind dialog
7519  this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7520  inst.settings.onSelect = onSelect;
7521  this._inDialog = true;
7522  this.dpDiv.addClass( this._dialogClass );
7523  this._showDatepicker( this._dialogInput[ 0 ] );
7524  if ( $.blockUI ) {
7525  $.blockUI( this.dpDiv );
7526  }
7527  $.data( this._dialogInput[ 0 ], "datepicker", inst );
7528  return this;
7529  },
7530 
7531  /* Detach a datepicker from its control.
7532  * @param target element - the target input field or division or span
7533  */
7534  _destroyDatepicker: function( target ) {
7535  var nodeName,
7536  $target = $( target ),
7537  inst = $.data( target, "datepicker" );
7538 
7539  if ( !$target.hasClass( this.markerClassName ) ) {
7540  return;
7541  }
7542 
7543  nodeName = target.nodeName.toLowerCase();
7544  $.removeData( target, "datepicker" );
7545  if ( nodeName === "input" ) {
7546  inst.append.remove();
7547  inst.trigger.remove();
7548  $target.removeClass( this.markerClassName ).
7549  off( "focus", this._showDatepicker ).
7550  off( "keydown", this._doKeyDown ).
7551  off( "keypress", this._doKeyPress ).
7552  off( "keyup", this._doKeyUp );
7553  } else if ( nodeName === "div" || nodeName === "span" ) {
7554  $target.removeClass( this.markerClassName ).empty();
7555  }
7556 
7557  if ( datepicker_instActive === inst ) {
7558  datepicker_instActive = null;
7559  }
7560  },
7561 
7562  /* Enable the date picker to a jQuery selection.
7563  * @param target element - the target input field or division or span
7564  */
7565  _enableDatepicker: function( target ) {
7566  var nodeName, inline,
7567  $target = $( target ),
7568  inst = $.data( target, "datepicker" );
7569 
7570  if ( !$target.hasClass( this.markerClassName ) ) {
7571  return;
7572  }
7573 
7574  nodeName = target.nodeName.toLowerCase();
7575  if ( nodeName === "input" ) {
7576  target.disabled = false;
7577  inst.trigger.filter( "button" ).
7578  each( function() { this.disabled = false; } ).end().
7579  filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7580  } else if ( nodeName === "div" || nodeName === "span" ) {
7581  inline = $target.children( "." + this._inlineClass );
7582  inline.children().removeClass( "ui-state-disabled" );
7583  inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7584  prop( "disabled", false );
7585  }
7586  this._disabledInputs = $.map( this._disabledInputs,
7587  function( value ) { return ( value === target ? null : value ); } ); // delete entry
7588  },
7589 
7590  /* Disable the date picker to a jQuery selection.
7591  * @param target element - the target input field or division or span
7592  */
7593  _disableDatepicker: function( target ) {
7594  var nodeName, inline,
7595  $target = $( target ),
7596  inst = $.data( target, "datepicker" );
7597 
7598  if ( !$target.hasClass( this.markerClassName ) ) {
7599  return;
7600  }
7601 
7602  nodeName = target.nodeName.toLowerCase();
7603  if ( nodeName === "input" ) {
7604  target.disabled = true;
7605  inst.trigger.filter( "button" ).
7606  each( function() { this.disabled = true; } ).end().
7607  filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7608  } else if ( nodeName === "div" || nodeName === "span" ) {
7609  inline = $target.children( "." + this._inlineClass );
7610  inline.children().addClass( "ui-state-disabled" );
7611  inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7612  prop( "disabled", true );
7613  }
7614  this._disabledInputs = $.map( this._disabledInputs,
7615  function( value ) { return ( value === target ? null : value ); } ); // delete entry
7616  this._disabledInputs[ this._disabledInputs.length ] = target;
7617  },
7618 
7619  /* Is the first field in a jQuery collection disabled as a datepicker?
7620  * @param target element - the target input field or division or span
7621  * @return boolean - true if disabled, false if enabled
7622  */
7623  _isDisabledDatepicker: function( target ) {
7624  if ( !target ) {
7625  return false;
7626  }
7627  for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7628  if ( this._disabledInputs[ i ] === target ) {
7629  return true;
7630  }
7631  }
7632  return false;
7633  },
7634 
7635  /* Retrieve the instance data for the target control.
7636  * @param target element - the target input field or division or span
7637  * @return object - the associated instance data
7638  * @throws error if a jQuery problem getting data
7639  */
7640  _getInst: function( target ) {
7641  try {
7642  return $.data( target, "datepicker" );
7643  }
7644  catch ( err ) {
7645  throw "Missing instance data for this datepicker";
7646  }
7647  },
7648 
7649  /* Update or retrieve the settings for a date picker attached to an input field or division.
7650  * @param target element - the target input field or division or span
7651  * @param name object - the new settings to update or
7652  * string - the name of the setting to change or retrieve,
7653  * when retrieving also "all" for all instance settings or
7654  * "defaults" for all global defaults
7655  * @param value any - the new value for the setting
7656  * (omit if above is an object or to retrieve a value)
7657  */
7658  _optionDatepicker: function( target, name, value ) {
7659  var settings, date, minDate, maxDate,
7660  inst = this._getInst( target );
7661 
7662  if ( arguments.length === 2 && typeof name === "string" ) {
7663  return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7664  ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7665  this._get( inst, name ) ) : null ) );
7666  }
7667 
7668  settings = name || {};
7669  if ( typeof name === "string" ) {
7670  settings = {};
7671  settings[ name ] = value;
7672  }
7673 
7674  if ( inst ) {
7675  if ( this._curInst === inst ) {
7676  this._hideDatepicker();
7677  }
7678 
7679  date = this._getDateDatepicker( target, true );
7680  minDate = this._getMinMaxDate( inst, "min" );
7681  maxDate = this._getMinMaxDate( inst, "max" );
7682  datepicker_extendRemove( inst.settings, settings );
7683 
7684  // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7685  if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7686  inst.settings.minDate = this._formatDate( inst, minDate );
7687  }
7688  if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7689  inst.settings.maxDate = this._formatDate( inst, maxDate );
7690  }
7691  if ( "disabled" in settings ) {
7692  if ( settings.disabled ) {
7693  this._disableDatepicker( target );
7694  } else {
7695  this._enableDatepicker( target );
7696  }
7697  }
7698  this._attachments( $( target ), inst );
7699  this._autoSize( inst );
7700  this._setDate( inst, date );
7701  this._updateAlternate( inst );
7702  this._updateDatepicker( inst );
7703  }
7704  },
7705 
7706  // Change method deprecated
7707  _changeDatepicker: function( target, name, value ) {
7708  this._optionDatepicker( target, name, value );
7709  },
7710 
7711  /* Redraw the date picker attached to an input field or division.
7712  * @param target element - the target input field or division or span
7713  */
7714  _refreshDatepicker: function( target ) {
7715  var inst = this._getInst( target );
7716  if ( inst ) {
7717  this._updateDatepicker( inst );
7718  }
7719  },
7720 
7721  /* Set the dates for a jQuery selection.
7722  * @param target element - the target input field or division or span
7723  * @param date Date - the new date
7724  */
7725  _setDateDatepicker: function( target, date ) {
7726  var inst = this._getInst( target );
7727  if ( inst ) {
7728  this._setDate( inst, date );
7729  this._updateDatepicker( inst );
7730  this._updateAlternate( inst );
7731  }
7732  },
7733 
7734  /* Get the date(s) for the first entry in a jQuery selection.
7735  * @param target element - the target input field or division or span
7736  * @param noDefault boolean - true if no default date is to be used
7737  * @return Date - the current date
7738  */
7739  _getDateDatepicker: function( target, noDefault ) {
7740  var inst = this._getInst( target );
7741  if ( inst && !inst.inline ) {
7742  this._setDateFromField( inst, noDefault );
7743  }
7744  return ( inst ? this._getDate( inst ) : null );
7745  },
7746 
7747  /* Handle keystrokes. */
7748  _doKeyDown: function( event ) {
7749  var onSelect, dateStr, sel,
7750  inst = $.datepicker._getInst( event.target ),
7751  handled = true,
7752  isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7753 
7754  inst._keyEvent = true;
7755  if ( $.datepicker._datepickerShowing ) {
7756  switch ( event.keyCode ) {
7757  case 9: $.datepicker._hideDatepicker();
7758  handled = false;
7759  break; // hide on tab out
7760  case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7761  $.datepicker._currentClass + ")", inst.dpDiv );
7762  if ( sel[ 0 ] ) {
7763  $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7764  }
7765 
7766  onSelect = $.datepicker._get( inst, "onSelect" );
7767  if ( onSelect ) {
7768  dateStr = $.datepicker._formatDate( inst );
7769 
7770  // Trigger custom callback
7771  onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7772  } else {
7773  $.datepicker._hideDatepicker();
7774  }
7775 
7776  return false; // don't submit the form
7777  case 27: $.datepicker._hideDatepicker();
7778  break; // hide on escape
7779  case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7780  -$.datepicker._get( inst, "stepBigMonths" ) :
7781  -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7782  break; // previous month/year on page up/+ ctrl
7783  case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7784  +$.datepicker._get( inst, "stepBigMonths" ) :
7785  +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7786  break; // next month/year on page down/+ ctrl
7787  case 35: if ( event.ctrlKey || event.metaKey ) {
7788  $.datepicker._clearDate( event.target );
7789  }
7790  handled = event.ctrlKey || event.metaKey;
7791  break; // clear on ctrl or command +end
7792  case 36: if ( event.ctrlKey || event.metaKey ) {
7793  $.datepicker._gotoToday( event.target );
7794  }
7795  handled = event.ctrlKey || event.metaKey;
7796  break; // current on ctrl or command +home
7797  case 37: if ( event.ctrlKey || event.metaKey ) {
7798  $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7799  }
7800  handled = event.ctrlKey || event.metaKey;
7801 
7802  // -1 day on ctrl or command +left
7803  if ( event.originalEvent.altKey ) {
7804  $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7805  -$.datepicker._get( inst, "stepBigMonths" ) :
7806  -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7807  }
7808 
7809  // next month/year on alt +left on Mac
7810  break;
7811  case 38: if ( event.ctrlKey || event.metaKey ) {
7812  $.datepicker._adjustDate( event.target, -7, "D" );
7813  }
7814  handled = event.ctrlKey || event.metaKey;
7815  break; // -1 week on ctrl or command +up
7816  case 39: if ( event.ctrlKey || event.metaKey ) {
7817  $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7818  }
7819  handled = event.ctrlKey || event.metaKey;
7820 
7821  // +1 day on ctrl or command +right
7822  if ( event.originalEvent.altKey ) {
7823  $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7824  +$.datepicker._get( inst, "stepBigMonths" ) :
7825  +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7826  }
7827 
7828  // next month/year on alt +right
7829  break;
7830  case 40: if ( event.ctrlKey || event.metaKey ) {
7831  $.datepicker._adjustDate( event.target, +7, "D" );
7832  }
7833  handled = event.ctrlKey || event.metaKey;
7834  break; // +1 week on ctrl or command +down
7835  default: handled = false;
7836  }
7837  } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
7838  $.datepicker._showDatepicker( this );
7839  } else {
7840  handled = false;
7841  }
7842 
7843  if ( handled ) {
7844  event.preventDefault();
7845  event.stopPropagation();
7846  }
7847  },
7848 
7849  /* Filter entered characters - based on date format. */
7850  _doKeyPress: function( event ) {
7851  var chars, chr,
7852  inst = $.datepicker._getInst( event.target );
7853 
7854  if ( $.datepicker._get( inst, "constrainInput" ) ) {
7855  chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
7856  chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
7857  return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
7858  }
7859  },
7860 
7861  /* Synchronise manual entry and field/alternate field. */
7862  _doKeyUp: function( event ) {
7863  var date,
7864  inst = $.datepicker._getInst( event.target );
7865 
7866  if ( inst.input.val() !== inst.lastVal ) {
7867  try {
7868  date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
7869  ( inst.input ? inst.input.val() : null ),
7870  $.datepicker._getFormatConfig( inst ) );
7871 
7872  if ( date ) { // only if valid
7873  $.datepicker._setDateFromField( inst );
7874  $.datepicker._updateAlternate( inst );
7875  $.datepicker._updateDatepicker( inst );
7876  }
7877  }
7878  catch ( err ) {
7879  }
7880  }
7881  return true;
7882  },
7883 
7884  /* Pop-up the date picker for a given input field.
7885  * If false returned from beforeShow event handler do not show.
7886  * @param input element - the input field attached to the date picker or
7887  * event - if triggered by focus
7888  */
7889  _showDatepicker: function( input ) {
7890  input = input.target || input;
7891  if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
7892  input = $( "input", input.parentNode )[ 0 ];
7893  }
7894 
7895  if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
7896  return;
7897  }
7898 
7899  var inst, beforeShow, beforeShowSettings, isFixed,
7900  offset, showAnim, duration;
7901 
7902  inst = $.datepicker._getInst( input );
7903  if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
7904  $.datepicker._curInst.dpDiv.stop( true, true );
7905  if ( inst && $.datepicker._datepickerShowing ) {
7906  $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
7907  }
7908  }
7909 
7910  beforeShow = $.datepicker._get( inst, "beforeShow" );
7911  beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
7912  if ( beforeShowSettings === false ) {
7913  return;
7914  }
7915  datepicker_extendRemove( inst.settings, beforeShowSettings );
7916 
7917  inst.lastVal = null;
7918  $.datepicker._lastInput = input;
7919  $.datepicker._setDateFromField( inst );
7920 
7921  if ( $.datepicker._inDialog ) { // hide cursor
7922  input.value = "";
7923  }
7924  if ( !$.datepicker._pos ) { // position below input
7925  $.datepicker._pos = $.datepicker._findPos( input );
7926  $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
7927  }
7928 
7929  isFixed = false;
7930  $( input ).parents().each( function() {
7931  isFixed |= $( this ).css( "position" ) === "fixed";
7932  return !isFixed;
7933  } );
7934 
7935  offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
7936  $.datepicker._pos = null;
7937 
7938  //to avoid flashes on Firefox
7939  inst.dpDiv.empty();
7940 
7941  // determine sizing offscreen
7942  inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
7943  $.datepicker._updateDatepicker( inst );
7944 
7945  // fix width for dynamic number of date pickers
7946  // and adjust position before showing
7947  offset = $.datepicker._checkOffset( inst, offset, isFixed );
7948  inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
7949  "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
7950  left: offset.left + "px", top: offset.top + "px" } );
7951 
7952  if ( !inst.inline ) {
7953  showAnim = $.datepicker._get( inst, "showAnim" );
7954  duration = $.datepicker._get( inst, "duration" );
7955  inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
7956  $.datepicker._datepickerShowing = true;
7957 
7958  if ( $.effects && $.effects.effect[ showAnim ] ) {
7959  inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
7960  } else {
7961  inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
7962  }
7963 
7964  if ( $.datepicker._shouldFocusInput( inst ) ) {
7965  inst.input.trigger( "focus" );
7966  }
7967 
7968  $.datepicker._curInst = inst;
7969  }
7970  },
7971 
7972  /* Generate the date picker content. */
7973  _updateDatepicker: function( inst ) {
7974  this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7975  datepicker_instActive = inst; // for delegate hover events
7976  inst.dpDiv.empty().append( this._generateHTML( inst ) );
7977  this._attachHandlers( inst );
7978 
7979  var origyearshtml,
7980  numMonths = this._getNumberOfMonths( inst ),
7981  cols = numMonths[ 1 ],
7982  width = 17,
7983  activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
7984 
7985  if ( activeCell.length > 0 ) {
7986  datepicker_handleMouseover.apply( activeCell.get( 0 ) );
7987  }
7988 
7989  inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
7990  if ( cols > 1 ) {
7991  inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
7992  }
7993  inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
7994  "Class" ]( "ui-datepicker-multi" );
7995  inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
7996  "Class" ]( "ui-datepicker-rtl" );
7997 
7998  if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7999  inst.input.trigger( "focus" );
8000  }
8001 
8002  // Deffered render of the years select (to avoid flashes on Firefox)
8003  if ( inst.yearshtml ) {
8004  origyearshtml = inst.yearshtml;
8005  setTimeout( function() {
8006 
8007  //assure that inst.yearshtml didn't change.
8008  if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8009  inst.dpDiv.find( "select.ui-datepicker-year:first" ).replaceWith( inst.yearshtml );
8010  }
8011  origyearshtml = inst.yearshtml = null;
8012  }, 0 );
8013  }
8014  },
8015 
8016  // #6694 - don't focus the input if it's already focused
8017  // this breaks the change event in IE
8018  // Support: IE and jQuery <1.9
8019  _shouldFocusInput: function( inst ) {
8020  return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8021  },
8022 
8023  /* Check positioning to remain on screen. */
8024  _checkOffset: function( inst, offset, isFixed ) {
8025  var dpWidth = inst.dpDiv.outerWidth(),
8026  dpHeight = inst.dpDiv.outerHeight(),
8027  inputWidth = inst.input ? inst.input.outerWidth() : 0,
8028  inputHeight = inst.input ? inst.input.outerHeight() : 0,
8029  viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8030  viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8031 
8032  offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8033  offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8034  offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8035 
8036  // Now check if datepicker is showing outside window viewport - move to a better place if so.
8037  offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8038  Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8039  offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8040  Math.abs( dpHeight + inputHeight ) : 0 );
8041 
8042  return offset;
8043  },
8044 
8045  /* Find an object's position on the screen. */
8046  _findPos: function( obj ) {
8047  var position,
8048  inst = this._getInst( obj ),
8049  isRTL = this._get( inst, "isRTL" );
8050 
8051  while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {
8052  obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8053  }
8054 
8055  position = $( obj ).offset();
8056  return [ position.left, position.top ];
8057  },
8058 
8059  /* Hide the date picker from view.
8060  * @param input element - the input field attached to the date picker
8061  */
8062  _hideDatepicker: function( input ) {
8063  var showAnim, duration, postProcess, onClose,
8064  inst = this._curInst;
8065 
8066  if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8067  return;
8068  }
8069 
8070  if ( this._datepickerShowing ) {
8071  showAnim = this._get( inst, "showAnim" );
8072  duration = this._get( inst, "duration" );
8073  postProcess = function() {
8074  $.datepicker._tidyDialog( inst );
8075  };
8076 
8077  // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8078  if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8079  inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8080  } else {
8081  inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8082  ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8083  }
8084 
8085  if ( !showAnim ) {
8086  postProcess();
8087  }
8088  this._datepickerShowing = false;
8089 
8090  onClose = this._get( inst, "onClose" );
8091  if ( onClose ) {
8092  onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8093  }
8094 
8095  this._lastInput = null;
8096  if ( this._inDialog ) {
8097  this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8098  if ( $.blockUI ) {
8099  $.unblockUI();
8100  $( "body" ).append( this.dpDiv );
8101  }
8102  }
8103  this._inDialog = false;
8104  }
8105  },
8106 
8107  /* Tidy up after a dialog display. */
8108  _tidyDialog: function( inst ) {
8109  inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8110  },
8111 
8112  /* Close date picker if clicked elsewhere. */
8113  _checkExternalClick: function( event ) {
8114  if ( !$.datepicker._curInst ) {
8115  return;
8116  }
8117 
8118  var $target = $( event.target ),
8119  inst = $.datepicker._getInst( $target[ 0 ] );
8120 
8121  if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8122  $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8123  !$target.hasClass( $.datepicker.markerClassName ) &&
8124  !$target.closest( "." + $.datepicker._triggerClass ).length &&
8125  $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8126  ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8127  $.datepicker._hideDatepicker();
8128  }
8129  },
8130 
8131  /* Adjust one of the date sub-fields. */
8132  _adjustDate: function( id, offset, period ) {
8133  var target = $( id ),
8134  inst = this._getInst( target[ 0 ] );
8135 
8136  if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8137  return;
8138  }
8139  this._adjustInstDate( inst, offset +
8140  ( period === "M" ? this._get( inst, "showCurrentAtPos" ) : 0 ), // undo positioning
8141  period );
8142  this._updateDatepicker( inst );
8143  },
8144 
8145  /* Action for current link. */
8146  _gotoToday: function( id ) {
8147  var date,
8148  target = $( id ),
8149  inst = this._getInst( target[ 0 ] );
8150 
8151  if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8152  inst.selectedDay = inst.currentDay;
8153  inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8154  inst.drawYear = inst.selectedYear = inst.currentYear;
8155  } else {
8156  date = new Date();
8157  inst.selectedDay = date.getDate();
8158  inst.drawMonth = inst.selectedMonth = date.getMonth();
8159  inst.drawYear = inst.selectedYear = date.getFullYear();
8160  }
8161  this._notifyChange( inst );
8162  this._adjustDate( target );
8163  },
8164 
8165  /* Action for selecting a new month/year. */
8166  _selectMonthYear: function( id, select, period ) {
8167  var target = $( id ),
8168  inst = this._getInst( target[ 0 ] );
8169 
8170  inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8171  inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8172  parseInt( select.options[ select.selectedIndex ].value, 10 );
8173 
8174  this._notifyChange( inst );
8175  this._adjustDate( target );
8176  },
8177 
8178  /* Action for selecting a day. */
8179  _selectDay: function( id, month, year, td ) {
8180  var inst,
8181  target = $( id );
8182 
8183  if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8184  return;
8185  }
8186 
8187  inst = this._getInst( target[ 0 ] );
8188  inst.selectedDay = inst.currentDay = $( "a", td ).html();
8189  inst.selectedMonth = inst.currentMonth = month;
8190  inst.selectedYear = inst.currentYear = year;
8191  this._selectDate( id, this._formatDate( inst,
8192  inst.currentDay, inst.currentMonth, inst.currentYear ) );
8193  },
8194 
8195  /* Erase the input field and hide the date picker. */
8196  _clearDate: function( id ) {
8197  var target = $( id );
8198  this._selectDate( target, "" );
8199  },
8200 
8201  /* Update the input field with the selected date. */
8202  _selectDate: function( id, dateStr ) {
8203  var onSelect,
8204  target = $( id ),
8205  inst = this._getInst( target[ 0 ] );
8206 
8207  dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8208  if ( inst.input ) {
8209  inst.input.val( dateStr );
8210  }
8211  this._updateAlternate( inst );
8212 
8213  onSelect = this._get( inst, "onSelect" );
8214  if ( onSelect ) {
8215  onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback
8216  } else if ( inst.input ) {
8217  inst.input.trigger( "change" ); // fire the change event
8218  }
8219 
8220  if ( inst.inline ) {
8221  this._updateDatepicker( inst );
8222  } else {
8223  this._hideDatepicker();
8224  this._lastInput = inst.input[ 0 ];
8225  if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8226  inst.input.trigger( "focus" ); // restore focus
8227  }
8228  this._lastInput = null;
8229  }
8230  },
8231 
8232  /* Update any alternate field to synchronise with the main field. */
8233  _updateAlternate: function( inst ) {
8234  var altFormat, date, dateStr,
8235  altField = this._get( inst, "altField" );
8236 
8237  if ( altField ) { // update alternate field too
8238  altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8239  date = this._getDate( inst );
8240  dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8241  $( altField ).val( dateStr );
8242  }
8243  },
8244 
8245  /* Set as beforeShowDay function to prevent selection of weekends.
8246  * @param date Date - the date to customise
8247  * @return [boolean, string] - is this date selectable?, what is its CSS class?
8248  */
8249  noWeekends: function( date ) {
8250  var day = date.getDay();
8251  return [ ( day > 0 && day < 6 ), "" ];
8252  },
8253 
8254  /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8255  * @param date Date - the date to get the week for
8256  * @return number - the number of the week within the year that contains this date
8257  */
8258  iso8601Week: function( date ) {
8259  var time,
8260  checkDate = new Date( date.getTime() );
8261 
8262  // Find Thursday of this week starting on Monday
8263  checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8264 
8265  time = checkDate.getTime();
8266  checkDate.setMonth( 0 ); // Compare with Jan 1
8267  checkDate.setDate( 1 );
8268  return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8269  },
8270 
8271  /* Parse a string value into a date object.
8272  * See formatDate below for the possible formats.
8273  *
8274  * @param format string - the expected format of the date
8275  * @param value string - the date in the above format
8276  * @param settings Object - attributes include:
8277  * shortYearCutoff number - the cutoff year for determining the century (optional)
8278  * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8279  * dayNames string[7] - names of the days from Sunday (optional)
8280  * monthNamesShort string[12] - abbreviated names of the months (optional)
8281  * monthNames string[12] - names of the months (optional)
8282  * @return Date - the extracted date value or null if value is blank
8283  */
8284  parseDate: function( format, value, settings ) {
8285  if ( format == null || value == null ) {
8286  throw "Invalid arguments";
8287  }
8288 
8289  value = ( typeof value === "object" ? value.toString() : value + "" );
8290  if ( value === "" ) {
8291  return null;
8292  }
8293 
8294  var iFormat, dim, extra,
8295  iValue = 0,
8296  shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8297  shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8298  new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8299  dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8300  dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8301  monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8302  monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8303  year = -1,
8304  month = -1,
8305  day = -1,
8306  doy = -1,
8307  literal = false,
8308  date,
8309 
8310  // Check whether a format character is doubled
8311  lookAhead = function( match ) {
8312  var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8313  if ( matches ) {
8314  iFormat++;
8315  }
8316  return matches;
8317  },
8318 
8319  // Extract a number from the string value
8320  getNumber = function( match ) {
8321  var isDoubled = lookAhead( match ),
8322  size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8323  ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8324  minSize = ( match === "y" ? size : 1 ),
8325  digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8326  num = value.substring( iValue ).match( digits );
8327  if ( !num ) {
8328  throw "Missing number at position " + iValue;
8329  }
8330  iValue += num[ 0 ].length;
8331  return parseInt( num[ 0 ], 10 );
8332  },
8333 
8334  // Extract a name from the string value and convert to an index
8335  getName = function( match, shortNames, longNames ) {
8336  var index = -1,
8337  names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8338  return [ [ k, v ] ];
8339  } ).sort( function( a, b ) {
8340  return -( a[ 1 ].length - b[ 1 ].length );
8341  } );
8342 
8343  $.each( names, function( i, pair ) {
8344  var name = pair[ 1 ];
8345  if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8346  index = pair[ 0 ];
8347  iValue += name.length;
8348  return false;
8349  }
8350  } );
8351  if ( index !== -1 ) {
8352  return index + 1;
8353  } else {
8354  throw "Unknown name at position " + iValue;
8355  }
8356  },
8357 
8358  // Confirm that a literal character matches the string value
8359  checkLiteral = function() {
8360  if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8361  throw "Unexpected literal at position " + iValue;
8362  }
8363  iValue++;
8364  };
8365 
8366  for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8367  if ( literal ) {
8368  if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8369  literal = false;
8370  } else {
8371  checkLiteral();
8372  }
8373  } else {
8374  switch ( format.charAt( iFormat ) ) {
8375  case "d":
8376  day = getNumber( "d" );
8377  break;
8378  case "D":
8379  getName( "D", dayNamesShort, dayNames );
8380  break;
8381  case "o":
8382  doy = getNumber( "o" );
8383  break;
8384  case "m":
8385  month = getNumber( "m" );
8386  break;
8387  case "M":
8388  month = getName( "M", monthNamesShort, monthNames );
8389  break;
8390  case "y":
8391  year = getNumber( "y" );
8392  break;
8393  case "@":
8394  date = new Date( getNumber( "@" ) );
8395  year = date.getFullYear();
8396  month = date.getMonth() + 1;
8397  day = date.getDate();
8398  break;
8399  case "!":
8400  date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8401  year = date.getFullYear();
8402  month = date.getMonth() + 1;
8403  day = date.getDate();
8404  break;
8405  case "'":
8406  if ( lookAhead( "'" ) ) {
8407  checkLiteral();
8408  } else {
8409  literal = true;
8410  }
8411  break;
8412  default:
8413  checkLiteral();
8414  }
8415  }
8416  }
8417 
8418  if ( iValue < value.length ) {
8419  extra = value.substr( iValue );
8420  if ( !/^\s+/.test( extra ) ) {
8421  throw "Extra/unparsed characters found in date: " + extra;
8422  }
8423  }
8424 
8425  if ( year === -1 ) {
8426  year = new Date().getFullYear();
8427  } else if ( year < 100 ) {
8428  year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8429  ( year <= shortYearCutoff ? 0 : -100 );
8430  }
8431 
8432  if ( doy > -1 ) {
8433  month = 1;
8434  day = doy;
8435  do {
8436  dim = this._getDaysInMonth( year, month - 1 );
8437  if ( day <= dim ) {
8438  break;
8439  }
8440  month++;
8441  day -= dim;
8442  } while ( true );
8443  }
8444 
8445  date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8446  if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8447  throw "Invalid date"; // E.g. 31/02/00
8448  }
8449  return date;
8450  },
8451 
8452  /* Standard date formats. */
8453  ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8454  COOKIE: "D, dd M yy",
8455  ISO_8601: "yy-mm-dd",
8456  RFC_822: "D, d M y",
8457  RFC_850: "DD, dd-M-y",
8458  RFC_1036: "D, d M y",
8459  RFC_1123: "D, d M yy",
8460  RFC_2822: "D, d M yy",
8461  RSS: "D, d M y", // RFC 822
8462  TICKS: "!",
8463  TIMESTAMP: "@",
8464  W3C: "yy-mm-dd", // ISO 8601
8465 
8466  _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8467  Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8468 
8469  /* Format a date object into a string value.
8470  * The format can be combinations of the following:
8471  * d - day of month (no leading zero)
8472  * dd - day of month (two digit)
8473  * o - day of year (no leading zeros)
8474  * oo - day of year (three digit)
8475  * D - day name short
8476  * DD - day name long
8477  * m - month of year (no leading zero)
8478  * mm - month of year (two digit)
8479  * M - month name short
8480  * MM - month name long
8481  * y - year (two digit)
8482  * yy - year (four digit)
8483  * @ - Unix timestamp (ms since 01/01/1970)
8484  * ! - Windows ticks (100ns since 01/01/0001)
8485  * "..." - literal text
8486  * '' - single quote
8487  *
8488  * @param format string - the desired format of the date
8489  * @param date Date - the date value to format
8490  * @param settings Object - attributes include:
8491  * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8492  * dayNames string[7] - names of the days from Sunday (optional)
8493  * monthNamesShort string[12] - abbreviated names of the months (optional)
8494  * monthNames string[12] - names of the months (optional)
8495  * @return string - the date in the above format
8496  */
8497  formatDate: function( format, date, settings ) {
8498  if ( !date ) {
8499  return "";
8500  }
8501 
8502  var iFormat,
8503  dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8504  dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8505  monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8506  monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8507 
8508  // Check whether a format character is doubled
8509  lookAhead = function( match ) {
8510  var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8511  if ( matches ) {
8512  iFormat++;
8513  }
8514  return matches;
8515  },
8516 
8517  // Format a number, with leading zero if necessary
8518  formatNumber = function( match, value, len ) {
8519  var num = "" + value;
8520  if ( lookAhead( match ) ) {
8521  while ( num.length < len ) {
8522  num = "0" + num;
8523  }
8524  }
8525  return num;
8526  },
8527 
8528  // Format a name, short or long as requested
8529  formatName = function( match, value, shortNames, longNames ) {
8530  return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8531  },
8532  output = "",
8533  literal = false;
8534 
8535  if ( date ) {
8536  for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8537  if ( literal ) {
8538  if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8539  literal = false;
8540  } else {
8541  output += format.charAt( iFormat );
8542  }
8543  } else {
8544  switch ( format.charAt( iFormat ) ) {
8545  case "d":
8546  output += formatNumber( "d", date.getDate(), 2 );
8547  break;
8548  case "D":
8549  output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8550  break;
8551  case "o":
8552  output += formatNumber( "o",
8553  Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8554  break;
8555  case "m":
8556  output += formatNumber( "m", date.getMonth() + 1, 2 );
8557  break;
8558  case "M":
8559  output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8560  break;
8561  case "y":
8562  output += ( lookAhead( "y" ) ? date.getFullYear() :
8563  ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8564  break;
8565  case "@":
8566  output += date.getTime();
8567  break;
8568  case "!":
8569  output += date.getTime() * 10000 + this._ticksTo1970;
8570  break;
8571  case "'":
8572  if ( lookAhead( "'" ) ) {
8573  output += "'";
8574  } else {
8575  literal = true;
8576  }
8577  break;
8578  default:
8579  output += format.charAt( iFormat );
8580  }
8581  }
8582  }
8583  }
8584  return output;
8585  },
8586 
8587  /* Extract all possible characters from the date format. */
8588  _possibleChars: function( format ) {
8589  var iFormat,
8590  chars = "",
8591  literal = false,
8592 
8593  // Check whether a format character is doubled
8594  lookAhead = function( match ) {
8595  var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8596  if ( matches ) {
8597  iFormat++;
8598  }
8599  return matches;
8600  };
8601 
8602  for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8603  if ( literal ) {
8604  if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8605  literal = false;
8606  } else {
8607  chars += format.charAt( iFormat );
8608  }
8609  } else {
8610  switch ( format.charAt( iFormat ) ) {
8611  case "d": case "m": case "y": case "@":
8612  chars += "0123456789";
8613  break;
8614  case "D": case "M":
8615  return null; // Accept anything
8616  case "'":
8617  if ( lookAhead( "'" ) ) {
8618  chars += "'";
8619  } else {
8620  literal = true;
8621  }
8622  break;
8623  default:
8624  chars += format.charAt( iFormat );
8625  }
8626  }
8627  }
8628  return chars;
8629  },
8630 
8631  /* Get a setting value, defaulting if necessary. */
8632  _get: function( inst, name ) {
8633  return inst.settings[ name ] !== undefined ?
8634  inst.settings[ name ] : this._defaults[ name ];
8635  },
8636 
8637  /* Parse existing date and initialise date picker. */
8638  _setDateFromField: function( inst, noDefault ) {
8639  if ( inst.input.val() === inst.lastVal ) {
8640  return;
8641  }
8642 
8643  var dateFormat = this._get( inst, "dateFormat" ),
8644  dates = inst.lastVal = inst.input ? inst.input.val() : null,
8645  defaultDate = this._getDefaultDate( inst ),
8646  date = defaultDate,
8647  settings = this._getFormatConfig( inst );
8648 
8649  try {
8650  date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8651  } catch ( event ) {
8652  dates = ( noDefault ? "" : dates );
8653  }
8654  inst.selectedDay = date.getDate();
8655  inst.drawMonth = inst.selectedMonth = date.getMonth();
8656  inst.drawYear = inst.selectedYear = date.getFullYear();
8657  inst.currentDay = ( dates ? date.getDate() : 0 );
8658  inst.currentMonth = ( dates ? date.getMonth() : 0 );
8659  inst.currentYear = ( dates ? date.getFullYear() : 0 );
8660  this._adjustInstDate( inst );
8661  },
8662 
8663  /* Retrieve the default date shown on opening. */
8664  _getDefaultDate: function( inst ) {
8665  return this._restrictMinMax( inst,
8666  this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8667  },
8668 
8669  /* A date may be specified as an exact value or a relative one. */
8670  _determineDate: function( inst, date, defaultDate ) {
8671  var offsetNumeric = function( offset ) {
8672  var date = new Date();
8673  date.setDate( date.getDate() + offset );
8674  return date;
8675  },
8676  offsetString = function( offset ) {
8677  try {
8678  return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8679  offset, $.datepicker._getFormatConfig( inst ) );
8680  }
8681  catch ( e ) {
8682 
8683  // Ignore
8684  }
8685 
8686  var date = ( offset.toLowerCase().match( /^c/ ) ?
8687  $.datepicker._getDate( inst ) : null ) || new Date(),
8688  year = date.getFullYear(),
8689  month = date.getMonth(),
8690  day = date.getDate(),
8691  pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8692  matches = pattern.exec( offset );
8693 
8694  while ( matches ) {
8695  switch ( matches[ 2 ] || "d" ) {
8696  case "d" : case "D" :
8697  day += parseInt( matches[ 1 ], 10 ); break;
8698  case "w" : case "W" :
8699  day += parseInt( matches[ 1 ], 10 ) * 7; break;
8700  case "m" : case "M" :
8701  month += parseInt( matches[ 1 ], 10 );
8702  day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8703  break;
8704  case "y": case "Y" :
8705  year += parseInt( matches[ 1 ], 10 );
8706  day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8707  break;
8708  }
8709  matches = pattern.exec( offset );
8710  }
8711  return new Date( year, month, day );
8712  },
8713  newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8714  ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8715 
8716  newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8717  if ( newDate ) {
8718  newDate.setHours( 0 );
8719  newDate.setMinutes( 0 );
8720  newDate.setSeconds( 0 );
8721  newDate.setMilliseconds( 0 );
8722  }
8723  return this._daylightSavingAdjust( newDate );
8724  },
8725 
8726  /* Handle switch to/from daylight saving.
8727  * Hours may be non-zero on daylight saving cut-over:
8728  * > 12 when midnight changeover, but then cannot generate
8729  * midnight datetime, so jump to 1AM, otherwise reset.
8730  * @param date (Date) the date to check
8731  * @return (Date) the corrected date
8732  */
8733  _daylightSavingAdjust: function( date ) {
8734  if ( !date ) {
8735  return null;
8736  }
8737  date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8738  return date;
8739  },
8740 
8741  /* Set the date(s) directly. */
8742  _setDate: function( inst, date, noChange ) {
8743  var clear = !date,
8744  origMonth = inst.selectedMonth,
8745  origYear = inst.selectedYear,
8746  newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8747 
8748  inst.selectedDay = inst.currentDay = newDate.getDate();
8749  inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8750  inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8751  if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8752  this._notifyChange( inst );
8753  }
8754  this._adjustInstDate( inst );
8755  if ( inst.input ) {
8756  inst.input.val( clear ? "" : this._formatDate( inst ) );
8757  }
8758  },
8759 
8760  /* Retrieve the date(s) directly. */
8761  _getDate: function( inst ) {
8762  var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8763  this._daylightSavingAdjust( new Date(
8764  inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8765  return startDate;
8766  },
8767 
8768  /* Attach the onxxx handlers. These are declared statically so
8769  * they work with static code transformers like Caja.
8770  */
8771  _attachHandlers: function( inst ) {
8772  var stepMonths = this._get( inst, "stepMonths" ),
8773  id = "#" + inst.id.replace( /\\\\/g, "\\" );
8774  inst.dpDiv.find( "[data-handler]" ).map( function() {
8775  var handler = {
8776  prev: function() {
8777  $.datepicker._adjustDate( id, -stepMonths, "M" );
8778  },
8779  next: function() {
8780  $.datepicker._adjustDate( id, +stepMonths, "M" );
8781  },
8782  hide: function() {
8783  $.datepicker._hideDatepicker();
8784  },
8785  today: function() {
8786  $.datepicker._gotoToday( id );
8787  },
8788  selectDay: function() {
8789  $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8790  return false;
8791  },
8792  selectMonth: function() {
8793  $.datepicker._selectMonthYear( id, this, "M" );
8794  return false;
8795  },
8796  selectYear: function() {
8797  $.datepicker._selectMonthYear( id, this, "Y" );
8798  return false;
8799  }
8800  };
8801  $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8802  } );
8803  },
8804 
8805  /* Generate the HTML for the current state of the date picker. */
8806  _generateHTML: function( inst ) {
8807  var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8808  controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8809  monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8810  selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8811  cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8812  printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8813  tempDate = new Date(),
8814  today = this._daylightSavingAdjust(
8815  new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8816  isRTL = this._get( inst, "isRTL" ),
8817  showButtonPanel = this._get( inst, "showButtonPanel" ),
8818  hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8819  navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8820  numMonths = this._getNumberOfMonths( inst ),
8821  showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8822  stepMonths = this._get( inst, "stepMonths" ),
8823  isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8824  currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8825  new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8826  minDate = this._getMinMaxDate( inst, "min" ),
8827  maxDate = this._getMinMaxDate( inst, "max" ),
8828  drawMonth = inst.drawMonth - showCurrentAtPos,
8829  drawYear = inst.drawYear;
8830 
8831  if ( drawMonth < 0 ) {
8832  drawMonth += 12;
8833  drawYear--;
8834  }
8835  if ( maxDate ) {
8836  maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
8837  maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
8838  maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
8839  while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
8840  drawMonth--;
8841  if ( drawMonth < 0 ) {
8842  drawMonth = 11;
8843  drawYear--;
8844  }
8845  }
8846  }
8847  inst.drawMonth = drawMonth;
8848  inst.drawYear = drawYear;
8849 
8850  prevText = this._get( inst, "prevText" );
8851  prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
8852  this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
8853  this._getFormatConfig( inst ) ) );
8854 
8855  prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?
8856  "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
8857  " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" :
8858  ( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" ) );
8859 
8860  nextText = this._get( inst, "nextText" );
8861  nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
8862  this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
8863  this._getFormatConfig( inst ) ) );
8864 
8865  next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?
8866  "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
8867  " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" :
8868  ( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" ) );
8869 
8870  currentText = this._get( inst, "currentText" );
8871  gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
8872  currentText = ( !navigationAsDateFormat ? currentText :
8873  this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
8874 
8875  controls = ( !inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
8876  this._get( inst, "closeText" ) + "</button>" : "" );
8877 
8878  buttonPanel = ( showButtonPanel ) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + ( isRTL ? controls : "" ) +
8879  ( this._isInRange( inst, gotoDate ) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
8880  ">" + currentText + "</button>" : "" ) + ( isRTL ? "" : controls ) + "</div>" : "";
8881 
8882  firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
8883  firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
8884 
8885  showWeek = this._get( inst, "showWeek" );
8886  dayNames = this._get( inst, "dayNames" );
8887  dayNamesMin = this._get( inst, "dayNamesMin" );
8888  monthNames = this._get( inst, "monthNames" );
8889  monthNamesShort = this._get( inst, "monthNamesShort" );
8890  beforeShowDay = this._get( inst, "beforeShowDay" );
8891  showOtherMonths = this._get( inst, "showOtherMonths" );
8892  selectOtherMonths = this._get( inst, "selectOtherMonths" );
8893  defaultDate = this._getDefaultDate( inst );
8894  html = "";
8895 
8896  for ( row = 0; row < numMonths[ 0 ]; row++ ) {
8897  group = "";
8898  this.maxRows = 4;
8899  for ( col = 0; col < numMonths[ 1 ]; col++ ) {
8900  selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
8901  cornerClass = " ui-corner-all";
8902  calender = "";
8903  if ( isMultiMonth ) {
8904  calender += "<div class='ui-datepicker-group";
8905  if ( numMonths[ 1 ] > 1 ) {
8906  switch ( col ) {
8907  case 0: calender += " ui-datepicker-group-first";
8908  cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
8909  case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
8910  cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
8911  default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8912  }
8913  }
8914  calender += "'>";
8915  }
8916  calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8917  ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
8918  ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
8919  this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
8920  row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
8921  "</div><table class='ui-datepicker-calendar'><thead>" +
8922  "<tr>";
8923  thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
8924  for ( dow = 0; dow < 7; dow++ ) { // days of the week
8925  day = ( dow + firstDay ) % 7;
8926  thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
8927  "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
8928  }
8929  calender += thead + "</tr></thead><tbody>";
8930  daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
8931  if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
8932  inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
8933  }
8934  leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
8935  curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
8936  numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
8937  this.maxRows = numRows;
8938  printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
8939  for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
8940  calender += "<tr>";
8941  tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
8942  this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
8943  for ( dow = 0; dow < 7; dow++ ) { // create date picker days
8944  daySettings = ( beforeShowDay ?
8945  beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
8946  otherMonth = ( printDate.getMonth() !== drawMonth );
8947  unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
8948  ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
8949  tbody += "<td class='" +
8950  ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
8951  ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
8952  ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
8953  ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
8954 
8955  // or defaultDate is current printedDate and defaultDate is selectedDate
8956  " " + this._dayOverClass : "" ) + // highlight selected day
8957  ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days
8958  ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
8959  ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
8960  ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
8961  ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
8962  ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
8963  ( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
8964  ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
8965  ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
8966  ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
8967  ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
8968  "' href='#'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
8969  printDate.setDate( printDate.getDate() + 1 );
8970  printDate = this._daylightSavingAdjust( printDate );
8971  }
8972  calender += tbody + "</tr>";
8973  }
8974  drawMonth++;
8975  if ( drawMonth > 11 ) {
8976  drawMonth = 0;
8977  drawYear++;
8978  }
8979  calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
8980  ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
8981  group += calender;
8982  }
8983  html += group;
8984  }
8985  html += buttonPanel;
8986  inst._keyEvent = false;
8987  return html;
8988  },
8989 
8990  /* Generate the month and year header. */
8991  _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
8992  secondary, monthNames, monthNamesShort ) {
8993 
8994  var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
8995  changeMonth = this._get( inst, "changeMonth" ),
8996  changeYear = this._get( inst, "changeYear" ),
8997  showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
8998  html = "<div class='ui-datepicker-title'>",
8999  monthHtml = "";
9000 
9001  // Month selection
9002  if ( secondary || !changeMonth ) {
9003  monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9004  } else {
9005  inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9006  inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9007  monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
9008  for ( month = 0; month < 12; month++ ) {
9009  if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9010  monthHtml += "<option value='" + month + "'" +
9011  ( month === drawMonth ? " selected='selected'" : "" ) +
9012  ">" + monthNamesShort[ month ] + "</option>";
9013  }
9014  }
9015  monthHtml += "</select>";
9016  }
9017 
9018  if ( !showMonthAfterYear ) {
9019  html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9020  }
9021 
9022  // Year selection
9023  if ( !inst.yearshtml ) {
9024  inst.yearshtml = "";
9025  if ( secondary || !changeYear ) {
9026  html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9027  } else {
9028 
9029  // determine range of years to display
9030  years = this._get( inst, "yearRange" ).split( ":" );
9031  thisYear = new Date().getFullYear();
9032  determineYear = function( value ) {
9033  var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9034  ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9035  parseInt( value, 10 ) ) );
9036  return ( isNaN( year ) ? thisYear : year );
9037  };
9038  year = determineYear( years[ 0 ] );
9039  endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9040  year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9041  endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9042  inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
9043  for ( ; year <= endYear; year++ ) {
9044  inst.yearshtml += "<option value='" + year + "'" +
9045  ( year === drawYear ? " selected='selected'" : "" ) +
9046  ">" + year + "</option>";
9047  }
9048  inst.yearshtml += "</select>";
9049 
9050  html += inst.yearshtml;
9051  inst.yearshtml = null;
9052  }
9053  }
9054 
9055  html += this._get( inst, "yearSuffix" );
9056  if ( showMonthAfterYear ) {
9057  html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9058  }
9059  html += "</div>"; // Close datepicker_header
9060  return html;
9061  },
9062 
9063  /* Adjust one of the date sub-fields. */
9064  _adjustInstDate: function( inst, offset, period ) {
9065  var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9066  month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9067  day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9068  date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9069 
9070  inst.selectedDay = date.getDate();
9071  inst.drawMonth = inst.selectedMonth = date.getMonth();
9072  inst.drawYear = inst.selectedYear = date.getFullYear();
9073  if ( period === "M" || period === "Y" ) {
9074  this._notifyChange( inst );
9075  }
9076  },
9077 
9078  /* Ensure a date is within any min/max bounds. */
9079  _restrictMinMax: function( inst, date ) {
9080  var minDate = this._getMinMaxDate( inst, "min" ),
9081  maxDate = this._getMinMaxDate( inst, "max" ),
9082  newDate = ( minDate && date < minDate ? minDate : date );
9083  return ( maxDate && newDate > maxDate ? maxDate : newDate );
9084  },
9085 
9086  /* Notify change of month/year. */
9087  _notifyChange: function( inst ) {
9088  var onChange = this._get( inst, "onChangeMonthYear" );
9089  if ( onChange ) {
9090  onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9091  [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9092  }
9093  },
9094 
9095  /* Determine the number of months to show. */
9096  _getNumberOfMonths: function( inst ) {
9097  var numMonths = this._get( inst, "numberOfMonths" );
9098  return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9099  },
9100 
9101  /* Determine the current maximum date - ensure no time components are set. */
9102  _getMinMaxDate: function( inst, minMax ) {
9103  return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9104  },
9105 
9106  /* Find the number of days in a given month. */
9107  _getDaysInMonth: function( year, month ) {
9108  return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9109  },
9110 
9111  /* Find the day of the week of the first of a month. */
9112  _getFirstDayOfMonth: function( year, month ) {
9113  return new Date( year, month, 1 ).getDay();
9114  },
9115 
9116  /* Determines if we should allow a "next/prev" month display change. */
9117  _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9118  var numMonths = this._getNumberOfMonths( inst ),
9119  date = this._daylightSavingAdjust( new Date( curYear,
9120  curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9121 
9122  if ( offset < 0 ) {
9123  date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9124  }
9125  return this._isInRange( inst, date );
9126  },
9127 
9128  /* Is the given date in the accepted range? */
9129  _isInRange: function( inst, date ) {
9130  var yearSplit, currentYear,
9131  minDate = this._getMinMaxDate( inst, "min" ),
9132  maxDate = this._getMinMaxDate( inst, "max" ),
9133  minYear = null,
9134  maxYear = null,
9135  years = this._get( inst, "yearRange" );
9136  if ( years ) {
9137  yearSplit = years.split( ":" );
9138  currentYear = new Date().getFullYear();
9139  minYear = parseInt( yearSplit[ 0 ], 10 );
9140  maxYear = parseInt( yearSplit[ 1 ], 10 );
9141  if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9142  minYear += currentYear;
9143  }
9144  if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9145  maxYear += currentYear;
9146  }
9147  }
9148 
9149  return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9150  ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9151  ( !minYear || date.getFullYear() >= minYear ) &&
9152  ( !maxYear || date.getFullYear() <= maxYear ) );
9153  },
9154 
9155  /* Provide the configuration settings for formatting/parsing. */
9156  _getFormatConfig: function( inst ) {
9157  var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9158  shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9159  new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9160  return { shortYearCutoff: shortYearCutoff,
9161  dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9162  monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9163  },
9164 
9165  /* Format the given date for display. */
9166  _formatDate: function( inst, day, month, year ) {
9167  if ( !day ) {
9168  inst.currentDay = inst.selectedDay;
9169  inst.currentMonth = inst.selectedMonth;
9170  inst.currentYear = inst.selectedYear;
9171  }
9172  var date = ( day ? ( typeof day === "object" ? day :
9173  this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9174  this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9175  return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9176  }
9177 } );
9178 
9179 /*
9180  * Bind hover events for datepicker elements.
9181  * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9182  * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9183  */
9184 function datepicker_bindHover( dpDiv ) {
9185  var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9186  return dpDiv.on( "mouseout", selector, function() {
9187  $( this ).removeClass( "ui-state-hover" );
9188  if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9189  $( this ).removeClass( "ui-datepicker-prev-hover" );
9190  }
9191  if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9192  $( this ).removeClass( "ui-datepicker-next-hover" );
9193  }
9194  } )
9195  .on( "mouseover", selector, datepicker_handleMouseover );
9196 }
9197 
9198 function datepicker_handleMouseover() {
9199  if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9200  $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9201  $( this ).addClass( "ui-state-hover" );
9202  if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9203  $( this ).addClass( "ui-datepicker-prev-hover" );
9204  }
9205  if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9206  $( this ).addClass( "ui-datepicker-next-hover" );
9207  }
9208  }
9209 }
9210 
9211 /* jQuery extend now ignores nulls! */
9212 function datepicker_extendRemove( target, props ) {
9213  $.extend( target, props );
9214  for ( var name in props ) {
9215  if ( props[ name ] == null ) {
9216  target[ name ] = props[ name ];
9217  }
9218  }
9219  return target;
9220 }
9221 
9222 /* Invoke the datepicker functionality.
9223  @param options string - a command, optionally followed by additional parameters or
9224  Object - settings for attaching new datepicker functionality
9225  @return jQuery object */
9226 $.fn.datepicker = function( options ) {
9227 
9228  /* Verify an empty collection wasn't passed - Fixes #6976 */
9229  if ( !this.length ) {
9230  return this;
9231  }
9232 
9233  /* Initialise the date picker. */
9234  if ( !$.datepicker.initialized ) {
9235  $( document ).on( "mousedown", $.datepicker._checkExternalClick );
9236  $.datepicker.initialized = true;
9237  }
9238 
9239  /* Append datepicker main container to body if not exist. */
9240  if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9241  $( "body" ).append( $.datepicker.dpDiv );
9242  }
9243 
9244  var otherArgs = Array.prototype.slice.call( arguments, 1 );
9245  if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9246  return $.datepicker[ "_" + options + "Datepicker" ].
9247  apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9248  }
9249  if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9250  return $.datepicker[ "_" + options + "Datepicker" ].
9251  apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9252  }
9253  return this.each( function() {
9254  typeof options === "string" ?
9255  $.datepicker[ "_" + options + "Datepicker" ].
9256  apply( $.datepicker, [ this ].concat( otherArgs ) ) :
9257  $.datepicker._attachDatepicker( this, options );
9258  } );
9259 };
9260 
9261 $.datepicker = new Datepicker(); // singleton instance
9262 $.datepicker.initialized = false;
9263 $.datepicker.uuid = new Date().getTime();
9264 $.datepicker.version = "1.12.1";
9265 
9266 var widgetsDatepicker = $.datepicker;
9267 
9268 
9269 
9270 
9271 // This file is deprecated
9272 var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
9273 
9283 //>>label: Mouse
9284 //>>group: Widgets
9285 //>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9286 //>>docs: http://api.jqueryui.com/mouse/
9287 
9288 
9289 
9290 var mouseHandled = false;
9291 $( document ).on( "mouseup", function() {
9292  mouseHandled = false;
9293 } );
9294 
9295 var widgetsMouse = $.widget( "ui.mouse", {
9296  version: "1.12.1",
9297  options: {
9298  cancel: "input, textarea, button, select, option",
9299  distance: 1,
9300  delay: 0
9301  },
9302  _mouseInit: function() {
9303  var that = this;
9304 
9305  this.element
9306  .on( "mousedown." + this.widgetName, function( event ) {
9307  return that._mouseDown( event );
9308  } )
9309  .on( "click." + this.widgetName, function( event ) {
9310  if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9311  $.removeData( event.target, that.widgetName + ".preventClickEvent" );
9312  event.stopImmediatePropagation();
9313  return false;
9314  }
9315  } );
9316 
9317  this.started = false;
9318  },
9319 
9320  // TODO: make sure destroying one instance of mouse doesn't mess with
9321  // other instances of mouse
9322  _mouseDestroy: function() {
9323  this.element.off( "." + this.widgetName );
9324  if ( this._mouseMoveDelegate ) {
9325  this.document
9326  .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9327  .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9328  }
9329  },
9330 
9331  _mouseDown: function( event ) {
9332 
9333  // don't let more than one widget handle mouseStart
9334  if ( mouseHandled ) {
9335  return;
9336  }
9337 
9338  this._mouseMoved = false;
9339 
9340  // We may have missed mouseup (out of window)
9341  ( this._mouseStarted && this._mouseUp( event ) );
9342 
9343  this._mouseDownEvent = event;
9344 
9345  var that = this,
9346  btnIsLeft = ( event.which === 1 ),
9347 
9348  // event.target.nodeName works around a bug in IE 8 with
9349  // disabled inputs (#7620)
9350  elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
9351  $( event.target ).closest( this.options.cancel ).length : false );
9352  if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9353  return true;
9354  }
9355 
9356  this.mouseDelayMet = !this.options.delay;
9357  if ( !this.mouseDelayMet ) {
9358  this._mouseDelayTimer = setTimeout( function() {
9359  that.mouseDelayMet = true;
9360  }, this.options.delay );
9361  }
9362 
9363  if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9364  this._mouseStarted = ( this._mouseStart( event ) !== false );
9365  if ( !this._mouseStarted ) {
9366  event.preventDefault();
9367  return true;
9368  }
9369  }
9370 
9371  // Click event may never have fired (Gecko & Opera)
9372  if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9373  $.removeData( event.target, this.widgetName + ".preventClickEvent" );
9374  }
9375 
9376  // These delegates are required to keep context
9377  this._mouseMoveDelegate = function( event ) {
9378  return that._mouseMove( event );
9379  };
9380  this._mouseUpDelegate = function( event ) {
9381  return that._mouseUp( event );
9382  };
9383 
9384  this.document
9385  .on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9386  .on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9387 
9388  event.preventDefault();
9389 
9390  mouseHandled = true;
9391  return true;
9392  },
9393 
9394  _mouseMove: function( event ) {
9395 
9396  // Only check for mouseups outside the document if you've moved inside the document
9397  // at least once. This prevents the firing of mouseup in the case of IE<9, which will
9398  // fire a mousemove event if content is placed under the cursor. See #7778
9399  // Support: IE <9
9400  if ( this._mouseMoved ) {
9401 
9402  // IE mouseup check - mouseup happened when mouse was out of window
9403  if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
9404  !event.button ) {
9405  return this._mouseUp( event );
9406 
9407  // Iframe mouseup check - mouseup occurred in another document
9408  } else if ( !event.which ) {
9409 
9410  // Support: Safari <=8 - 9
9411  // Safari sets which to 0 if you press any of the following keys
9412  // during a drag (#14461)
9413  if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9414  event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9415  this.ignoreMissingWhich = true;
9416  } else if ( !this.ignoreMissingWhich ) {
9417  return this._mouseUp( event );
9418  }
9419  }
9420  }
9421 
9422  if ( event.which || event.button ) {
9423  this._mouseMoved = true;
9424  }
9425 
9426  if ( this._mouseStarted ) {
9427  this._mouseDrag( event );
9428  return event.preventDefault();
9429  }
9430 
9431  if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9432  this._mouseStarted =
9433  ( this._mouseStart( this._mouseDownEvent, event ) !== false );
9434  ( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );
9435  }
9436 
9437  return !this._mouseStarted;
9438  },
9439 
9440  _mouseUp: function( event ) {
9441  this.document
9442  .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9443  .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9444 
9445  if ( this._mouseStarted ) {
9446  this._mouseStarted = false;
9447 
9448  if ( event.target === this._mouseDownEvent.target ) {
9449  $.data( event.target, this.widgetName + ".preventClickEvent", true );
9450  }
9451 
9452  this._mouseStop( event );
9453  }
9454 
9455  if ( this._mouseDelayTimer ) {
9456  clearTimeout( this._mouseDelayTimer );
9457  delete this._mouseDelayTimer;
9458  }
9459 
9460  this.ignoreMissingWhich = false;
9461  mouseHandled = false;
9462  event.preventDefault();
9463  },
9464 
9465  _mouseDistanceMet: function( event ) {
9466  return ( Math.max(
9467  Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9468  Math.abs( this._mouseDownEvent.pageY - event.pageY )
9469  ) >= this.options.distance
9470  );
9471  },
9472 
9473  _mouseDelayMet: function( /* event */ ) {
9474  return this.mouseDelayMet;
9475  },
9476 
9477  // These are placeholder methods, to be overriden by extending plugin
9478  _mouseStart: function( /* event */ ) {},
9479  _mouseDrag: function( /* event */ ) {},
9480  _mouseStop: function( /* event */ ) {},
9481  _mouseCapture: function( /* event */ ) { return true; }
9482 } );
9483 
9484 
9485 
9486 
9487 // $.ui.plugin is deprecated. Use $.widget() extensions instead.
9488 var plugin = $.ui.plugin = {
9489  add: function( module, option, set ) {
9490  var i,
9491  proto = $.ui[ module ].prototype;
9492  for ( i in set ) {
9493  proto.plugins[ i ] = proto.plugins[ i ] || [];
9494  proto.plugins[ i ].push( [ option, set[ i ] ] );
9495  }
9496  },
9497  call: function( instance, name, args, allowDisconnected ) {
9498  var i,
9499  set = instance.plugins[ name ];
9500 
9501  if ( !set ) {
9502  return;
9503  }
9504 
9505  if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9506  instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9507  return;
9508  }
9509 
9510  for ( i = 0; i < set.length; i++ ) {
9511  if ( instance.options[ set[ i ][ 0 ] ] ) {
9512  set[ i ][ 1 ].apply( instance.element, args );
9513  }
9514  }
9515  }
9516 };
9517 
9518 
9519 
9520 var safeBlur = $.ui.safeBlur = function( element ) {
9521 
9522  // Support: IE9 - 10 only
9523  // If the <body> is blurred, IE will switch windows, see #9420
9524  if ( element && element.nodeName.toLowerCase() !== "body" ) {
9525  $( element ).trigger( "blur" );
9526  }
9527 };
9528 
9529 
9539 //>>label: Draggable
9540 //>>group: Interactions
9541 //>>description: Enables dragging functionality for any element.
9542 //>>docs: http://api.jqueryui.com/draggable/
9543 //>>demos: http://jqueryui.com/draggable/
9544 //>>css.structure: ../../themes/base/draggable.css
9545 
9546 
9547 
9548 $.widget( "ui.draggable", $.ui.mouse, {
9549  version: "1.12.1",
9550  widgetEventPrefix: "drag",
9551  options: {
9552  addClasses: true,
9553  appendTo: "parent",
9554  axis: false,
9555  connectToSortable: false,
9556  containment: false,
9557  cursor: "auto",
9558  cursorAt: false,
9559  grid: false,
9560  handle: false,
9561  helper: "original",
9562  iframeFix: false,
9563  opacity: false,
9564  refreshPositions: false,
9565  revert: false,
9566  revertDuration: 500,
9567  scope: "default",
9568  scroll: true,
9569  scrollSensitivity: 20,
9570  scrollSpeed: 20,
9571  snap: false,
9572  snapMode: "both",
9573  snapTolerance: 20,
9574  stack: false,
9575  zIndex: false,
9576 
9577  // Callbacks
9578  drag: null,
9579  start: null,
9580  stop: null
9581  },
9582  _create: function() {
9583 
9584  if ( this.options.helper === "original" ) {
9585  this._setPositionRelative();
9586  }
9587  if ( this.options.addClasses ) {
9588  this._addClass( "ui-draggable" );
9589  }
9590  this._setHandleClassName();
9591 
9592  this._mouseInit();
9593  },
9594 
9595  _setOption: function( key, value ) {
9596  this._super( key, value );
9597  if ( key === "handle" ) {
9598  this._removeHandleClassName();
9599  this._setHandleClassName();
9600  }
9601  },
9602 
9603  _destroy: function() {
9604  if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9605  this.destroyOnClear = true;
9606  return;
9607  }
9608  this._removeHandleClassName();
9609  this._mouseDestroy();
9610  },
9611 
9612  _mouseCapture: function( event ) {
9613  var o = this.options;
9614 
9615  // Among others, prevent a drag on a resizable-handle
9616  if ( this.helper || o.disabled ||
9617  $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9618  return false;
9619  }
9620 
9621  //Quit if we're not on a valid handle
9622  this.handle = this._getHandle( event );
9623  if ( !this.handle ) {
9624  return false;
9625  }
9626 
9627  this._blurActiveElement( event );
9628 
9629  this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9630 
9631  return true;
9632 
9633  },
9634 
9635  _blockFrames: function( selector ) {
9636  this.iframeBlocks = this.document.find( selector ).map( function() {
9637  var iframe = $( this );
9638 
9639  return $( "<div>" )
9640  .css( "position", "absolute" )
9641  .appendTo( iframe.parent() )
9642  .outerWidth( iframe.outerWidth() )
9643  .outerHeight( iframe.outerHeight() )
9644  .offset( iframe.offset() )[ 0 ];
9645  } );
9646  },
9647 
9648  _unblockFrames: function() {
9649  if ( this.iframeBlocks ) {
9650  this.iframeBlocks.remove();
9651  delete this.iframeBlocks;
9652  }
9653  },
9654 
9655  _blurActiveElement: function( event ) {
9656  var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
9657  target = $( event.target );
9658 
9659  // Don't blur if the event occurred on an element that is within
9660  // the currently focused element
9661  // See #10527, #12472
9662  if ( target.closest( activeElement ).length ) {
9663  return;
9664  }
9665 
9666  // Blur any element that currently has focus, see #4261
9667  $.ui.safeBlur( activeElement );
9668  },
9669 
9670  _mouseStart: function( event ) {
9671 
9672  var o = this.options;
9673 
9674  //Create and append the visible helper
9675  this.helper = this._createHelper( event );
9676 
9677  this._addClass( this.helper, "ui-draggable-dragging" );
9678 
9679  //Cache the helper size
9680  this._cacheHelperProportions();
9681 
9682  //If ddmanager is used for droppables, set the global draggable
9683  if ( $.ui.ddmanager ) {
9684  $.ui.ddmanager.current = this;
9685  }
9686 
9687  /*
9688  * - Position generation -
9689  * This block generates everything position related - it's the core of draggables.
9690  */
9691 
9692  //Cache the margins of the original element
9693  this._cacheMargins();
9694 
9695  //Store the helper's css position
9696  this.cssPosition = this.helper.css( "position" );
9697  this.scrollParent = this.helper.scrollParent( true );
9698  this.offsetParent = this.helper.offsetParent();
9699  this.hasFixedAncestor = this.helper.parents().filter( function() {
9700  return $( this ).css( "position" ) === "fixed";
9701  } ).length > 0;
9702 
9703  //The element's absolute position on the page minus margins
9704  this.positionAbs = this.element.offset();
9705  this._refreshOffsets( event );
9706 
9707  //Generate the original position
9708  this.originalPosition = this.position = this._generatePosition( event, false );
9709  this.originalPageX = event.pageX;
9710  this.originalPageY = event.pageY;
9711 
9712  //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9713  ( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
9714 
9715  //Set a containment if given in the options
9716  this._setContainment();
9717 
9718  //Trigger event + callbacks
9719  if ( this._trigger( "start", event ) === false ) {
9720  this._clear();
9721  return false;
9722  }
9723 
9724  //Recache the helper size
9725  this._cacheHelperProportions();
9726 
9727  //Prepare the droppable offsets
9728  if ( $.ui.ddmanager && !o.dropBehaviour ) {
9729  $.ui.ddmanager.prepareOffsets( this, event );
9730  }
9731 
9732  // Execute the drag once - this causes the helper not to be visible before getting its
9733  // correct position
9734  this._mouseDrag( event, true );
9735 
9736  // If the ddmanager is used for droppables, inform the manager that dragging has started
9737  // (see #5003)
9738  if ( $.ui.ddmanager ) {
9739  $.ui.ddmanager.dragStart( this, event );
9740  }
9741 
9742  return true;
9743  },
9744 
9745  _refreshOffsets: function( event ) {
9746  this.offset = {
9747  top: this.positionAbs.top - this.margins.top,
9748  left: this.positionAbs.left - this.margins.left,
9749  scroll: false,
9750  parent: this._getParentOffset(),
9751  relative: this._getRelativeOffset()
9752  };
9753 
9754  this.offset.click = {
9755  left: event.pageX - this.offset.left,
9756  top: event.pageY - this.offset.top
9757  };
9758  },
9759 
9760  _mouseDrag: function( event, noPropagation ) {
9761 
9762  // reset any necessary cached properties (see #5009)
9763  if ( this.hasFixedAncestor ) {
9764  this.offset.parent = this._getParentOffset();
9765  }
9766 
9767  //Compute the helpers position
9768  this.position = this._generatePosition( event, true );
9769  this.positionAbs = this._convertPositionTo( "absolute" );
9770 
9771  //Call plugins and callbacks and use the resulting position if something is returned
9772  if ( !noPropagation ) {
9773  var ui = this._uiHash();
9774  if ( this._trigger( "drag", event, ui ) === false ) {
9775  this._mouseUp( new $.Event( "mouseup", event ) );
9776  return false;
9777  }
9778  this.position = ui.position;
9779  }
9780 
9781  this.helper[ 0 ].style.left = this.position.left + "px";
9782  this.helper[ 0 ].style.top = this.position.top + "px";
9783 
9784  if ( $.ui.ddmanager ) {
9785  $.ui.ddmanager.drag( this, event );
9786  }
9787 
9788  return false;
9789  },
9790 
9791  _mouseStop: function( event ) {
9792 
9793  //If we are using droppables, inform the manager about the drop
9794  var that = this,
9795  dropped = false;
9796  if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
9797  dropped = $.ui.ddmanager.drop( this, event );
9798  }
9799 
9800  //if a drop comes from outside (a sortable)
9801  if ( this.dropped ) {
9802  dropped = this.dropped;
9803  this.dropped = false;
9804  }
9805 
9806  if ( ( this.options.revert === "invalid" && !dropped ) ||
9807  ( this.options.revert === "valid" && dropped ) ||
9808  this.options.revert === true || ( $.isFunction( this.options.revert ) &&
9809  this.options.revert.call( this.element, dropped ) )
9810  ) {
9811  $( this.helper ).animate(
9812  this.originalPosition,
9813  parseInt( this.options.revertDuration, 10 ),
9814  function() {
9815  if ( that._trigger( "stop", event ) !== false ) {
9816  that._clear();
9817  }
9818  }
9819  );
9820  } else {
9821  if ( this._trigger( "stop", event ) !== false ) {
9822  this._clear();
9823  }
9824  }
9825 
9826  return false;
9827  },
9828 
9829  _mouseUp: function( event ) {
9830  this._unblockFrames();
9831 
9832  // If the ddmanager is used for droppables, inform the manager that dragging has stopped
9833  // (see #5003)
9834  if ( $.ui.ddmanager ) {
9835  $.ui.ddmanager.dragStop( this, event );
9836  }
9837 
9838  // Only need to focus if the event occurred on the draggable itself, see #10527
9839  if ( this.handleElement.is( event.target ) ) {
9840 
9841  // The interaction is over; whether or not the click resulted in a drag,
9842  // focus the element
9843  this.element.trigger( "focus" );
9844  }
9845 
9846  return $.ui.mouse.prototype._mouseUp.call( this, event );
9847  },
9848 
9849  cancel: function() {
9850 
9851  if ( this.helper.is( ".ui-draggable-dragging" ) ) {
9852  this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
9853  } else {
9854  this._clear();
9855  }
9856 
9857  return this;
9858 
9859  },
9860 
9861  _getHandle: function( event ) {
9862  return this.options.handle ?
9863  !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
9864  true;
9865  },
9866 
9867  _setHandleClassName: function() {
9868  this.handleElement = this.options.handle ?
9869  this.element.find( this.options.handle ) : this.element;
9870  this._addClass( this.handleElement, "ui-draggable-handle" );
9871  },
9872 
9873  _removeHandleClassName: function() {
9874  this._removeClass( this.handleElement, "ui-draggable-handle" );
9875  },
9876 
9877  _createHelper: function( event ) {
9878 
9879  var o = this.options,
9880  helperIsFunction = $.isFunction( o.helper ),
9881  helper = helperIsFunction ?
9882  $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
9883  ( o.helper === "clone" ?
9884  this.element.clone().removeAttr( "id" ) :
9885  this.element );
9886 
9887  if ( !helper.parents( "body" ).length ) {
9888  helper.appendTo( ( o.appendTo === "parent" ?
9889  this.element[ 0 ].parentNode :
9890  o.appendTo ) );
9891  }
9892 
9893  // Http://bugs.jqueryui.com/ticket/9446
9894  // a helper function can return the original element
9895  // which wouldn't have been set to relative in _create
9896  if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
9897  this._setPositionRelative();
9898  }
9899 
9900  if ( helper[ 0 ] !== this.element[ 0 ] &&
9901  !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
9902  helper.css( "position", "absolute" );
9903  }
9904 
9905  return helper;
9906 
9907  },
9908 
9909  _setPositionRelative: function() {
9910  if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
9911  this.element[ 0 ].style.position = "relative";
9912  }
9913  },
9914 
9915  _adjustOffsetFromHelper: function( obj ) {
9916  if ( typeof obj === "string" ) {
9917  obj = obj.split( " " );
9918  }
9919  if ( $.isArray( obj ) ) {
9920  obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
9921  }
9922  if ( "left" in obj ) {
9923  this.offset.click.left = obj.left + this.margins.left;
9924  }
9925  if ( "right" in obj ) {
9926  this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
9927  }
9928  if ( "top" in obj ) {
9929  this.offset.click.top = obj.top + this.margins.top;
9930  }
9931  if ( "bottom" in obj ) {
9932  this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
9933  }
9934  },
9935 
9936  _isRootNode: function( element ) {
9937  return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
9938  },
9939 
9940  _getParentOffset: function() {
9941 
9942  //Get the offsetParent and cache its position
9943  var po = this.offsetParent.offset(),
9944  document = this.document[ 0 ];
9945 
9946  // This is a special case where we need to modify a offset calculated on start, since the
9947  // following happened:
9948  // 1. The position of the helper is absolute, so it's position is calculated based on the
9949  // next positioned parent
9950  // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
9951  // the document, which means that the scroll is included in the initial calculation of the
9952  // offset of the parent, and never recalculated upon drag
9953  if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
9954  $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
9955  po.left += this.scrollParent.scrollLeft();
9956  po.top += this.scrollParent.scrollTop();
9957  }
9958 
9959  if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
9960  po = { top: 0, left: 0 };
9961  }
9962 
9963  return {
9964  top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
9965  left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
9966  };
9967 
9968  },
9969 
9970  _getRelativeOffset: function() {
9971  if ( this.cssPosition !== "relative" ) {
9972  return { top: 0, left: 0 };
9973  }
9974 
9975  var p = this.element.position(),
9976  scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
9977 
9978  return {
9979  top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
9980  ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
9981  left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
9982  ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
9983  };
9984 
9985  },
9986 
9987  _cacheMargins: function() {
9988  this.margins = {
9989  left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
9990  top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
9991  right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
9992  bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
9993  };
9994  },
9995 
9996  _cacheHelperProportions: function() {
9997  this.helperProportions = {
9998  width: this.helper.outerWidth(),
9999  height: this.helper.outerHeight()
10000  };
10001  },
10002 
10003  _setContainment: function() {
10004 
10005  var isUserScrollable, c, ce,
10006  o = this.options,
10007  document = this.document[ 0 ];
10008 
10009  this.relativeContainer = null;
10010 
10011  if ( !o.containment ) {
10012  this.containment = null;
10013  return;
10014  }
10015 
10016  if ( o.containment === "window" ) {
10017  this.containment = [
10018  $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10019  $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10020  $( window ).scrollLeft() + $( window ).width() -
10021  this.helperProportions.width - this.margins.left,
10022  $( window ).scrollTop() +
10023  ( $( window ).height() || document.body.parentNode.scrollHeight ) -
10024  this.helperProportions.height - this.margins.top
10025  ];
10026  return;
10027  }
10028 
10029  if ( o.containment === "document" ) {
10030  this.containment = [
10031  0,
10032  0,
10033  $( document ).width() - this.helperProportions.width - this.margins.left,
10034  ( $( document ).height() || document.body.parentNode.scrollHeight ) -
10035  this.helperProportions.height - this.margins.top
10036  ];
10037  return;
10038  }
10039 
10040  if ( o.containment.constructor === Array ) {
10041  this.containment = o.containment;
10042  return;
10043  }
10044 
10045  if ( o.containment === "parent" ) {
10046  o.containment = this.helper[ 0 ].parentNode;
10047  }
10048 
10049  c = $( o.containment );
10050  ce = c[ 0 ];
10051 
10052  if ( !ce ) {
10053  return;
10054  }
10055 
10056  isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10057 
10058  this.containment = [
10059  ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10060  ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10061  ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10062  ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10063  ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10064  ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10065  ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10066  this.helperProportions.width -
10067  this.margins.left -
10068  this.margins.right,
10069  ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10070  ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10071  ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10072  this.helperProportions.height -
10073  this.margins.top -
10074  this.margins.bottom
10075  ];
10076  this.relativeContainer = c;
10077  },
10078 
10079  _convertPositionTo: function( d, pos ) {
10080 
10081  if ( !pos ) {
10082  pos = this.position;
10083  }
10084 
10085  var mod = d === "absolute" ? 1 : -1,
10086  scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10087 
10088  return {
10089  top: (
10090 
10091  // The absolute mouse position
10092  pos.top +
10093 
10094  // Only for relative positioned nodes: Relative offset from element to offset parent
10095  this.offset.relative.top * mod +
10096 
10097  // The offsetParent's offset without borders (offset + border)
10098  this.offset.parent.top * mod -
10099  ( ( this.cssPosition === "fixed" ?
10100  -this.offset.scroll.top :
10101  ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10102  ),
10103  left: (
10104 
10105  // The absolute mouse position
10106  pos.left +
10107 
10108  // Only for relative positioned nodes: Relative offset from element to offset parent
10109  this.offset.relative.left * mod +
10110 
10111  // The offsetParent's offset without borders (offset + border)
10112  this.offset.parent.left * mod -
10113  ( ( this.cssPosition === "fixed" ?
10114  -this.offset.scroll.left :
10115  ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10116  )
10117  };
10118 
10119  },
10120 
10121  _generatePosition: function( event, constrainPosition ) {
10122 
10123  var containment, co, top, left,
10124  o = this.options,
10125  scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10126  pageX = event.pageX,
10127  pageY = event.pageY;
10128 
10129  // Cache the scroll
10130  if ( !scrollIsRootNode || !this.offset.scroll ) {
10131  this.offset.scroll = {
10132  top: this.scrollParent.scrollTop(),
10133  left: this.scrollParent.scrollLeft()
10134  };
10135  }
10136 
10137  /*
10138  * - Position constraining -
10139  * Constrain the position to a mix of grid, containment.
10140  */
10141 
10142  // If we are not dragging yet, we won't check for options
10143  if ( constrainPosition ) {
10144  if ( this.containment ) {
10145  if ( this.relativeContainer ) {
10146  co = this.relativeContainer.offset();
10147  containment = [
10148  this.containment[ 0 ] + co.left,
10149  this.containment[ 1 ] + co.top,
10150  this.containment[ 2 ] + co.left,
10151  this.containment[ 3 ] + co.top
10152  ];
10153  } else {
10154  containment = this.containment;
10155  }
10156 
10157  if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10158  pageX = containment[ 0 ] + this.offset.click.left;
10159  }
10160  if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10161  pageY = containment[ 1 ] + this.offset.click.top;
10162  }
10163  if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10164  pageX = containment[ 2 ] + this.offset.click.left;
10165  }
10166  if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10167  pageY = containment[ 3 ] + this.offset.click.top;
10168  }
10169  }
10170 
10171  if ( o.grid ) {
10172 
10173  //Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10174  // argument errors in IE (see ticket #6950)
10175  top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10176  this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10177  pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10178  top - this.offset.click.top > containment[ 3 ] ) ?
10179  top :
10180  ( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10181  top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10182 
10183  left = o.grid[ 0 ] ? this.originalPageX +
10184  Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10185  this.originalPageX;
10186  pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10187  left - this.offset.click.left > containment[ 2 ] ) ?
10188  left :
10189  ( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10190  left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10191  }
10192 
10193  if ( o.axis === "y" ) {
10194  pageX = this.originalPageX;
10195  }
10196 
10197  if ( o.axis === "x" ) {
10198  pageY = this.originalPageY;
10199  }
10200  }
10201 
10202  return {
10203  top: (
10204 
10205  // The absolute mouse position
10206  pageY -
10207 
10208  // Click offset (relative to the element)
10209  this.offset.click.top -
10210 
10211  // Only for relative positioned nodes: Relative offset from element to offset parent
10212  this.offset.relative.top -
10213 
10214  // The offsetParent's offset without borders (offset + border)
10215  this.offset.parent.top +
10216  ( this.cssPosition === "fixed" ?
10217  -this.offset.scroll.top :
10218  ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10219  ),
10220  left: (
10221 
10222  // The absolute mouse position
10223  pageX -
10224 
10225  // Click offset (relative to the element)
10226  this.offset.click.left -
10227 
10228  // Only for relative positioned nodes: Relative offset from element to offset parent
10229  this.offset.relative.left -
10230 
10231  // The offsetParent's offset without borders (offset + border)
10232  this.offset.parent.left +
10233  ( this.cssPosition === "fixed" ?
10234  -this.offset.scroll.left :
10235  ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10236  )
10237  };
10238 
10239  },
10240 
10241  _clear: function() {
10242  this._removeClass( this.helper, "ui-draggable-dragging" );
10243  if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10244  this.helper.remove();
10245  }
10246  this.helper = null;
10247  this.cancelHelperRemoval = false;
10248  if ( this.destroyOnClear ) {
10249  this.destroy();
10250  }
10251  },
10252 
10253  // From now on bulk stuff - mainly helpers
10254 
10255  _trigger: function( type, event, ui ) {
10256  ui = ui || this._uiHash();
10257  $.ui.plugin.call( this, type, [ event, ui, this ], true );
10258 
10259  // Absolute position and offset (see #6884 ) have to be recalculated after plugins
10260  if ( /^(drag|start|stop)/.test( type ) ) {
10261  this.positionAbs = this._convertPositionTo( "absolute" );
10262  ui.offset = this.positionAbs;
10263  }
10264  return $.Widget.prototype._trigger.call( this, type, event, ui );
10265  },
10266 
10267  plugins: {},
10268 
10269  _uiHash: function() {
10270  return {
10271  helper: this.helper,
10272  position: this.position,
10273  originalPosition: this.originalPosition,
10274  offset: this.positionAbs
10275  };
10276  }
10277 
10278 } );
10279 
10280 $.ui.plugin.add( "draggable", "connectToSortable", {
10281  start: function( event, ui, draggable ) {
10282  var uiSortable = $.extend( {}, ui, {
10283  item: draggable.element
10284  } );
10285 
10286  draggable.sortables = [];
10287  $( draggable.options.connectToSortable ).each( function() {
10288  var sortable = $( this ).sortable( "instance" );
10289 
10290  if ( sortable && !sortable.options.disabled ) {
10291  draggable.sortables.push( sortable );
10292 
10293  // RefreshPositions is called at drag start to refresh the containerCache
10294  // which is used in drag. This ensures it's initialized and synchronized
10295  // with any changes that might have happened on the page since initialization.
10296  sortable.refreshPositions();
10297  sortable._trigger( "activate", event, uiSortable );
10298  }
10299  } );
10300  },
10301  stop: function( event, ui, draggable ) {
10302  var uiSortable = $.extend( {}, ui, {
10303  item: draggable.element
10304  } );
10305 
10306  draggable.cancelHelperRemoval = false;
10307 
10308  $.each( draggable.sortables, function() {
10309  var sortable = this;
10310 
10311  if ( sortable.isOver ) {
10312  sortable.isOver = 0;
10313 
10314  // Allow this sortable to handle removing the helper
10315  draggable.cancelHelperRemoval = true;
10316  sortable.cancelHelperRemoval = false;
10317 
10318  // Use _storedCSS To restore properties in the sortable,
10319  // as this also handles revert (#9675) since the draggable
10320  // may have modified them in unexpected ways (#8809)
10321  sortable._storedCSS = {
10322  position: sortable.placeholder.css( "position" ),
10323  top: sortable.placeholder.css( "top" ),
10324  left: sortable.placeholder.css( "left" )
10325  };
10326 
10327  sortable._mouseStop( event );
10328 
10329  // Once drag has ended, the sortable should return to using
10330  // its original helper, not the shared helper from draggable
10331  sortable.options.helper = sortable.options._helper;
10332  } else {
10333 
10334  // Prevent this Sortable from removing the helper.
10335  // However, don't set the draggable to remove the helper
10336  // either as another connected Sortable may yet handle the removal.
10337  sortable.cancelHelperRemoval = true;
10338 
10339  sortable._trigger( "deactivate", event, uiSortable );
10340  }
10341  } );
10342  },
10343  drag: function( event, ui, draggable ) {
10344  $.each( draggable.sortables, function() {
10345  var innermostIntersecting = false,
10346  sortable = this;
10347 
10348  // Copy over variables that sortable's _intersectsWith uses
10349  sortable.positionAbs = draggable.positionAbs;
10350  sortable.helperProportions = draggable.helperProportions;
10351  sortable.offset.click = draggable.offset.click;
10352 
10353  if ( sortable._intersectsWith( sortable.containerCache ) ) {
10354  innermostIntersecting = true;
10355 
10356  $.each( draggable.sortables, function() {
10357 
10358  // Copy over variables that sortable's _intersectsWith uses
10359  this.positionAbs = draggable.positionAbs;
10360  this.helperProportions = draggable.helperProportions;
10361  this.offset.click = draggable.offset.click;
10362 
10363  if ( this !== sortable &&
10364  this._intersectsWith( this.containerCache ) &&
10365  $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10366  innermostIntersecting = false;
10367  }
10368 
10369  return innermostIntersecting;
10370  } );
10371  }
10372 
10373  if ( innermostIntersecting ) {
10374 
10375  // If it intersects, we use a little isOver variable and set it once,
10376  // so that the move-in stuff gets fired only once.
10377  if ( !sortable.isOver ) {
10378  sortable.isOver = 1;
10379 
10380  // Store draggable's parent in case we need to reappend to it later.
10381  draggable._parent = ui.helper.parent();
10382 
10383  sortable.currentItem = ui.helper
10384  .appendTo( sortable.element )
10385  .data( "ui-sortable-item", true );
10386 
10387  // Store helper option to later restore it
10388  sortable.options._helper = sortable.options.helper;
10389 
10390  sortable.options.helper = function() {
10391  return ui.helper[ 0 ];
10392  };
10393 
10394  // Fire the start events of the sortable with our passed browser event,
10395  // and our own helper (so it doesn't create a new one)
10396  event.target = sortable.currentItem[ 0 ];
10397  sortable._mouseCapture( event, true );
10398  sortable._mouseStart( event, true, true );
10399 
10400  // Because the browser event is way off the new appended portlet,
10401  // modify necessary variables to reflect the changes
10402  sortable.offset.click.top = draggable.offset.click.top;
10403  sortable.offset.click.left = draggable.offset.click.left;
10404  sortable.offset.parent.left -= draggable.offset.parent.left -
10405  sortable.offset.parent.left;
10406  sortable.offset.parent.top -= draggable.offset.parent.top -
10407  sortable.offset.parent.top;
10408 
10409  draggable._trigger( "toSortable", event );
10410 
10411  // Inform draggable that the helper is in a valid drop zone,
10412  // used solely in the revert option to handle "valid/invalid".
10413  draggable.dropped = sortable.element;
10414 
10415  // Need to refreshPositions of all sortables in the case that
10416  // adding to one sortable changes the location of the other sortables (#9675)
10417  $.each( draggable.sortables, function() {
10418  this.refreshPositions();
10419  } );
10420 
10421  // Hack so receive/update callbacks work (mostly)
10422  draggable.currentItem = draggable.element;
10423  sortable.fromOutside = draggable;
10424  }
10425 
10426  if ( sortable.currentItem ) {
10427  sortable._mouseDrag( event );
10428 
10429  // Copy the sortable's position because the draggable's can potentially reflect
10430  // a relative position, while sortable is always absolute, which the dragged
10431  // element has now become. (#8809)
10432  ui.position = sortable.position;
10433  }
10434  } else {
10435 
10436  // If it doesn't intersect with the sortable, and it intersected before,
10437  // we fake the drag stop of the sortable, but make sure it doesn't remove
10438  // the helper by using cancelHelperRemoval.
10439  if ( sortable.isOver ) {
10440 
10441  sortable.isOver = 0;
10442  sortable.cancelHelperRemoval = true;
10443 
10444  // Calling sortable's mouseStop would trigger a revert,
10445  // so revert must be temporarily false until after mouseStop is called.
10446  sortable.options._revert = sortable.options.revert;
10447  sortable.options.revert = false;
10448 
10449  sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10450  sortable._mouseStop( event, true );
10451 
10452  // Restore sortable behaviors that were modfied
10453  // when the draggable entered the sortable area (#9481)
10454  sortable.options.revert = sortable.options._revert;
10455  sortable.options.helper = sortable.options._helper;
10456 
10457  if ( sortable.placeholder ) {
10458  sortable.placeholder.remove();
10459  }
10460 
10461  // Restore and recalculate the draggable's offset considering the sortable
10462  // may have modified them in unexpected ways. (#8809, #10669)
10463  ui.helper.appendTo( draggable._parent );
10464  draggable._refreshOffsets( event );
10465  ui.position = draggable._generatePosition( event, true );
10466 
10467  draggable._trigger( "fromSortable", event );
10468 
10469  // Inform draggable that the helper is no longer in a valid drop zone
10470  draggable.dropped = false;
10471 
10472  // Need to refreshPositions of all sortables just in case removing
10473  // from one sortable changes the location of other sortables (#9675)
10474  $.each( draggable.sortables, function() {
10475  this.refreshPositions();
10476  } );
10477  }
10478  }
10479  } );
10480  }
10481 } );
10482 
10483 $.ui.plugin.add( "draggable", "cursor", {
10484  start: function( event, ui, instance ) {
10485  var t = $( "body" ),
10486  o = instance.options;
10487 
10488  if ( t.css( "cursor" ) ) {
10489  o._cursor = t.css( "cursor" );
10490  }
10491  t.css( "cursor", o.cursor );
10492  },
10493  stop: function( event, ui, instance ) {
10494  var o = instance.options;
10495  if ( o._cursor ) {
10496  $( "body" ).css( "cursor", o._cursor );
10497  }
10498  }
10499 } );
10500 
10501 $.ui.plugin.add( "draggable", "opacity", {
10502  start: function( event, ui, instance ) {
10503  var t = $( ui.helper ),
10504  o = instance.options;
10505  if ( t.css( "opacity" ) ) {
10506  o._opacity = t.css( "opacity" );
10507  }
10508  t.css( "opacity", o.opacity );
10509  },
10510  stop: function( event, ui, instance ) {
10511  var o = instance.options;
10512  if ( o._opacity ) {
10513  $( ui.helper ).css( "opacity", o._opacity );
10514  }
10515  }
10516 } );
10517 
10518 $.ui.plugin.add( "draggable", "scroll", {
10519  start: function( event, ui, i ) {
10520  if ( !i.scrollParentNotHidden ) {
10521  i.scrollParentNotHidden = i.helper.scrollParent( false );
10522  }
10523 
10524  if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10525  i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10526  i.overflowOffset = i.scrollParentNotHidden.offset();
10527  }
10528  },
10529  drag: function( event, ui, i ) {
10530 
10531  var o = i.options,
10532  scrolled = false,
10533  scrollParent = i.scrollParentNotHidden[ 0 ],
10534  document = i.document[ 0 ];
10535 
10536  if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10537  if ( !o.axis || o.axis !== "x" ) {
10538  if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10539  o.scrollSensitivity ) {
10540  scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10541  } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10542  scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10543  }
10544  }
10545 
10546  if ( !o.axis || o.axis !== "y" ) {
10547  if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10548  o.scrollSensitivity ) {
10549  scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10550  } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10551  scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10552  }
10553  }
10554 
10555  } else {
10556 
10557  if ( !o.axis || o.axis !== "x" ) {
10558  if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10559  scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10560  } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10561  o.scrollSensitivity ) {
10562  scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10563  }
10564  }
10565 
10566  if ( !o.axis || o.axis !== "y" ) {
10567  if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10568  scrolled = $( document ).scrollLeft(
10569  $( document ).scrollLeft() - o.scrollSpeed
10570  );
10571  } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10572  o.scrollSensitivity ) {
10573  scrolled = $( document ).scrollLeft(
10574  $( document ).scrollLeft() + o.scrollSpeed
10575  );
10576  }
10577  }
10578 
10579  }
10580 
10581  if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10582  $.ui.ddmanager.prepareOffsets( i, event );
10583  }
10584 
10585  }
10586 } );
10587 
10588 $.ui.plugin.add( "draggable", "snap", {
10589  start: function( event, ui, i ) {
10590 
10591  var o = i.options;
10592 
10593  i.snapElements = [];
10594 
10595  $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10596  .each( function() {
10597  var $t = $( this ),
10598  $o = $t.offset();
10599  if ( this !== i.element[ 0 ] ) {
10600  i.snapElements.push( {
10601  item: this,
10602  width: $t.outerWidth(), height: $t.outerHeight(),
10603  top: $o.top, left: $o.left
10604  } );
10605  }
10606  } );
10607 
10608  },
10609  drag: function( event, ui, inst ) {
10610 
10611  var ts, bs, ls, rs, l, r, t, b, i, first,
10612  o = inst.options,
10613  d = o.snapTolerance,
10614  x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10615  y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10616 
10617  for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10618 
10619  l = inst.snapElements[ i ].left - inst.margins.left;
10620  r = l + inst.snapElements[ i ].width;
10621  t = inst.snapElements[ i ].top - inst.margins.top;
10622  b = t + inst.snapElements[ i ].height;
10623 
10624  if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10625  !$.contains( inst.snapElements[ i ].item.ownerDocument,
10626  inst.snapElements[ i ].item ) ) {
10627  if ( inst.snapElements[ i ].snapping ) {
10628  ( inst.options.snap.release &&
10629  inst.options.snap.release.call(
10630  inst.element,
10631  event,
10632  $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10633  ) );
10634  }
10635  inst.snapElements[ i ].snapping = false;
10636  continue;
10637  }
10638 
10639  if ( o.snapMode !== "inner" ) {
10640  ts = Math.abs( t - y2 ) <= d;
10641  bs = Math.abs( b - y1 ) <= d;
10642  ls = Math.abs( l - x2 ) <= d;
10643  rs = Math.abs( r - x1 ) <= d;
10644  if ( ts ) {
10645  ui.position.top = inst._convertPositionTo( "relative", {
10646  top: t - inst.helperProportions.height,
10647  left: 0
10648  } ).top;
10649  }
10650  if ( bs ) {
10651  ui.position.top = inst._convertPositionTo( "relative", {
10652  top: b,
10653  left: 0
10654  } ).top;
10655  }
10656  if ( ls ) {
10657  ui.position.left = inst._convertPositionTo( "relative", {
10658  top: 0,
10659  left: l - inst.helperProportions.width
10660  } ).left;
10661  }
10662  if ( rs ) {
10663  ui.position.left = inst._convertPositionTo( "relative", {
10664  top: 0,
10665  left: r
10666  } ).left;
10667  }
10668  }
10669 
10670  first = ( ts || bs || ls || rs );
10671 
10672  if ( o.snapMode !== "outer" ) {
10673  ts = Math.abs( t - y1 ) <= d;
10674  bs = Math.abs( b - y2 ) <= d;
10675  ls = Math.abs( l - x1 ) <= d;
10676  rs = Math.abs( r - x2 ) <= d;
10677  if ( ts ) {
10678  ui.position.top = inst._convertPositionTo( "relative", {
10679  top: t,
10680  left: 0
10681  } ).top;
10682  }
10683  if ( bs ) {
10684  ui.position.top = inst._convertPositionTo( "relative", {
10685  top: b - inst.helperProportions.height,
10686  left: 0
10687  } ).top;
10688  }
10689  if ( ls ) {
10690  ui.position.left = inst._convertPositionTo( "relative", {
10691  top: 0,
10692  left: l
10693  } ).left;
10694  }
10695  if ( rs ) {
10696  ui.position.left = inst._convertPositionTo( "relative", {
10697  top: 0,
10698  left: r - inst.helperProportions.width
10699  } ).left;
10700  }
10701  }
10702 
10703  if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10704  ( inst.options.snap.snap &&
10705  inst.options.snap.snap.call(
10706  inst.element,
10707  event,
10708  $.extend( inst._uiHash(), {
10709  snapItem: inst.snapElements[ i ].item
10710  } ) ) );
10711  }
10712  inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10713 
10714  }
10715 
10716  }
10717 } );
10718 
10719 $.ui.plugin.add( "draggable", "stack", {
10720  start: function( event, ui, instance ) {
10721  var min,
10722  o = instance.options,
10723  group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10724  return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10725  ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10726  } );
10727 
10728  if ( !group.length ) { return; }
10729 
10730  min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10731  $( group ).each( function( i ) {
10732  $( this ).css( "zIndex", min + i );
10733  } );
10734  this.css( "zIndex", ( min + group.length ) );
10735  }
10736 } );
10737 
10738 $.ui.plugin.add( "draggable", "zIndex", {
10739  start: function( event, ui, instance ) {
10740  var t = $( ui.helper ),
10741  o = instance.options;
10742 
10743  if ( t.css( "zIndex" ) ) {
10744  o._zIndex = t.css( "zIndex" );
10745  }
10746  t.css( "zIndex", o.zIndex );
10747  },
10748  stop: function( event, ui, instance ) {
10749  var o = instance.options;
10750 
10751  if ( o._zIndex ) {
10752  $( ui.helper ).css( "zIndex", o._zIndex );
10753  }
10754  }
10755 } );
10756 
10757 var widgetsDraggable = $.ui.draggable;
10758 
10759 
10769 //>>label: Resizable
10770 //>>group: Interactions
10771 //>>description: Enables resize functionality for any element.
10772 //>>docs: http://api.jqueryui.com/resizable/
10773 //>>demos: http://jqueryui.com/resizable/
10774 //>>css.structure: ../../themes/base/core.css
10775 //>>css.structure: ../../themes/base/resizable.css
10776 //>>css.theme: ../../themes/base/theme.css
10777 
10778 
10779 
10780 $.widget( "ui.resizable", $.ui.mouse, {
10781  version: "1.12.1",
10782  widgetEventPrefix: "resize",
10783  options: {
10784  alsoResize: false,
10785  animate: false,
10786  animateDuration: "slow",
10787  animateEasing: "swing",
10788  aspectRatio: false,
10789  autoHide: false,
10790  classes: {
10791  "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
10792  },
10793  containment: false,
10794  ghost: false,
10795  grid: false,
10796  handles: "e,s,se",
10797  helper: false,
10798  maxHeight: null,
10799  maxWidth: null,
10800  minHeight: 10,
10801  minWidth: 10,
10802 
10803  // See #7960
10804  zIndex: 90,
10805 
10806  // Callbacks
10807  resize: null,
10808  start: null,
10809  stop: null
10810  },
10811 
10812  _num: function( value ) {
10813  return parseFloat( value ) || 0;
10814  },
10815 
10816  _isNumber: function( value ) {
10817  return !isNaN( parseFloat( value ) );
10818  },
10819 
10820  _hasScroll: function( el, a ) {
10821 
10822  if ( $( el ).css( "overflow" ) === "hidden" ) {
10823  return false;
10824  }
10825 
10826  var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
10827  has = false;
10828 
10829  if ( el[ scroll ] > 0 ) {
10830  return true;
10831  }
10832 
10833  // TODO: determine which cases actually cause this to happen
10834  // if the element doesn't have the scroll set, see if it's possible to
10835  // set the scroll
10836  el[ scroll ] = 1;
10837  has = ( el[ scroll ] > 0 );
10838  el[ scroll ] = 0;
10839  return has;
10840  },
10841 
10842  _create: function() {
10843 
10844  var margins,
10845  o = this.options,
10846  that = this;
10847  this._addClass( "ui-resizable" );
10848 
10849  $.extend( this, {
10850  _aspectRatio: !!( o.aspectRatio ),
10851  aspectRatio: o.aspectRatio,
10852  originalElement: this.element,
10853  _proportionallyResizeElements: [],
10854  _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
10855  } );
10856 
10857  // Wrap the element if it cannot hold child nodes
10858  if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
10859 
10860  this.element.wrap(
10861  $( "<div class='ui-wrapper' style='overflow: hidden;'></div>" ).css( {
10862  position: this.element.css( "position" ),
10863  width: this.element.outerWidth(),
10864  height: this.element.outerHeight(),
10865  top: this.element.css( "top" ),
10866  left: this.element.css( "left" )
10867  } )
10868  );
10869 
10870  this.element = this.element.parent().data(
10871  "ui-resizable", this.element.resizable( "instance" )
10872  );
10873 
10874  this.elementIsWrapper = true;
10875 
10876  margins = {
10877  marginTop: this.originalElement.css( "marginTop" ),
10878  marginRight: this.originalElement.css( "marginRight" ),
10879  marginBottom: this.originalElement.css( "marginBottom" ),
10880  marginLeft: this.originalElement.css( "marginLeft" )
10881  };
10882 
10883  this.element.css( margins );
10884  this.originalElement.css( "margin", 0 );
10885 
10886  // support: Safari
10887  // Prevent Safari textarea resize
10888  this.originalResizeStyle = this.originalElement.css( "resize" );
10889  this.originalElement.css( "resize", "none" );
10890 
10891  this._proportionallyResizeElements.push( this.originalElement.css( {
10892  position: "static",
10893  zoom: 1,
10894  display: "block"
10895  } ) );
10896 
10897  // Support: IE9
10898  // avoid IE jump (hard set the margin)
10899  this.originalElement.css( margins );
10900 
10901  this._proportionallyResize();
10902  }
10903 
10904  this._setupHandles();
10905 
10906  if ( o.autoHide ) {
10907  $( this.element )
10908  .on( "mouseenter", function() {
10909  if ( o.disabled ) {
10910  return;
10911  }
10912  that._removeClass( "ui-resizable-autohide" );
10913  that._handles.show();
10914  } )
10915  .on( "mouseleave", function() {
10916  if ( o.disabled ) {
10917  return;
10918  }
10919  if ( !that.resizing ) {
10920  that._addClass( "ui-resizable-autohide" );
10921  that._handles.hide();
10922  }
10923  } );
10924  }
10925 
10926  this._mouseInit();
10927  },
10928 
10929  _destroy: function() {
10930 
10931  this._mouseDestroy();
10932 
10933  var wrapper,
10934  _destroy = function( exp ) {
10935  $( exp )
10936  .removeData( "resizable" )
10937  .removeData( "ui-resizable" )
10938  .off( ".resizable" )
10939  .find( ".ui-resizable-handle" )
10940  .remove();
10941  };
10942 
10943  // TODO: Unwrap at same DOM position
10944  if ( this.elementIsWrapper ) {
10945  _destroy( this.element );
10946  wrapper = this.element;
10947  this.originalElement.css( {
10948  position: wrapper.css( "position" ),
10949  width: wrapper.outerWidth(),
10950  height: wrapper.outerHeight(),
10951  top: wrapper.css( "top" ),
10952  left: wrapper.css( "left" )
10953  } ).insertAfter( wrapper );
10954  wrapper.remove();
10955  }
10956 
10957  this.originalElement.css( "resize", this.originalResizeStyle );
10958  _destroy( this.originalElement );
10959 
10960  return this;
10961  },
10962 
10963  _setOption: function( key, value ) {
10964  this._super( key, value );
10965 
10966  switch ( key ) {
10967  case "handles":
10968  this._removeHandles();
10969  this._setupHandles();
10970  break;
10971  default:
10972  break;
10973  }
10974  },
10975 
10976  _setupHandles: function() {
10977  var o = this.options, handle, i, n, hname, axis, that = this;
10978  this.handles = o.handles ||
10979  ( !$( ".ui-resizable-handle", this.element ).length ?
10980  "e,s,se" : {
10981  n: ".ui-resizable-n",
10982  e: ".ui-resizable-e",
10983  s: ".ui-resizable-s",
10984  w: ".ui-resizable-w",
10985  se: ".ui-resizable-se",
10986  sw: ".ui-resizable-sw",
10987  ne: ".ui-resizable-ne",
10988  nw: ".ui-resizable-nw"
10989  } );
10990 
10991  this._handles = $();
10992  if ( this.handles.constructor === String ) {
10993 
10994  if ( this.handles === "all" ) {
10995  this.handles = "n,e,s,w,se,sw,ne,nw";
10996  }
10997 
10998  n = this.handles.split( "," );
10999  this.handles = {};
11000 
11001  for ( i = 0; i < n.length; i++ ) {
11002 
11003  handle = $.trim( n[ i ] );
11004  hname = "ui-resizable-" + handle;
11005  axis = $( "<div>" );
11006  this._addClass( axis, "ui-resizable-handle " + hname );
11007 
11008  axis.css( { zIndex: o.zIndex } );
11009 
11010  this.handles[ handle ] = ".ui-resizable-" + handle;
11011  this.element.append( axis );
11012  }
11013 
11014  }
11015 
11016  this._renderAxis = function( target ) {
11017 
11018  var i, axis, padPos, padWrapper;
11019 
11020  target = target || this.element;
11021 
11022  for ( i in this.handles ) {
11023 
11024  if ( this.handles[ i ].constructor === String ) {
11025  this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11026  } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11027  this.handles[ i ] = $( this.handles[ i ] );
11028  this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11029  }
11030 
11031  if ( this.elementIsWrapper &&
11032  this.originalElement[ 0 ]
11033  .nodeName
11034  .match( /^(textarea|input|select|button)$/i ) ) {
11035  axis = $( this.handles[ i ], this.element );
11036 
11037  padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11038  axis.outerHeight() :
11039  axis.outerWidth();
11040 
11041  padPos = [ "padding",
11042  /ne|nw|n/.test( i ) ? "Top" :
11043  /se|sw|s/.test( i ) ? "Bottom" :
11044  /^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11045 
11046  target.css( padPos, padWrapper );
11047 
11048  this._proportionallyResize();
11049  }
11050 
11051  this._handles = this._handles.add( this.handles[ i ] );
11052  }
11053  };
11054 
11055  // TODO: make renderAxis a prototype function
11056  this._renderAxis( this.element );
11057 
11058  this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11059  this._handles.disableSelection();
11060 
11061  this._handles.on( "mouseover", function() {
11062  if ( !that.resizing ) {
11063  if ( this.className ) {
11064  axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11065  }
11066  that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11067  }
11068  } );
11069 
11070  if ( o.autoHide ) {
11071  this._handles.hide();
11072  this._addClass( "ui-resizable-autohide" );
11073  }
11074  },
11075 
11076  _removeHandles: function() {
11077  this._handles.remove();
11078  },
11079 
11080  _mouseCapture: function( event ) {
11081  var i, handle,
11082  capture = false;
11083 
11084  for ( i in this.handles ) {
11085  handle = $( this.handles[ i ] )[ 0 ];
11086  if ( handle === event.target || $.contains( handle, event.target ) ) {
11087  capture = true;
11088  }
11089  }
11090 
11091  return !this.options.disabled && capture;
11092  },
11093 
11094  _mouseStart: function( event ) {
11095 
11096  var curleft, curtop, cursor,
11097  o = this.options,
11098  el = this.element;
11099 
11100  this.resizing = true;
11101 
11102  this._renderProxy();
11103 
11104  curleft = this._num( this.helper.css( "left" ) );
11105  curtop = this._num( this.helper.css( "top" ) );
11106 
11107  if ( o.containment ) {
11108  curleft += $( o.containment ).scrollLeft() || 0;
11109  curtop += $( o.containment ).scrollTop() || 0;
11110  }
11111 
11112  this.offset = this.helper.offset();
11113  this.position = { left: curleft, top: curtop };
11114 
11115  this.size = this._helper ? {
11116  width: this.helper.width(),
11117  height: this.helper.height()
11118  } : {
11119  width: el.width(),
11120  height: el.height()
11121  };
11122 
11123  this.originalSize = this._helper ? {
11124  width: el.outerWidth(),
11125  height: el.outerHeight()
11126  } : {
11127  width: el.width(),
11128  height: el.height()
11129  };
11130 
11131  this.sizeDiff = {
11132  width: el.outerWidth() - el.width(),
11133  height: el.outerHeight() - el.height()
11134  };
11135 
11136  this.originalPosition = { left: curleft, top: curtop };
11137  this.originalMousePosition = { left: event.pageX, top: event.pageY };
11138 
11139  this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11140  o.aspectRatio :
11141  ( ( this.originalSize.width / this.originalSize.height ) || 1 );
11142 
11143  cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11144  $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11145 
11146  this._addClass( "ui-resizable-resizing" );
11147  this._propagate( "start", event );
11148  return true;
11149  },
11150 
11151  _mouseDrag: function( event ) {
11152 
11153  var data, props,
11154  smp = this.originalMousePosition,
11155  a = this.axis,
11156  dx = ( event.pageX - smp.left ) || 0,
11157  dy = ( event.pageY - smp.top ) || 0,
11158  trigger = this._change[ a ];
11159 
11160  this._updatePrevProperties();
11161 
11162  if ( !trigger ) {
11163  return false;
11164  }
11165 
11166  data = trigger.apply( this, [ event, dx, dy ] );
11167 
11168  this._updateVirtualBoundaries( event.shiftKey );
11169  if ( this._aspectRatio || event.shiftKey ) {
11170  data = this._updateRatio( data, event );
11171  }
11172 
11173  data = this._respectSize( data, event );
11174 
11175  this._updateCache( data );
11176 
11177  this._propagate( "resize", event );
11178 
11179  props = this._applyChanges();
11180 
11181  if ( !this._helper && this._proportionallyResizeElements.length ) {
11182  this._proportionallyResize();
11183  }
11184 
11185  if ( !$.isEmptyObject( props ) ) {
11186  this._updatePrevProperties();
11187  this._trigger( "resize", event, this.ui() );
11188  this._applyChanges();
11189  }
11190 
11191  return false;
11192  },
11193 
11194  _mouseStop: function( event ) {
11195 
11196  this.resizing = false;
11197  var pr, ista, soffseth, soffsetw, s, left, top,
11198  o = this.options, that = this;
11199 
11200  if ( this._helper ) {
11201 
11202  pr = this._proportionallyResizeElements;
11203  ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11204  soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11205  soffsetw = ista ? 0 : that.sizeDiff.width;
11206 
11207  s = {
11208  width: ( that.helper.width() - soffsetw ),
11209  height: ( that.helper.height() - soffseth )
11210  };
11211  left = ( parseFloat( that.element.css( "left" ) ) +
11212  ( that.position.left - that.originalPosition.left ) ) || null;
11213  top = ( parseFloat( that.element.css( "top" ) ) +
11214  ( that.position.top - that.originalPosition.top ) ) || null;
11215 
11216  if ( !o.animate ) {
11217  this.element.css( $.extend( s, { top: top, left: left } ) );
11218  }
11219 
11220  that.helper.height( that.size.height );
11221  that.helper.width( that.size.width );
11222 
11223  if ( this._helper && !o.animate ) {
11224  this._proportionallyResize();
11225  }
11226  }
11227 
11228  $( "body" ).css( "cursor", "auto" );
11229 
11230  this._removeClass( "ui-resizable-resizing" );
11231 
11232  this._propagate( "stop", event );
11233 
11234  if ( this._helper ) {
11235  this.helper.remove();
11236  }
11237 
11238  return false;
11239 
11240  },
11241 
11242  _updatePrevProperties: function() {
11243  this.prevPosition = {
11244  top: this.position.top,
11245  left: this.position.left
11246  };
11247  this.prevSize = {
11248  width: this.size.width,
11249  height: this.size.height
11250  };
11251  },
11252 
11253  _applyChanges: function() {
11254  var props = {};
11255 
11256  if ( this.position.top !== this.prevPosition.top ) {
11257  props.top = this.position.top + "px";
11258  }
11259  if ( this.position.left !== this.prevPosition.left ) {
11260  props.left = this.position.left + "px";
11261  }
11262  if ( this.size.width !== this.prevSize.width ) {
11263  props.width = this.size.width + "px";
11264  }
11265  if ( this.size.height !== this.prevSize.height ) {
11266  props.height = this.size.height + "px";
11267  }
11268 
11269  this.helper.css( props );
11270 
11271  return props;
11272  },
11273 
11274  _updateVirtualBoundaries: function( forceAspectRatio ) {
11275  var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11276  o = this.options;
11277 
11278  b = {
11279  minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11280  maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11281  minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11282  maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11283  };
11284 
11285  if ( this._aspectRatio || forceAspectRatio ) {
11286  pMinWidth = b.minHeight * this.aspectRatio;
11287  pMinHeight = b.minWidth / this.aspectRatio;
11288  pMaxWidth = b.maxHeight * this.aspectRatio;
11289  pMaxHeight = b.maxWidth / this.aspectRatio;
11290 
11291  if ( pMinWidth > b.minWidth ) {
11292  b.minWidth = pMinWidth;
11293  }
11294  if ( pMinHeight > b.minHeight ) {
11295  b.minHeight = pMinHeight;
11296  }
11297  if ( pMaxWidth < b.maxWidth ) {
11298  b.maxWidth = pMaxWidth;
11299  }
11300  if ( pMaxHeight < b.maxHeight ) {
11301  b.maxHeight = pMaxHeight;
11302  }
11303  }
11304  this._vBoundaries = b;
11305  },
11306 
11307  _updateCache: function( data ) {
11308  this.offset = this.helper.offset();
11309  if ( this._isNumber( data.left ) ) {
11310  this.position.left = data.left;
11311  }
11312  if ( this._isNumber( data.top ) ) {
11313  this.position.top = data.top;
11314  }
11315  if ( this._isNumber( data.height ) ) {
11316  this.size.height = data.height;
11317  }
11318  if ( this._isNumber( data.width ) ) {
11319  this.size.width = data.width;
11320  }
11321  },
11322 
11323  _updateRatio: function( data ) {
11324 
11325  var cpos = this.position,
11326  csize = this.size,
11327  a = this.axis;
11328 
11329  if ( this._isNumber( data.height ) ) {
11330  data.width = ( data.height * this.aspectRatio );
11331  } else if ( this._isNumber( data.width ) ) {
11332  data.height = ( data.width / this.aspectRatio );
11333  }
11334 
11335  if ( a === "sw" ) {
11336  data.left = cpos.left + ( csize.width - data.width );
11337  data.top = null;
11338  }
11339  if ( a === "nw" ) {
11340  data.top = cpos.top + ( csize.height - data.height );
11341  data.left = cpos.left + ( csize.width - data.width );
11342  }
11343 
11344  return data;
11345  },
11346 
11347  _respectSize: function( data ) {
11348 
11349  var o = this._vBoundaries,
11350  a = this.axis,
11351  ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11352  ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11353  isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11354  isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11355  dw = this.originalPosition.left + this.originalSize.width,
11356  dh = this.originalPosition.top + this.originalSize.height,
11357  cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11358  if ( isminw ) {
11359  data.width = o.minWidth;
11360  }
11361  if ( isminh ) {
11362  data.height = o.minHeight;
11363  }
11364  if ( ismaxw ) {
11365  data.width = o.maxWidth;
11366  }
11367  if ( ismaxh ) {
11368  data.height = o.maxHeight;
11369  }
11370 
11371  if ( isminw && cw ) {
11372  data.left = dw - o.minWidth;
11373  }
11374  if ( ismaxw && cw ) {
11375  data.left = dw - o.maxWidth;
11376  }
11377  if ( isminh && ch ) {
11378  data.top = dh - o.minHeight;
11379  }
11380  if ( ismaxh && ch ) {
11381  data.top = dh - o.maxHeight;
11382  }
11383 
11384  // Fixing jump error on top/left - bug #2330
11385  if ( !data.width && !data.height && !data.left && data.top ) {
11386  data.top = null;
11387  } else if ( !data.width && !data.height && !data.top && data.left ) {
11388  data.left = null;
11389  }
11390 
11391  return data;
11392  },
11393 
11394  _getPaddingPlusBorderDimensions: function( element ) {
11395  var i = 0,
11396  widths = [],
11397  borders = [
11398  element.css( "borderTopWidth" ),
11399  element.css( "borderRightWidth" ),
11400  element.css( "borderBottomWidth" ),
11401  element.css( "borderLeftWidth" )
11402  ],
11403  paddings = [
11404  element.css( "paddingTop" ),
11405  element.css( "paddingRight" ),
11406  element.css( "paddingBottom" ),
11407  element.css( "paddingLeft" )
11408  ];
11409 
11410  for ( ; i < 4; i++ ) {
11411  widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11412  widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11413  }
11414 
11415  return {
11416  height: widths[ 0 ] + widths[ 2 ],
11417  width: widths[ 1 ] + widths[ 3 ]
11418  };
11419  },
11420 
11421  _proportionallyResize: function() {
11422 
11423  if ( !this._proportionallyResizeElements.length ) {
11424  return;
11425  }
11426 
11427  var prel,
11428  i = 0,
11429  element = this.helper || this.element;
11430 
11431  for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11432 
11433  prel = this._proportionallyResizeElements[ i ];
11434 
11435  // TODO: Seems like a bug to cache this.outerDimensions
11436  // considering that we are in a loop.
11437  if ( !this.outerDimensions ) {
11438  this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11439  }
11440 
11441  prel.css( {
11442  height: ( element.height() - this.outerDimensions.height ) || 0,
11443  width: ( element.width() - this.outerDimensions.width ) || 0
11444  } );
11445 
11446  }
11447 
11448  },
11449 
11450  _renderProxy: function() {
11451 
11452  var el = this.element, o = this.options;
11453  this.elementOffset = el.offset();
11454 
11455  if ( this._helper ) {
11456 
11457  this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );
11458 
11459  this._addClass( this.helper, this._helper );
11460  this.helper.css( {
11461  width: this.element.outerWidth(),
11462  height: this.element.outerHeight(),
11463  position: "absolute",
11464  left: this.elementOffset.left + "px",
11465  top: this.elementOffset.top + "px",
11466  zIndex: ++o.zIndex //TODO: Don't modify option
11467  } );
11468 
11469  this.helper
11470  .appendTo( "body" )
11471  .disableSelection();
11472 
11473  } else {
11474  this.helper = this.element;
11475  }
11476 
11477  },
11478 
11479  _change: {
11480  e: function( event, dx ) {
11481  return { width: this.originalSize.width + dx };
11482  },
11483  w: function( event, dx ) {
11484  var cs = this.originalSize, sp = this.originalPosition;
11485  return { left: sp.left + dx, width: cs.width - dx };
11486  },
11487  n: function( event, dx, dy ) {
11488  var cs = this.originalSize, sp = this.originalPosition;
11489  return { top: sp.top + dy, height: cs.height - dy };
11490  },
11491  s: function( event, dx, dy ) {
11492  return { height: this.originalSize.height + dy };
11493  },
11494  se: function( event, dx, dy ) {
11495  return $.extend( this._change.s.apply( this, arguments ),
11496  this._change.e.apply( this, [ event, dx, dy ] ) );
11497  },
11498  sw: function( event, dx, dy ) {
11499  return $.extend( this._change.s.apply( this, arguments ),
11500  this._change.w.apply( this, [ event, dx, dy ] ) );
11501  },
11502  ne: function( event, dx, dy ) {
11503  return $.extend( this._change.n.apply( this, arguments ),
11504  this._change.e.apply( this, [ event, dx, dy ] ) );
11505  },
11506  nw: function( event, dx, dy ) {
11507  return $.extend( this._change.n.apply( this, arguments ),
11508  this._change.w.apply( this, [ event, dx, dy ] ) );
11509  }
11510  },
11511 
11512  _propagate: function( n, event ) {
11513  $.ui.plugin.call( this, n, [ event, this.ui() ] );
11514  ( n !== "resize" && this._trigger( n, event, this.ui() ) );
11515  },
11516 
11517  plugins: {},
11518 
11519  ui: function() {
11520  return {
11521  originalElement: this.originalElement,
11522  element: this.element,
11523  helper: this.helper,
11524  position: this.position,
11525  size: this.size,
11526  originalSize: this.originalSize,
11527  originalPosition: this.originalPosition
11528  };
11529  }
11530 
11531 } );
11532 
11533 /*
11534  * Resizable Extensions
11535  */
11536 
11537 $.ui.plugin.add( "resizable", "animate", {
11538 
11539  stop: function( event ) {
11540  var that = $( this ).resizable( "instance" ),
11541  o = that.options,
11542  pr = that._proportionallyResizeElements,
11543  ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11544  soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11545  soffsetw = ista ? 0 : that.sizeDiff.width,
11546  style = {
11547  width: ( that.size.width - soffsetw ),
11548  height: ( that.size.height - soffseth )
11549  },
11550  left = ( parseFloat( that.element.css( "left" ) ) +
11551  ( that.position.left - that.originalPosition.left ) ) || null,
11552  top = ( parseFloat( that.element.css( "top" ) ) +
11553  ( that.position.top - that.originalPosition.top ) ) || null;
11554 
11555  that.element.animate(
11556  $.extend( style, top && left ? { top: top, left: left } : {} ), {
11557  duration: o.animateDuration,
11558  easing: o.animateEasing,
11559  step: function() {
11560 
11561  var data = {
11562  width: parseFloat( that.element.css( "width" ) ),
11563  height: parseFloat( that.element.css( "height" ) ),
11564  top: parseFloat( that.element.css( "top" ) ),
11565  left: parseFloat( that.element.css( "left" ) )
11566  };
11567 
11568  if ( pr && pr.length ) {
11569  $( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11570  }
11571 
11572  // Propagating resize, and updating values for each animation step
11573  that._updateCache( data );
11574  that._propagate( "resize", event );
11575 
11576  }
11577  }
11578  );
11579  }
11580 
11581 } );
11582 
11583 $.ui.plugin.add( "resizable", "containment", {
11584 
11585  start: function() {
11586  var element, p, co, ch, cw, width, height,
11587  that = $( this ).resizable( "instance" ),
11588  o = that.options,
11589  el = that.element,
11590  oc = o.containment,
11591  ce = ( oc instanceof $ ) ?
11592  oc.get( 0 ) :
11593  ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11594 
11595  if ( !ce ) {
11596  return;
11597  }
11598 
11599  that.containerElement = $( ce );
11600 
11601  if ( /document/.test( oc ) || oc === document ) {
11602  that.containerOffset = {
11603  left: 0,
11604  top: 0
11605  };
11606  that.containerPosition = {
11607  left: 0,
11608  top: 0
11609  };
11610 
11611  that.parentData = {
11612  element: $( document ),
11613  left: 0,
11614  top: 0,
11615  width: $( document ).width(),
11616  height: $( document ).height() || document.body.parentNode.scrollHeight
11617  };
11618  } else {
11619  element = $( ce );
11620  p = [];
11621  $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11622  p[ i ] = that._num( element.css( "padding" + name ) );
11623  } );
11624 
11625  that.containerOffset = element.offset();
11626  that.containerPosition = element.position();
11627  that.containerSize = {
11628  height: ( element.innerHeight() - p[ 3 ] ),
11629  width: ( element.innerWidth() - p[ 1 ] )
11630  };
11631 
11632  co = that.containerOffset;
11633  ch = that.containerSize.height;
11634  cw = that.containerSize.width;
11635  width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
11636  height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
11637 
11638  that.parentData = {
11639  element: ce,
11640  left: co.left,
11641  top: co.top,
11642  width: width,
11643  height: height
11644  };
11645  }
11646  },
11647 
11648  resize: function( event ) {
11649  var woset, hoset, isParent, isOffsetRelative,
11650  that = $( this ).resizable( "instance" ),
11651  o = that.options,
11652  co = that.containerOffset,
11653  cp = that.position,
11654  pRatio = that._aspectRatio || event.shiftKey,
11655  cop = {
11656  top: 0,
11657  left: 0
11658  },
11659  ce = that.containerElement,
11660  continueResize = true;
11661 
11662  if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11663  cop = co;
11664  }
11665 
11666  if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11667  that.size.width = that.size.width +
11668  ( that._helper ?
11669  ( that.position.left - co.left ) :
11670  ( that.position.left - cop.left ) );
11671 
11672  if ( pRatio ) {
11673  that.size.height = that.size.width / that.aspectRatio;
11674  continueResize = false;
11675  }
11676  that.position.left = o.helper ? co.left : 0;
11677  }
11678 
11679  if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11680  that.size.height = that.size.height +
11681  ( that._helper ?
11682  ( that.position.top - co.top ) :
11683  that.position.top );
11684 
11685  if ( pRatio ) {
11686  that.size.width = that.size.height * that.aspectRatio;
11687  continueResize = false;
11688  }
11689  that.position.top = that._helper ? co.top : 0;
11690  }
11691 
11692  isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11693  isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11694 
11695  if ( isParent && isOffsetRelative ) {
11696  that.offset.left = that.parentData.left + that.position.left;
11697  that.offset.top = that.parentData.top + that.position.top;
11698  } else {
11699  that.offset.left = that.element.offset().left;
11700  that.offset.top = that.element.offset().top;
11701  }
11702 
11703  woset = Math.abs( that.sizeDiff.width +
11704  ( that._helper ?
11705  that.offset.left - cop.left :
11706  ( that.offset.left - co.left ) ) );
11707 
11708  hoset = Math.abs( that.sizeDiff.height +
11709  ( that._helper ?
11710  that.offset.top - cop.top :
11711  ( that.offset.top - co.top ) ) );
11712 
11713  if ( woset + that.size.width >= that.parentData.width ) {
11714  that.size.width = that.parentData.width - woset;
11715  if ( pRatio ) {
11716  that.size.height = that.size.width / that.aspectRatio;
11717  continueResize = false;
11718  }
11719  }
11720 
11721  if ( hoset + that.size.height >= that.parentData.height ) {
11722  that.size.height = that.parentData.height - hoset;
11723  if ( pRatio ) {
11724  that.size.width = that.size.height * that.aspectRatio;
11725  continueResize = false;
11726  }
11727  }
11728 
11729  if ( !continueResize ) {
11730  that.position.left = that.prevPosition.left;
11731  that.position.top = that.prevPosition.top;
11732  that.size.width = that.prevSize.width;
11733  that.size.height = that.prevSize.height;
11734  }
11735  },
11736 
11737  stop: function() {
11738  var that = $( this ).resizable( "instance" ),
11739  o = that.options,
11740  co = that.containerOffset,
11741  cop = that.containerPosition,
11742  ce = that.containerElement,
11743  helper = $( that.helper ),
11744  ho = helper.offset(),
11745  w = helper.outerWidth() - that.sizeDiff.width,
11746  h = helper.outerHeight() - that.sizeDiff.height;
11747 
11748  if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
11749  $( this ).css( {
11750  left: ho.left - cop.left - co.left,
11751  width: w,
11752  height: h
11753  } );
11754  }
11755 
11756  if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
11757  $( this ).css( {
11758  left: ho.left - cop.left - co.left,
11759  width: w,
11760  height: h
11761  } );
11762  }
11763  }
11764 } );
11765 
11766 $.ui.plugin.add( "resizable", "alsoResize", {
11767 
11768  start: function() {
11769  var that = $( this ).resizable( "instance" ),
11770  o = that.options;
11771 
11772  $( o.alsoResize ).each( function() {
11773  var el = $( this );
11774  el.data( "ui-resizable-alsoresize", {
11775  width: parseFloat( el.width() ), height: parseFloat( el.height() ),
11776  left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
11777  } );
11778  } );
11779  },
11780 
11781  resize: function( event, ui ) {
11782  var that = $( this ).resizable( "instance" ),
11783  o = that.options,
11784  os = that.originalSize,
11785  op = that.originalPosition,
11786  delta = {
11787  height: ( that.size.height - os.height ) || 0,
11788  width: ( that.size.width - os.width ) || 0,
11789  top: ( that.position.top - op.top ) || 0,
11790  left: ( that.position.left - op.left ) || 0
11791  };
11792 
11793  $( o.alsoResize ).each( function() {
11794  var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
11795  css = el.parents( ui.originalElement[ 0 ] ).length ?
11796  [ "width", "height" ] :
11797  [ "width", "height", "top", "left" ];
11798 
11799  $.each( css, function( i, prop ) {
11800  var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
11801  if ( sum && sum >= 0 ) {
11802  style[ prop ] = sum || null;
11803  }
11804  } );
11805 
11806  el.css( style );
11807  } );
11808  },
11809 
11810  stop: function() {
11811  $( this ).removeData( "ui-resizable-alsoresize" );
11812  }
11813 } );
11814 
11815 $.ui.plugin.add( "resizable", "ghost", {
11816 
11817  start: function() {
11818 
11819  var that = $( this ).resizable( "instance" ), cs = that.size;
11820 
11821  that.ghost = that.originalElement.clone();
11822  that.ghost.css( {
11823  opacity: 0.25,
11824  display: "block",
11825  position: "relative",
11826  height: cs.height,
11827  width: cs.width,
11828  margin: 0,
11829  left: 0,
11830  top: 0
11831  } );
11832 
11833  that._addClass( that.ghost, "ui-resizable-ghost" );
11834 
11835  // DEPRECATED
11836  // TODO: remove after 1.12
11837  if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
11838 
11839  // Ghost option
11840  that.ghost.addClass( this.options.ghost );
11841  }
11842 
11843  that.ghost.appendTo( that.helper );
11844 
11845  },
11846 
11847  resize: function() {
11848  var that = $( this ).resizable( "instance" );
11849  if ( that.ghost ) {
11850  that.ghost.css( {
11851  position: "relative",
11852  height: that.size.height,
11853  width: that.size.width
11854  } );
11855  }
11856  },
11857 
11858  stop: function() {
11859  var that = $( this ).resizable( "instance" );
11860  if ( that.ghost && that.helper ) {
11861  that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
11862  }
11863  }
11864 
11865 } );
11866 
11867 $.ui.plugin.add( "resizable", "grid", {
11868 
11869  resize: function() {
11870  var outerDimensions,
11871  that = $( this ).resizable( "instance" ),
11872  o = that.options,
11873  cs = that.size,
11874  os = that.originalSize,
11875  op = that.originalPosition,
11876  a = that.axis,
11877  grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
11878  gridX = ( grid[ 0 ] || 1 ),
11879  gridY = ( grid[ 1 ] || 1 ),
11880  ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
11881  oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
11882  newWidth = os.width + ox,
11883  newHeight = os.height + oy,
11884  isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
11885  isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
11886  isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
11887  isMinHeight = o.minHeight && ( o.minHeight > newHeight );
11888 
11889  o.grid = grid;
11890 
11891  if ( isMinWidth ) {
11892  newWidth += gridX;
11893  }
11894  if ( isMinHeight ) {
11895  newHeight += gridY;
11896  }
11897  if ( isMaxWidth ) {
11898  newWidth -= gridX;
11899  }
11900  if ( isMaxHeight ) {
11901  newHeight -= gridY;
11902  }
11903 
11904  if ( /^(se|s|e)$/.test( a ) ) {
11905  that.size.width = newWidth;
11906  that.size.height = newHeight;
11907  } else if ( /^(ne)$/.test( a ) ) {
11908  that.size.width = newWidth;
11909  that.size.height = newHeight;
11910  that.position.top = op.top - oy;
11911  } else if ( /^(sw)$/.test( a ) ) {
11912  that.size.width = newWidth;
11913  that.size.height = newHeight;
11914  that.position.left = op.left - ox;
11915  } else {
11916  if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
11917  outerDimensions = that._getPaddingPlusBorderDimensions( this );
11918  }
11919 
11920  if ( newHeight - gridY > 0 ) {
11921  that.size.height = newHeight;
11922  that.position.top = op.top - oy;
11923  } else {
11924  newHeight = gridY - outerDimensions.height;
11925  that.size.height = newHeight;
11926  that.position.top = op.top + os.height - newHeight;
11927  }
11928  if ( newWidth - gridX > 0 ) {
11929  that.size.width = newWidth;
11930  that.position.left = op.left - ox;
11931  } else {
11932  newWidth = gridX - outerDimensions.width;
11933  that.size.width = newWidth;
11934  that.position.left = op.left + os.width - newWidth;
11935  }
11936  }
11937  }
11938 
11939 } );
11940 
11941 var widgetsResizable = $.ui.resizable;
11942 
11943 
11953 //>>label: Dialog
11954 //>>group: Widgets
11955 //>>description: Displays customizable dialog windows.
11956 //>>docs: http://api.jqueryui.com/dialog/
11957 //>>demos: http://jqueryui.com/dialog/
11958 //>>css.structure: ../../themes/base/core.css
11959 //>>css.structure: ../../themes/base/dialog.css
11960 //>>css.theme: ../../themes/base/theme.css
11961 
11962 
11963 
11964 $.widget( "ui.dialog", {
11965  version: "1.12.1",
11966  options: {
11967  appendTo: "body",
11968  autoOpen: true,
11969  buttons: [],
11970  classes: {
11971  "ui-dialog": "ui-corner-all",
11972  "ui-dialog-titlebar": "ui-corner-all"
11973  },
11974  closeOnEscape: true,
11975  closeText: "Close",
11976  draggable: true,
11977  hide: null,
11978  height: "auto",
11979  maxHeight: null,
11980  maxWidth: null,
11981  minHeight: 150,
11982  minWidth: 150,
11983  modal: false,
11984  position: {
11985  my: "center",
11986  at: "center",
11987  of: window,
11988  collision: "fit",
11989 
11990  // Ensure the titlebar is always visible
11991  using: function( pos ) {
11992  var topOffset = $( this ).css( pos ).offset().top;
11993  if ( topOffset < 0 ) {
11994  $( this ).css( "top", pos.top - topOffset );
11995  }
11996  }
11997  },
11998  resizable: true,
11999  show: null,
12000  title: null,
12001  width: 300,
12002 
12003  // Callbacks
12004  beforeClose: null,
12005  close: null,
12006  drag: null,
12007  dragStart: null,
12008  dragStop: null,
12009  focus: null,
12010  open: null,
12011  resize: null,
12012  resizeStart: null,
12013  resizeStop: null
12014  },
12015 
12016  sizeRelatedOptions: {
12017  buttons: true,
12018  height: true,
12019  maxHeight: true,
12020  maxWidth: true,
12021  minHeight: true,
12022  minWidth: true,
12023  width: true
12024  },
12025 
12026  resizableRelatedOptions: {
12027  maxHeight: true,
12028  maxWidth: true,
12029  minHeight: true,
12030  minWidth: true
12031  },
12032 
12033  _create: function() {
12034  this.originalCss = {
12035  display: this.element[ 0 ].style.display,
12036  width: this.element[ 0 ].style.width,
12037  minHeight: this.element[ 0 ].style.minHeight,
12038  maxHeight: this.element[ 0 ].style.maxHeight,
12039  height: this.element[ 0 ].style.height
12040  };
12041  this.originalPosition = {
12042  parent: this.element.parent(),
12043  index: this.element.parent().children().index( this.element )
12044  };
12045  this.originalTitle = this.element.attr( "title" );
12046  if ( this.options.title == null && this.originalTitle != null ) {
12047  this.options.title = this.originalTitle;
12048  }
12049 
12050  // Dialogs can't be disabled
12051  if ( this.options.disabled ) {
12052  this.options.disabled = false;
12053  }
12054 
12055  this._createWrapper();
12056 
12057  this.element
12058  .show()
12059  .removeAttr( "title" )
12060  .appendTo( this.uiDialog );
12061 
12062  this._addClass( "ui-dialog-content", "ui-widget-content" );
12063 
12064  this._createTitlebar();
12065  this._createButtonPane();
12066 
12067  if ( this.options.draggable && $.fn.draggable ) {
12068  this._makeDraggable();
12069  }
12070  if ( this.options.resizable && $.fn.resizable ) {
12071  this._makeResizable();
12072  }
12073 
12074  this._isOpen = false;
12075 
12076  this._trackFocus();
12077  },
12078 
12079  _init: function() {
12080  if ( this.options.autoOpen ) {
12081  this.open();
12082  }
12083  },
12084 
12085  _appendTo: function() {
12086  var element = this.options.appendTo;
12087  if ( element && ( element.jquery || element.nodeType ) ) {
12088  return $( element );
12089  }
12090  return this.document.find( element || "body" ).eq( 0 );
12091  },
12092 
12093  _destroy: function() {
12094  var next,
12095  originalPosition = this.originalPosition;
12096 
12097  this._untrackInstance();
12098  this._destroyOverlay();
12099 
12100  this.element
12101  .removeUniqueId()
12102  .css( this.originalCss )
12103 
12104  // Without detaching first, the following becomes really slow
12105  .detach();
12106 
12107  this.uiDialog.remove();
12108 
12109  if ( this.originalTitle ) {
12110  this.element.attr( "title", this.originalTitle );
12111  }
12112 
12113  next = originalPosition.parent.children().eq( originalPosition.index );
12114 
12115  // Don't try to place the dialog next to itself (#8613)
12116  if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12117  next.before( this.element );
12118  } else {
12119  originalPosition.parent.append( this.element );
12120  }
12121  },
12122 
12123  widget: function() {
12124  return this.uiDialog;
12125  },
12126 
12127  disable: $.noop,
12128  enable: $.noop,
12129 
12130  close: function( event ) {
12131  var that = this;
12132 
12133  if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12134  return;
12135  }
12136 
12137  this._isOpen = false;
12138  this._focusedElement = null;
12139  this._destroyOverlay();
12140  this._untrackInstance();
12141 
12142  if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12143 
12144  // Hiding a focused element doesn't trigger blur in WebKit
12145  // so in case we have nothing to focus on, explicitly blur the active element
12146  // https://bugs.webkit.org/show_bug.cgi?id=47182
12147  $.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
12148  }
12149 
12150  this._hide( this.uiDialog, this.options.hide, function() {
12151  that._trigger( "close", event );
12152  } );
12153  },
12154 
12155  isOpen: function() {
12156  return this._isOpen;
12157  },
12158 
12159  moveToTop: function() {
12160  this._moveToTop();
12161  },
12162 
12163  _moveToTop: function( event, silent ) {
12164  var moved = false,
12165  zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12166  return +$( this ).css( "z-index" );
12167  } ).get(),
12168  zIndexMax = Math.max.apply( null, zIndices );
12169 
12170  if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12171  this.uiDialog.css( "z-index", zIndexMax + 1 );
12172  moved = true;
12173  }
12174 
12175  if ( moved && !silent ) {
12176  this._trigger( "focus", event );
12177  }
12178  return moved;
12179  },
12180 
12181  open: function() {
12182  var that = this;
12183  if ( this._isOpen ) {
12184  if ( this._moveToTop() ) {
12185  this._focusTabbable();
12186  }
12187  return;
12188  }
12189 
12190  this._isOpen = true;
12191  this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
12192 
12193  this._size();
12194  this._position();
12195  this._createOverlay();
12196  this._moveToTop( null, true );
12197 
12198  // Ensure the overlay is moved to the top with the dialog, but only when
12199  // opening. The overlay shouldn't move after the dialog is open so that
12200  // modeless dialogs opened after the modal dialog stack properly.
12201  if ( this.overlay ) {
12202  this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12203  }
12204 
12205  this._show( this.uiDialog, this.options.show, function() {
12206  that._focusTabbable();
12207  that._trigger( "focus" );
12208  } );
12209 
12210  // Track the dialog immediately upon openening in case a focus event
12211  // somehow occurs outside of the dialog before an element inside the
12212  // dialog is focused (#10152)
12213  this._makeFocusTarget();
12214 
12215  this._trigger( "open" );
12216  },
12217 
12218  _focusTabbable: function() {
12219 
12220  // Set focus to the first match:
12221  // 1. An element that was focused previously
12222  // 2. First element inside the dialog matching [autofocus]
12223  // 3. Tabbable element inside the content element
12224  // 4. Tabbable element inside the buttonpane
12225  // 5. The close button
12226  // 6. The dialog itself
12227  var hasFocus = this._focusedElement;
12228  if ( !hasFocus ) {
12229  hasFocus = this.element.find( "[autofocus]" );
12230  }
12231  if ( !hasFocus.length ) {
12232  hasFocus = this.element.find( ":tabbable" );
12233  }
12234  if ( !hasFocus.length ) {
12235  hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12236  }
12237  if ( !hasFocus.length ) {
12238  hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12239  }
12240  if ( !hasFocus.length ) {
12241  hasFocus = this.uiDialog;
12242  }
12243  hasFocus.eq( 0 ).trigger( "focus" );
12244  },
12245 
12246  _keepFocus: function( event ) {
12247  function checkFocus() {
12248  var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
12249  isActive = this.uiDialog[ 0 ] === activeElement ||
12250  $.contains( this.uiDialog[ 0 ], activeElement );
12251  if ( !isActive ) {
12252  this._focusTabbable();
12253  }
12254  }
12255  event.preventDefault();
12256  checkFocus.call( this );
12257 
12258  // support: IE
12259  // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
12260  // so we check again later
12261  this._delay( checkFocus );
12262  },
12263 
12264  _createWrapper: function() {
12265  this.uiDialog = $( "<div>" )
12266  .hide()
12267  .attr( {
12268 
12269  // Setting tabIndex makes the div focusable
12270  tabIndex: -1,
12271  role: "dialog"
12272  } )
12273  .appendTo( this._appendTo() );
12274 
12275  this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12276  this._on( this.uiDialog, {
12277  keydown: function( event ) {
12278  if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12279  event.keyCode === $.ui.keyCode.ESCAPE ) {
12280  event.preventDefault();
12281  this.close( event );
12282  return;
12283  }
12284 
12285  // Prevent tabbing out of dialogs
12286  if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12287  return;
12288  }
12289  var tabbables = this.uiDialog.find( ":tabbable" ),
12290  first = tabbables.filter( ":first" ),
12291  last = tabbables.filter( ":last" );
12292 
12293  if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12294  !event.shiftKey ) {
12295  this._delay( function() {
12296  first.trigger( "focus" );
12297  } );
12298  event.preventDefault();
12299  } else if ( ( event.target === first[ 0 ] ||
12300  event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12301  this._delay( function() {
12302  last.trigger( "focus" );
12303  } );
12304  event.preventDefault();
12305  }
12306  },
12307  mousedown: function( event ) {
12308  if ( this._moveToTop( event ) ) {
12309  this._focusTabbable();
12310  }
12311  }
12312  } );
12313 
12314  // We assume that any existing aria-describedby attribute means
12315  // that the dialog content is marked up properly
12316  // otherwise we brute force the content as the description
12317  if ( !this.element.find( "[aria-describedby]" ).length ) {
12318  this.uiDialog.attr( {
12319  "aria-describedby": this.element.uniqueId().attr( "id" )
12320  } );
12321  }
12322  },
12323 
12324  _createTitlebar: function() {
12325  var uiDialogTitle;
12326 
12327  this.uiDialogTitlebar = $( "<div>" );
12328  this._addClass( this.uiDialogTitlebar,
12329  "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12330  this._on( this.uiDialogTitlebar, {
12331  mousedown: function( event ) {
12332 
12333  // Don't prevent click on close button (#8838)
12334  // Focusing a dialog that is partially scrolled out of view
12335  // causes the browser to scroll it into view, preventing the click event
12336  if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12337 
12338  // Dialog isn't getting focus when dragging (#8063)
12339  this.uiDialog.trigger( "focus" );
12340  }
12341  }
12342  } );
12343 
12344  // Support: IE
12345  // Use type="button" to prevent enter keypresses in textboxes from closing the
12346  // dialog in IE (#9312)
12347  this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12348  .button( {
12349  label: $( "<a>" ).text( this.options.closeText ).html(),
12350  icon: "ui-icon-closethick",
12351  showLabel: false
12352  } )
12353  .appendTo( this.uiDialogTitlebar );
12354 
12355  this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12356  this._on( this.uiDialogTitlebarClose, {
12357  click: function( event ) {
12358  event.preventDefault();
12359  this.close( event );
12360  }
12361  } );
12362 
12363  uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
12364  this._addClass( uiDialogTitle, "ui-dialog-title" );
12365  this._title( uiDialogTitle );
12366 
12367  this.uiDialogTitlebar.prependTo( this.uiDialog );
12368 
12369  this.uiDialog.attr( {
12370  "aria-labelledby": uiDialogTitle.attr( "id" )
12371  } );
12372  },
12373 
12374  _title: function( title ) {
12375  if ( this.options.title ) {
12376  title.text( this.options.title );
12377  } else {
12378  title.html( "&#160;" );
12379  }
12380  },
12381 
12382  _createButtonPane: function() {
12383  this.uiDialogButtonPane = $( "<div>" );
12384  this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12385  "ui-widget-content ui-helper-clearfix" );
12386 
12387  this.uiButtonSet = $( "<div>" )
12388  .appendTo( this.uiDialogButtonPane );
12389  this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12390 
12391  this._createButtons();
12392  },
12393 
12394  _createButtons: function() {
12395  var that = this,
12396  buttons = this.options.buttons;
12397 
12398  // If we already have a button pane, remove it
12399  this.uiDialogButtonPane.remove();
12400  this.uiButtonSet.empty();
12401 
12402  if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
12403  this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12404  return;
12405  }
12406 
12407  $.each( buttons, function( name, props ) {
12408  var click, buttonOptions;
12409  props = $.isFunction( props ) ?
12410  { click: props, text: name } :
12411  props;
12412 
12413  // Default to a non-submitting button
12414  props = $.extend( { type: "button" }, props );
12415 
12416  // Change the context for the click callback to be the main element
12417  click = props.click;
12418  buttonOptions = {
12419  icon: props.icon,
12420  iconPosition: props.iconPosition,
12421  showLabel: props.showLabel,
12422 
12423  // Deprecated options
12424  icons: props.icons,
12425  text: props.text
12426  };
12427 
12428  delete props.click;
12429  delete props.icon;
12430  delete props.iconPosition;
12431  delete props.showLabel;
12432 
12433  // Deprecated options
12434  delete props.icons;
12435  if ( typeof props.text === "boolean" ) {
12436  delete props.text;
12437  }
12438 
12439  $( "<button></button>", props )
12440  .button( buttonOptions )
12441  .appendTo( that.uiButtonSet )
12442  .on( "click", function() {
12443  click.apply( that.element[ 0 ], arguments );
12444  } );
12445  } );
12446  this._addClass( this.uiDialog, "ui-dialog-buttons" );
12447  this.uiDialogButtonPane.appendTo( this.uiDialog );
12448  },
12449 
12450  _makeDraggable: function() {
12451  var that = this,
12452  options = this.options;
12453 
12454  function filteredUi( ui ) {
12455  return {
12456  position: ui.position,
12457  offset: ui.offset
12458  };
12459  }
12460 
12461  this.uiDialog.draggable( {
12462  cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12463  handle: ".ui-dialog-titlebar",
12464  containment: "document",
12465  start: function( event, ui ) {
12466  that._addClass( $( this ), "ui-dialog-dragging" );
12467  that._blockFrames();
12468  that._trigger( "dragStart", event, filteredUi( ui ) );
12469  },
12470  drag: function( event, ui ) {
12471  that._trigger( "drag", event, filteredUi( ui ) );
12472  },
12473  stop: function( event, ui ) {
12474  var left = ui.offset.left - that.document.scrollLeft(),
12475  top = ui.offset.top - that.document.scrollTop();
12476 
12477  options.position = {
12478  my: "left top",
12479  at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12480  "top" + ( top >= 0 ? "+" : "" ) + top,
12481  of: that.window
12482  };
12483  that._removeClass( $( this ), "ui-dialog-dragging" );
12484  that._unblockFrames();
12485  that._trigger( "dragStop", event, filteredUi( ui ) );
12486  }
12487  } );
12488  },
12489 
12490  _makeResizable: function() {
12491  var that = this,
12492  options = this.options,
12493  handles = options.resizable,
12494 
12495  // .ui-resizable has position: relative defined in the stylesheet
12496  // but dialogs have to use absolute or fixed positioning
12497  position = this.uiDialog.css( "position" ),
12498  resizeHandles = typeof handles === "string" ?
12499  handles :
12500  "n,e,s,w,se,sw,ne,nw";
12501 
12502  function filteredUi( ui ) {
12503  return {
12504  originalPosition: ui.originalPosition,
12505  originalSize: ui.originalSize,
12506  position: ui.position,
12507  size: ui.size
12508  };
12509  }
12510 
12511  this.uiDialog.resizable( {
12512  cancel: ".ui-dialog-content",
12513  containment: "document",
12514  alsoResize: this.element,
12515  maxWidth: options.maxWidth,
12516  maxHeight: options.maxHeight,
12517  minWidth: options.minWidth,
12518  minHeight: this._minHeight(),
12519  handles: resizeHandles,
12520  start: function( event, ui ) {
12521  that._addClass( $( this ), "ui-dialog-resizing" );
12522  that._blockFrames();
12523  that._trigger( "resizeStart", event, filteredUi( ui ) );
12524  },
12525  resize: function( event, ui ) {
12526  that._trigger( "resize", event, filteredUi( ui ) );
12527  },
12528  stop: function( event, ui ) {
12529  var offset = that.uiDialog.offset(),
12530  left = offset.left - that.document.scrollLeft(),
12531  top = offset.top - that.document.scrollTop();
12532 
12533  options.height = that.uiDialog.height();
12534  options.width = that.uiDialog.width();
12535  options.position = {
12536  my: "left top",
12537  at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12538  "top" + ( top >= 0 ? "+" : "" ) + top,
12539  of: that.window
12540  };
12541  that._removeClass( $( this ), "ui-dialog-resizing" );
12542  that._unblockFrames();
12543  that._trigger( "resizeStop", event, filteredUi( ui ) );
12544  }
12545  } )
12546  .css( "position", position );
12547  },
12548 
12549  _trackFocus: function() {
12550  this._on( this.widget(), {
12551  focusin: function( event ) {
12552  this._makeFocusTarget();
12553  this._focusedElement = $( event.target );
12554  }
12555  } );
12556  },
12557 
12558  _makeFocusTarget: function() {
12559  this._untrackInstance();
12560  this._trackingInstances().unshift( this );
12561  },
12562 
12563  _untrackInstance: function() {
12564  var instances = this._trackingInstances(),
12565  exists = $.inArray( this, instances );
12566  if ( exists !== -1 ) {
12567  instances.splice( exists, 1 );
12568  }
12569  },
12570 
12571  _trackingInstances: function() {
12572  var instances = this.document.data( "ui-dialog-instances" );
12573  if ( !instances ) {
12574  instances = [];
12575  this.document.data( "ui-dialog-instances", instances );
12576  }
12577  return instances;
12578  },
12579 
12580  _minHeight: function() {
12581  var options = this.options;
12582 
12583  return options.height === "auto" ?
12584  options.minHeight :
12585  Math.min( options.minHeight, options.height );
12586  },
12587 
12588  _position: function() {
12589 
12590  // Need to show the dialog to get the actual offset in the position plugin
12591  var isVisible = this.uiDialog.is( ":visible" );
12592  if ( !isVisible ) {
12593  this.uiDialog.show();
12594  }
12595  this.uiDialog.position( this.options.position );
12596  if ( !isVisible ) {
12597  this.uiDialog.hide();
12598  }
12599  },
12600 
12601  _setOptions: function( options ) {
12602  var that = this,
12603  resize = false,
12604  resizableOptions = {};
12605 
12606  $.each( options, function( key, value ) {
12607  that._setOption( key, value );
12608 
12609  if ( key in that.sizeRelatedOptions ) {
12610  resize = true;
12611  }
12612  if ( key in that.resizableRelatedOptions ) {
12613  resizableOptions[ key ] = value;
12614  }
12615  } );
12616 
12617  if ( resize ) {
12618  this._size();
12619  this._position();
12620  }
12621  if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12622  this.uiDialog.resizable( "option", resizableOptions );
12623  }
12624  },
12625 
12626  _setOption: function( key, value ) {
12627  var isDraggable, isResizable,
12628  uiDialog = this.uiDialog;
12629 
12630  if ( key === "disabled" ) {
12631  return;
12632  }
12633 
12634  this._super( key, value );
12635 
12636  if ( key === "appendTo" ) {
12637  this.uiDialog.appendTo( this._appendTo() );
12638  }
12639 
12640  if ( key === "buttons" ) {
12641  this._createButtons();
12642  }
12643 
12644  if ( key === "closeText" ) {
12645  this.uiDialogTitlebarClose.button( {
12646 
12647  // Ensure that we always pass a string
12648  label: $( "<a>" ).text( "" + this.options.closeText ).html()
12649  } );
12650  }
12651 
12652  if ( key === "draggable" ) {
12653  isDraggable = uiDialog.is( ":data(ui-draggable)" );
12654  if ( isDraggable && !value ) {
12655  uiDialog.draggable( "destroy" );
12656  }
12657 
12658  if ( !isDraggable && value ) {
12659  this._makeDraggable();
12660  }
12661  }
12662 
12663  if ( key === "position" ) {
12664  this._position();
12665  }
12666 
12667  if ( key === "resizable" ) {
12668 
12669  // currently resizable, becoming non-resizable
12670  isResizable = uiDialog.is( ":data(ui-resizable)" );
12671  if ( isResizable && !value ) {
12672  uiDialog.resizable( "destroy" );
12673  }
12674 
12675  // Currently resizable, changing handles
12676  if ( isResizable && typeof value === "string" ) {
12677  uiDialog.resizable( "option", "handles", value );
12678  }
12679 
12680  // Currently non-resizable, becoming resizable
12681  if ( !isResizable && value !== false ) {
12682  this._makeResizable();
12683  }
12684  }
12685 
12686  if ( key === "title" ) {
12687  this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12688  }
12689  },
12690 
12691  _size: function() {
12692 
12693  // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12694  // divs will both have width and height set, so we need to reset them
12695  var nonContentHeight, minContentHeight, maxContentHeight,
12696  options = this.options;
12697 
12698  // Reset content sizing
12699  this.element.show().css( {
12700  width: "auto",
12701  minHeight: 0,
12702  maxHeight: "none",
12703  height: 0
12704  } );
12705 
12706  if ( options.minWidth > options.width ) {
12707  options.width = options.minWidth;
12708  }
12709 
12710  // Reset wrapper sizing
12711  // determine the height of all the non-content elements
12712  nonContentHeight = this.uiDialog.css( {
12713  height: "auto",
12714  width: options.width
12715  } )
12716  .outerHeight();
12717  minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12718  maxContentHeight = typeof options.maxHeight === "number" ?
12719  Math.max( 0, options.maxHeight - nonContentHeight ) :
12720  "none";
12721 
12722  if ( options.height === "auto" ) {
12723  this.element.css( {
12724  minHeight: minContentHeight,
12725  maxHeight: maxContentHeight,
12726  height: "auto"
12727  } );
12728  } else {
12729  this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12730  }
12731 
12732  if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12733  this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12734  }
12735  },
12736 
12737  _blockFrames: function() {
12738  this.iframeBlocks = this.document.find( "iframe" ).map( function() {
12739  var iframe = $( this );
12740 
12741  return $( "<div>" )
12742  .css( {
12743  position: "absolute",
12744  width: iframe.outerWidth(),
12745  height: iframe.outerHeight()
12746  } )
12747  .appendTo( iframe.parent() )
12748  .offset( iframe.offset() )[ 0 ];
12749  } );
12750  },
12751 
12752  _unblockFrames: function() {
12753  if ( this.iframeBlocks ) {
12754  this.iframeBlocks.remove();
12755  delete this.iframeBlocks;
12756  }
12757  },
12758 
12759  _allowInteraction: function( event ) {
12760  if ( $( event.target ).closest( ".ui-dialog" ).length ) {
12761  return true;
12762  }
12763 
12764  // TODO: Remove hack when datepicker implements
12765  // the .ui-front logic (#8989)
12766  return !!$( event.target ).closest( ".ui-datepicker" ).length;
12767  },
12768 
12769  _createOverlay: function() {
12770  if ( !this.options.modal ) {
12771  return;
12772  }
12773 
12774  // We use a delay in case the overlay is created from an
12775  // event that we're going to be cancelling (#2804)
12776  var isOpening = true;
12777  this._delay( function() {
12778  isOpening = false;
12779  } );
12780 
12781  if ( !this.document.data( "ui-dialog-overlays" ) ) {
12782 
12783  // Prevent use of anchors and inputs
12784  // Using _on() for an event handler shared across many instances is
12785  // safe because the dialogs stack and must be closed in reverse order
12786  this._on( this.document, {
12787  focusin: function( event ) {
12788  if ( isOpening ) {
12789  return;
12790  }
12791 
12792  if ( !this._allowInteraction( event ) ) {
12793  event.preventDefault();
12794  this._trackingInstances()[ 0 ]._focusTabbable();
12795  }
12796  }
12797  } );
12798  }
12799 
12800  this.overlay = $( "<div>" )
12801  .appendTo( this._appendTo() );
12802 
12803  this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
12804  this._on( this.overlay, {
12805  mousedown: "_keepFocus"
12806  } );
12807  this.document.data( "ui-dialog-overlays",
12808  ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
12809  },
12810 
12811  _destroyOverlay: function() {
12812  if ( !this.options.modal ) {
12813  return;
12814  }
12815 
12816  if ( this.overlay ) {
12817  var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
12818 
12819  if ( !overlays ) {
12820  this._off( this.document, "focusin" );
12821  this.document.removeData( "ui-dialog-overlays" );
12822  } else {
12823  this.document.data( "ui-dialog-overlays", overlays );
12824  }
12825 
12826  this.overlay.remove();
12827  this.overlay = null;
12828  }
12829  }
12830 } );
12831 
12832 // DEPRECATED
12833 // TODO: switch return back to widget declaration at top of file when this is removed
12834 if ( $.uiBackCompat !== false ) {
12835 
12836  // Backcompat for dialogClass option
12837  $.widget( "ui.dialog", $.ui.dialog, {
12838  options: {
12839  dialogClass: ""
12840  },
12841  _createWrapper: function() {
12842  this._super();
12843  this.uiDialog.addClass( this.options.dialogClass );
12844  },
12845  _setOption: function( key, value ) {
12846  if ( key === "dialogClass" ) {
12847  this.uiDialog
12848  .removeClass( this.options.dialogClass )
12849  .addClass( value );
12850  }
12851  this._superApply( arguments );
12852  }
12853  } );
12854 }
12855 
12856 var widgetsDialog = $.ui.dialog;
12857 
12858 
12868 //>>label: Droppable
12869 //>>group: Interactions
12870 //>>description: Enables drop targets for draggable elements.
12871 //>>docs: http://api.jqueryui.com/droppable/
12872 //>>demos: http://jqueryui.com/droppable/
12873 
12874 
12875 
12876 $.widget( "ui.droppable", {
12877  version: "1.12.1",
12878  widgetEventPrefix: "drop",
12879  options: {
12880  accept: "*",
12881  addClasses: true,
12882  greedy: false,
12883  scope: "default",
12884  tolerance: "intersect",
12885 
12886  // Callbacks
12887  activate: null,
12888  deactivate: null,
12889  drop: null,
12890  out: null,
12891  over: null
12892  },
12893  _create: function() {
12894 
12895  var proportions,
12896  o = this.options,
12897  accept = o.accept;
12898 
12899  this.isover = false;
12900  this.isout = true;
12901 
12902  this.accept = $.isFunction( accept ) ? accept : function( d ) {
12903  return d.is( accept );
12904  };
12905 
12906  this.proportions = function( /* valueToWrite */ ) {
12907  if ( arguments.length ) {
12908 
12909  // Store the droppable's proportions
12910  proportions = arguments[ 0 ];
12911  } else {
12912 
12913  // Retrieve or derive the droppable's proportions
12914  return proportions ?
12915  proportions :
12916  proportions = {
12917  width: this.element[ 0 ].offsetWidth,
12918  height: this.element[ 0 ].offsetHeight
12919  };
12920  }
12921  };
12922 
12923  this._addToManager( o.scope );
12924 
12925  o.addClasses && this._addClass( "ui-droppable" );
12926 
12927  },
12928 
12929  _addToManager: function( scope ) {
12930 
12931  // Add the reference and positions to the manager
12932  $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
12933  $.ui.ddmanager.droppables[ scope ].push( this );
12934  },
12935 
12936  _splice: function( drop ) {
12937  var i = 0;
12938  for ( ; i < drop.length; i++ ) {
12939  if ( drop[ i ] === this ) {
12940  drop.splice( i, 1 );
12941  }
12942  }
12943  },
12944 
12945  _destroy: function() {
12946  var drop = $.ui.ddmanager.droppables[ this.options.scope ];
12947 
12948  this._splice( drop );
12949  },
12950 
12951  _setOption: function( key, value ) {
12952 
12953  if ( key === "accept" ) {
12954  this.accept = $.isFunction( value ) ? value : function( d ) {
12955  return d.is( value );
12956  };
12957  } else if ( key === "scope" ) {
12958  var drop = $.ui.ddmanager.droppables[ this.options.scope ];
12959 
12960  this._splice( drop );
12961  this._addToManager( value );
12962  }
12963 
12964  this._super( key, value );
12965  },
12966 
12967  _activate: function( event ) {
12968  var draggable = $.ui.ddmanager.current;
12969 
12970  this._addActiveClass();
12971  if ( draggable ) {
12972  this._trigger( "activate", event, this.ui( draggable ) );
12973  }
12974  },
12975 
12976  _deactivate: function( event ) {
12977  var draggable = $.ui.ddmanager.current;
12978 
12979  this._removeActiveClass();
12980  if ( draggable ) {
12981  this._trigger( "deactivate", event, this.ui( draggable ) );
12982  }
12983  },
12984 
12985  _over: function( event ) {
12986 
12987  var draggable = $.ui.ddmanager.current;
12988 
12989  // Bail if draggable and droppable are same element
12990  if ( !draggable || ( draggable.currentItem ||
12991  draggable.element )[ 0 ] === this.element[ 0 ] ) {
12992  return;
12993  }
12994 
12995  if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
12996  draggable.element ) ) ) {
12997  this._addHoverClass();
12998  this._trigger( "over", event, this.ui( draggable ) );
12999  }
13000 
13001  },
13002 
13003  _out: function( event ) {
13004 
13005  var draggable = $.ui.ddmanager.current;
13006 
13007  // Bail if draggable and droppable are same element
13008  if ( !draggable || ( draggable.currentItem ||
13009  draggable.element )[ 0 ] === this.element[ 0 ] ) {
13010  return;
13011  }
13012 
13013  if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13014  draggable.element ) ) ) {
13015  this._removeHoverClass();
13016  this._trigger( "out", event, this.ui( draggable ) );
13017  }
13018 
13019  },
13020 
13021  _drop: function( event, custom ) {
13022 
13023  var draggable = custom || $.ui.ddmanager.current,
13024  childrenIntersection = false;
13025 
13026  // Bail if draggable and droppable are same element
13027  if ( !draggable || ( draggable.currentItem ||
13028  draggable.element )[ 0 ] === this.element[ 0 ] ) {
13029  return false;
13030  }
13031 
13032  this.element
13033  .find( ":data(ui-droppable)" )
13034  .not( ".ui-draggable-dragging" )
13035  .each( function() {
13036  var inst = $( this ).droppable( "instance" );
13037  if (
13038  inst.options.greedy &&
13039  !inst.options.disabled &&
13040  inst.options.scope === draggable.options.scope &&
13041  inst.accept.call(
13042  inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13043  ) &&
13044  intersect(
13045  draggable,
13046  $.extend( inst, { offset: inst.element.offset() } ),
13047  inst.options.tolerance, event
13048  )
13049  ) {
13050  childrenIntersection = true;
13051  return false; }
13052  } );
13053  if ( childrenIntersection ) {
13054  return false;
13055  }
13056 
13057  if ( this.accept.call( this.element[ 0 ],
13058  ( draggable.currentItem || draggable.element ) ) ) {
13059  this._removeActiveClass();
13060  this._removeHoverClass();
13061 
13062  this._trigger( "drop", event, this.ui( draggable ) );
13063  return this.element;
13064  }
13065 
13066  return false;
13067 
13068  },
13069 
13070  ui: function( c ) {
13071  return {
13072  draggable: ( c.currentItem || c.element ),
13073  helper: c.helper,
13074  position: c.position,
13075  offset: c.positionAbs
13076  };
13077  },
13078 
13079  // Extension points just to make backcompat sane and avoid duplicating logic
13080  // TODO: Remove in 1.13 along with call to it below
13081  _addHoverClass: function() {
13082  this._addClass( "ui-droppable-hover" );
13083  },
13084 
13085  _removeHoverClass: function() {
13086  this._removeClass( "ui-droppable-hover" );
13087  },
13088 
13089  _addActiveClass: function() {
13090  this._addClass( "ui-droppable-active" );
13091  },
13092 
13093  _removeActiveClass: function() {
13094  this._removeClass( "ui-droppable-active" );
13095  }
13096 } );
13097 
13098 var intersect = $.ui.intersect = ( function() {
13099  function isOverAxis( x, reference, size ) {
13100  return ( x >= reference ) && ( x < ( reference + size ) );
13101  }
13102 
13103  return function( draggable, droppable, toleranceMode, event ) {
13104 
13105  if ( !droppable.offset ) {
13106  return false;
13107  }
13108 
13109  var x1 = ( draggable.positionAbs ||
13110  draggable.position.absolute ).left + draggable.margins.left,
13111  y1 = ( draggable.positionAbs ||
13112  draggable.position.absolute ).top + draggable.margins.top,
13113  x2 = x1 + draggable.helperProportions.width,
13114  y2 = y1 + draggable.helperProportions.height,
13115  l = droppable.offset.left,
13116  t = droppable.offset.top,
13117  r = l + droppable.proportions().width,
13118  b = t + droppable.proportions().height;
13119 
13120  switch ( toleranceMode ) {
13121  case "fit":
13122  return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13123  case "intersect":
13124  return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13125  x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13126  t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13127  y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13128  case "pointer":
13129  return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13130  isOverAxis( event.pageX, l, droppable.proportions().width );
13131  case "touch":
13132  return (
13133  ( y1 >= t && y1 <= b ) || // Top edge touching
13134  ( y2 >= t && y2 <= b ) || // Bottom edge touching
13135  ( y1 < t && y2 > b ) // Surrounded vertically
13136  ) && (
13137  ( x1 >= l && x1 <= r ) || // Left edge touching
13138  ( x2 >= l && x2 <= r ) || // Right edge touching
13139  ( x1 < l && x2 > r ) // Surrounded horizontally
13140  );
13141  default:
13142  return false;
13143  }
13144  };
13145 } )();
13146 
13147 /*
13148  This manager tracks offsets of draggables and droppables
13149 */
13150 $.ui.ddmanager = {
13151  current: null,
13152  droppables: { "default": [] },
13153  prepareOffsets: function( t, event ) {
13154 
13155  var i, j,
13156  m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13157  type = event ? event.type : null, // workaround for #2317
13158  list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13159 
13160  droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13161 
13162  // No disabled and non-accepted
13163  if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13164  ( t.currentItem || t.element ) ) ) ) {
13165  continue;
13166  }
13167 
13168  // Filter out elements in the current dragged item
13169  for ( j = 0; j < list.length; j++ ) {
13170  if ( list[ j ] === m[ i ].element[ 0 ] ) {
13171  m[ i ].proportions().height = 0;
13172  continue droppablesLoop;
13173  }
13174  }
13175 
13176  m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13177  if ( !m[ i ].visible ) {
13178  continue;
13179  }
13180 
13181  // Activate the droppable if used directly from draggables
13182  if ( type === "mousedown" ) {
13183  m[ i ]._activate.call( m[ i ], event );
13184  }
13185 
13186  m[ i ].offset = m[ i ].element.offset();
13187  m[ i ].proportions( {
13188  width: m[ i ].element[ 0 ].offsetWidth,
13189  height: m[ i ].element[ 0 ].offsetHeight
13190  } );
13191 
13192  }
13193 
13194  },
13195  drop: function( draggable, event ) {
13196 
13197  var dropped = false;
13198 
13199  // Create a copy of the droppables in case the list changes during the drop (#9116)
13200  $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13201 
13202  if ( !this.options ) {
13203  return;
13204  }
13205  if ( !this.options.disabled && this.visible &&
13206  intersect( draggable, this, this.options.tolerance, event ) ) {
13207  dropped = this._drop.call( this, event ) || dropped;
13208  }
13209 
13210  if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13211  ( draggable.currentItem || draggable.element ) ) ) {
13212  this.isout = true;
13213  this.isover = false;
13214  this._deactivate.call( this, event );
13215  }
13216 
13217  } );
13218  return dropped;
13219 
13220  },
13221  dragStart: function( draggable, event ) {
13222 
13223  // Listen for scrolling so that if the dragging causes scrolling the position of the
13224  // droppables can be recalculated (see #5003)
13225  draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13226  if ( !draggable.options.refreshPositions ) {
13227  $.ui.ddmanager.prepareOffsets( draggable, event );
13228  }
13229  } );
13230  },
13231  drag: function( draggable, event ) {
13232 
13233  // If you have a highly dynamic page, you might try this option. It renders positions
13234  // every time you move the mouse.
13235  if ( draggable.options.refreshPositions ) {
13236  $.ui.ddmanager.prepareOffsets( draggable, event );
13237  }
13238 
13239  // Run through all droppables and check their positions based on specific tolerance options
13240  $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13241 
13242  if ( this.options.disabled || this.greedyChild || !this.visible ) {
13243  return;
13244  }
13245 
13246  var parentInstance, scope, parent,
13247  intersects = intersect( draggable, this, this.options.tolerance, event ),
13248  c = !intersects && this.isover ?
13249  "isout" :
13250  ( intersects && !this.isover ? "isover" : null );
13251  if ( !c ) {
13252  return;
13253  }
13254 
13255  if ( this.options.greedy ) {
13256 
13257  // find droppable parents with same scope
13258  scope = this.options.scope;
13259  parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13260  return $( this ).droppable( "instance" ).options.scope === scope;
13261  } );
13262 
13263  if ( parent.length ) {
13264  parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13265  parentInstance.greedyChild = ( c === "isover" );
13266  }
13267  }
13268 
13269  // We just moved into a greedy child
13270  if ( parentInstance && c === "isover" ) {
13271  parentInstance.isover = false;
13272  parentInstance.isout = true;
13273  parentInstance._out.call( parentInstance, event );
13274  }
13275 
13276  this[ c ] = true;
13277  this[ c === "isout" ? "isover" : "isout" ] = false;
13278  this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13279 
13280  // We just moved out of a greedy child
13281  if ( parentInstance && c === "isout" ) {
13282  parentInstance.isout = false;
13283  parentInstance.isover = true;
13284  parentInstance._over.call( parentInstance, event );
13285  }
13286  } );
13287 
13288  },
13289  dragStop: function( draggable, event ) {
13290  draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13291 
13292  // Call prepareOffsets one final time since IE does not fire return scroll events when
13293  // overflow was caused by drag (see #5003)
13294  if ( !draggable.options.refreshPositions ) {
13295  $.ui.ddmanager.prepareOffsets( draggable, event );
13296  }
13297  }
13298 };
13299 
13300 // DEPRECATED
13301 // TODO: switch return back to widget declaration at top of file when this is removed
13302 if ( $.uiBackCompat !== false ) {
13303 
13304  // Backcompat for activeClass and hoverClass options
13305  $.widget( "ui.droppable", $.ui.droppable, {
13306  options: {
13307  hoverClass: false,
13308  activeClass: false
13309  },
13310  _addActiveClass: function() {
13311  this._super();
13312  if ( this.options.activeClass ) {
13313  this.element.addClass( this.options.activeClass );
13314  }
13315  },
13316  _removeActiveClass: function() {
13317  this._super();
13318  if ( this.options.activeClass ) {
13319  this.element.removeClass( this.options.activeClass );
13320  }
13321  },
13322  _addHoverClass: function() {
13323  this._super();
13324  if ( this.options.hoverClass ) {
13325  this.element.addClass( this.options.hoverClass );
13326  }
13327  },
13328  _removeHoverClass: function() {
13329  this._super();
13330  if ( this.options.hoverClass ) {
13331  this.element.removeClass( this.options.hoverClass );
13332  }
13333  }
13334  } );
13335 }
13336 
13337 var widgetsDroppable = $.ui.droppable;
13338 
13339 
13349 //>>label: Progressbar
13350 //>>group: Widgets
13351 // jscs:disable maximumLineLength
13352 //>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13353 // jscs:enable maximumLineLength
13354 //>>docs: http://api.jqueryui.com/progressbar/
13355 //>>demos: http://jqueryui.com/progressbar/
13356 //>>css.structure: ../../themes/base/core.css
13357 //>>css.structure: ../../themes/base/progressbar.css
13358 //>>css.theme: ../../themes/base/theme.css
13359 
13360 
13361 
13362 var widgetsProgressbar = $.widget( "ui.progressbar", {
13363  version: "1.12.1",
13364  options: {
13365  classes: {
13366  "ui-progressbar": "ui-corner-all",
13367  "ui-progressbar-value": "ui-corner-left",
13368  "ui-progressbar-complete": "ui-corner-right"
13369  },
13370  max: 100,
13371  value: 0,
13372 
13373  change: null,
13374  complete: null
13375  },
13376 
13377  min: 0,
13378 
13379  _create: function() {
13380 
13381  // Constrain initial value
13382  this.oldValue = this.options.value = this._constrainedValue();
13383 
13384  this.element.attr( {
13385 
13386  // Only set static values; aria-valuenow and aria-valuemax are
13387  // set inside _refreshValue()
13388  role: "progressbar",
13389  "aria-valuemin": this.min
13390  } );
13391  this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13392 
13393  this.valueDiv = $( "<div>" ).appendTo( this.element );
13394  this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13395  this._refreshValue();
13396  },
13397 
13398  _destroy: function() {
13399  this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13400 
13401  this.valueDiv.remove();
13402  },
13403 
13404  value: function( newValue ) {
13405  if ( newValue === undefined ) {
13406  return this.options.value;
13407  }
13408 
13409  this.options.value = this._constrainedValue( newValue );
13410  this._refreshValue();
13411  },
13412 
13413  _constrainedValue: function( newValue ) {
13414  if ( newValue === undefined ) {
13415  newValue = this.options.value;
13416  }
13417 
13418  this.indeterminate = newValue === false;
13419 
13420  // Sanitize value
13421  if ( typeof newValue !== "number" ) {
13422  newValue = 0;
13423  }
13424 
13425  return this.indeterminate ? false :
13426  Math.min( this.options.max, Math.max( this.min, newValue ) );
13427  },
13428 
13429  _setOptions: function( options ) {
13430 
13431  // Ensure "value" option is set after other values (like max)
13432  var value = options.value;
13433  delete options.value;
13434 
13435  this._super( options );
13436 
13437  this.options.value = this._constrainedValue( value );
13438  this._refreshValue();
13439  },
13440 
13441  _setOption: function( key, value ) {
13442  if ( key === "max" ) {
13443 
13444  // Don't allow a max less than min
13445  value = Math.max( this.min, value );
13446  }
13447  this._super( key, value );
13448  },
13449 
13450  _setOptionDisabled: function( value ) {
13451  this._super( value );
13452 
13453  this.element.attr( "aria-disabled", value );
13454  this._toggleClass( null, "ui-state-disabled", !!value );
13455  },
13456 
13457  _percentage: function() {
13458  return this.indeterminate ?
13459  100 :
13460  100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13461  },
13462 
13463  _refreshValue: function() {
13464  var value = this.options.value,
13465  percentage = this._percentage();
13466 
13467  this.valueDiv
13468  .toggle( this.indeterminate || value > this.min )
13469  .width( percentage.toFixed( 0 ) + "%" );
13470 
13471  this
13472  ._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13473  value === this.options.max )
13474  ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13475 
13476  if ( this.indeterminate ) {
13477  this.element.removeAttr( "aria-valuenow" );
13478  if ( !this.overlayDiv ) {
13479  this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13480  this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13481  }
13482  } else {
13483  this.element.attr( {
13484  "aria-valuemax": this.options.max,
13485  "aria-valuenow": value
13486  } );
13487  if ( this.overlayDiv ) {
13488  this.overlayDiv.remove();
13489  this.overlayDiv = null;
13490  }
13491  }
13492 
13493  if ( this.oldValue !== value ) {
13494  this.oldValue = value;
13495  this._trigger( "change" );
13496  }
13497  if ( value === this.options.max ) {
13498  this._trigger( "complete" );
13499  }
13500  }
13501 } );
13502 
13503 
13513 //>>label: Selectable
13514 //>>group: Interactions
13515 //>>description: Allows groups of elements to be selected with the mouse.
13516 //>>docs: http://api.jqueryui.com/selectable/
13517 //>>demos: http://jqueryui.com/selectable/
13518 //>>css.structure: ../../themes/base/selectable.css
13519 
13520 
13521 
13522 var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13523  version: "1.12.1",
13524  options: {
13525  appendTo: "body",
13526  autoRefresh: true,
13527  distance: 0,
13528  filter: "*",
13529  tolerance: "touch",
13530 
13531  // Callbacks
13532  selected: null,
13533  selecting: null,
13534  start: null,
13535  stop: null,
13536  unselected: null,
13537  unselecting: null
13538  },
13539  _create: function() {
13540  var that = this;
13541 
13542  this._addClass( "ui-selectable" );
13543 
13544  this.dragged = false;
13545 
13546  // Cache selectee children based on filter
13547  this.refresh = function() {
13548  that.elementPos = $( that.element[ 0 ] ).offset();
13549  that.selectees = $( that.options.filter, that.element[ 0 ] );
13550  that._addClass( that.selectees, "ui-selectee" );
13551  that.selectees.each( function() {
13552  var $this = $( this ),
13553  selecteeOffset = $this.offset(),
13554  pos = {
13555  left: selecteeOffset.left - that.elementPos.left,
13556  top: selecteeOffset.top - that.elementPos.top
13557  };
13558  $.data( this, "selectable-item", {
13559  element: this,
13560  $element: $this,
13561  left: pos.left,
13562  top: pos.top,
13563  right: pos.left + $this.outerWidth(),
13564  bottom: pos.top + $this.outerHeight(),
13565  startselected: false,
13566  selected: $this.hasClass( "ui-selected" ),
13567  selecting: $this.hasClass( "ui-selecting" ),
13568  unselecting: $this.hasClass( "ui-unselecting" )
13569  } );
13570  } );
13571  };
13572  this.refresh();
13573 
13574  this._mouseInit();
13575 
13576  this.helper = $( "<div>" );
13577  this._addClass( this.helper, "ui-selectable-helper" );
13578  },
13579 
13580  _destroy: function() {
13581  this.selectees.removeData( "selectable-item" );
13582  this._mouseDestroy();
13583  },
13584 
13585  _mouseStart: function( event ) {
13586  var that = this,
13587  options = this.options;
13588 
13589  this.opos = [ event.pageX, event.pageY ];
13590  this.elementPos = $( this.element[ 0 ] ).offset();
13591 
13592  if ( this.options.disabled ) {
13593  return;
13594  }
13595 
13596  this.selectees = $( options.filter, this.element[ 0 ] );
13597 
13598  this._trigger( "start", event );
13599 
13600  $( options.appendTo ).append( this.helper );
13601 
13602  // position helper (lasso)
13603  this.helper.css( {
13604  "left": event.pageX,
13605  "top": event.pageY,
13606  "width": 0,
13607  "height": 0
13608  } );
13609 
13610  if ( options.autoRefresh ) {
13611  this.refresh();
13612  }
13613 
13614  this.selectees.filter( ".ui-selected" ).each( function() {
13615  var selectee = $.data( this, "selectable-item" );
13616  selectee.startselected = true;
13617  if ( !event.metaKey && !event.ctrlKey ) {
13618  that._removeClass( selectee.$element, "ui-selected" );
13619  selectee.selected = false;
13620  that._addClass( selectee.$element, "ui-unselecting" );
13621  selectee.unselecting = true;
13622 
13623  // selectable UNSELECTING callback
13624  that._trigger( "unselecting", event, {
13625  unselecting: selectee.element
13626  } );
13627  }
13628  } );
13629 
13630  $( event.target ).parents().addBack().each( function() {
13631  var doSelect,
13632  selectee = $.data( this, "selectable-item" );
13633  if ( selectee ) {
13634  doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13635  !selectee.$element.hasClass( "ui-selected" );
13636  that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13637  ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13638  selectee.unselecting = !doSelect;
13639  selectee.selecting = doSelect;
13640  selectee.selected = doSelect;
13641 
13642  // selectable (UN)SELECTING callback
13643  if ( doSelect ) {
13644  that._trigger( "selecting", event, {
13645  selecting: selectee.element
13646  } );
13647  } else {
13648  that._trigger( "unselecting", event, {
13649  unselecting: selectee.element
13650  } );
13651  }
13652  return false;
13653  }
13654  } );
13655 
13656  },
13657 
13658  _mouseDrag: function( event ) {
13659 
13660  this.dragged = true;
13661 
13662  if ( this.options.disabled ) {
13663  return;
13664  }
13665 
13666  var tmp,
13667  that = this,
13668  options = this.options,
13669  x1 = this.opos[ 0 ],
13670  y1 = this.opos[ 1 ],
13671  x2 = event.pageX,
13672  y2 = event.pageY;
13673 
13674  if ( x1 > x2 ) { tmp = x2; x2 = x1; x1 = tmp; }
13675  if ( y1 > y2 ) { tmp = y2; y2 = y1; y1 = tmp; }
13676  this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13677 
13678  this.selectees.each( function() {
13679  var selectee = $.data( this, "selectable-item" ),
13680  hit = false,
13681  offset = {};
13682 
13683  //prevent helper from being selected if appendTo: selectable
13684  if ( !selectee || selectee.element === that.element[ 0 ] ) {
13685  return;
13686  }
13687 
13688  offset.left = selectee.left + that.elementPos.left;
13689  offset.right = selectee.right + that.elementPos.left;
13690  offset.top = selectee.top + that.elementPos.top;
13691  offset.bottom = selectee.bottom + that.elementPos.top;
13692 
13693  if ( options.tolerance === "touch" ) {
13694  hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13695  offset.bottom < y1 ) );
13696  } else if ( options.tolerance === "fit" ) {
13697  hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13698  offset.bottom < y2 );
13699  }
13700 
13701  if ( hit ) {
13702 
13703  // SELECT
13704  if ( selectee.selected ) {
13705  that._removeClass( selectee.$element, "ui-selected" );
13706  selectee.selected = false;
13707  }
13708  if ( selectee.unselecting ) {
13709  that._removeClass( selectee.$element, "ui-unselecting" );
13710  selectee.unselecting = false;
13711  }
13712  if ( !selectee.selecting ) {
13713  that._addClass( selectee.$element, "ui-selecting" );
13714  selectee.selecting = true;
13715 
13716  // selectable SELECTING callback
13717  that._trigger( "selecting", event, {
13718  selecting: selectee.element
13719  } );
13720  }
13721  } else {
13722 
13723  // UNSELECT
13724  if ( selectee.selecting ) {
13725  if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
13726  that._removeClass( selectee.$element, "ui-selecting" );
13727  selectee.selecting = false;
13728  that._addClass( selectee.$element, "ui-selected" );
13729  selectee.selected = true;
13730  } else {
13731  that._removeClass( selectee.$element, "ui-selecting" );
13732  selectee.selecting = false;
13733  if ( selectee.startselected ) {
13734  that._addClass( selectee.$element, "ui-unselecting" );
13735  selectee.unselecting = true;
13736  }
13737 
13738  // selectable UNSELECTING callback
13739  that._trigger( "unselecting", event, {
13740  unselecting: selectee.element
13741  } );
13742  }
13743  }
13744  if ( selectee.selected ) {
13745  if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
13746  that._removeClass( selectee.$element, "ui-selected" );
13747  selectee.selected = false;
13748 
13749  that._addClass( selectee.$element, "ui-unselecting" );
13750  selectee.unselecting = true;
13751 
13752  // selectable UNSELECTING callback
13753  that._trigger( "unselecting", event, {
13754  unselecting: selectee.element
13755  } );
13756  }
13757  }
13758  }
13759  } );
13760 
13761  return false;
13762  },
13763 
13764  _mouseStop: function( event ) {
13765  var that = this;
13766 
13767  this.dragged = false;
13768 
13769  $( ".ui-unselecting", this.element[ 0 ] ).each( function() {
13770  var selectee = $.data( this, "selectable-item" );
13771  that._removeClass( selectee.$element, "ui-unselecting" );
13772  selectee.unselecting = false;
13773  selectee.startselected = false;
13774  that._trigger( "unselected", event, {
13775  unselected: selectee.element
13776  } );
13777  } );
13778  $( ".ui-selecting", this.element[ 0 ] ).each( function() {
13779  var selectee = $.data( this, "selectable-item" );
13780  that._removeClass( selectee.$element, "ui-selecting" )
13781  ._addClass( selectee.$element, "ui-selected" );
13782  selectee.selecting = false;
13783  selectee.selected = true;
13784  selectee.startselected = true;
13785  that._trigger( "selected", event, {
13786  selected: selectee.element
13787  } );
13788  } );
13789  this._trigger( "stop", event );
13790 
13791  this.helper.remove();
13792 
13793  return false;
13794  }
13795 
13796 } );
13797 
13798 
13808 //>>label: Selectmenu
13809 //>>group: Widgets
13810 // jscs:disable maximumLineLength
13811 //>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
13812 // jscs:enable maximumLineLength
13813 //>>docs: http://api.jqueryui.com/selectmenu/
13814 //>>demos: http://jqueryui.com/selectmenu/
13815 //>>css.structure: ../../themes/base/core.css
13816 //>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
13817 //>>css.theme: ../../themes/base/theme.css
13818 
13819 
13820 
13821 var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
13822  version: "1.12.1",
13823  defaultElement: "<select>",
13824  options: {
13825  appendTo: null,
13826  classes: {
13827  "ui-selectmenu-button-open": "ui-corner-top",
13828  "ui-selectmenu-button-closed": "ui-corner-all"
13829  },
13830  disabled: null,
13831  icons: {
13832  button: "ui-icon-triangle-1-s"
13833  },
13834  position: {
13835  my: "left top",
13836  at: "left bottom",
13837  collision: "none"
13838  },
13839  width: false,
13840 
13841  // Callbacks
13842  change: null,
13843  close: null,
13844  focus: null,
13845  open: null,
13846  select: null
13847  },
13848 
13849  _create: function() {
13850  var selectmenuId = this.element.uniqueId().attr( "id" );
13851  this.ids = {
13852  element: selectmenuId,
13853  button: selectmenuId + "-button",
13854  menu: selectmenuId + "-menu"
13855  };
13856 
13857  this._drawButton();
13858  this._drawMenu();
13859  this._bindFormResetHandler();
13860 
13861  this._rendered = false;
13862  this.menuItems = $();
13863  },
13864 
13865  _drawButton: function() {
13866  var icon,
13867  that = this,
13868  item = this._parseOption(
13869  this.element.find( "option:selected" ),
13870  this.element[ 0 ].selectedIndex
13871  );
13872 
13873  // Associate existing label with the new button
13874  this.labels = this.element.labels().attr( "for", this.ids.button );
13875  this._on( this.labels, {
13876  click: function( event ) {
13877  this.button.focus();
13878  event.preventDefault();
13879  }
13880  } );
13881 
13882  // Hide original select element
13883  this.element.hide();
13884 
13885  // Create button
13886  this.button = $( "<span>", {
13887  tabindex: this.options.disabled ? -1 : 0,
13888  id: this.ids.button,
13889  role: "combobox",
13890  "aria-expanded": "false",
13891  "aria-autocomplete": "list",
13892  "aria-owns": this.ids.menu,
13893  "aria-haspopup": "true",
13894  title: this.element.attr( "title" )
13895  } )
13896  .insertAfter( this.element );
13897 
13898  this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
13899  "ui-button ui-widget" );
13900 
13901  icon = $( "<span>" ).appendTo( this.button );
13902  this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
13903  this.buttonItem = this._renderButtonItem( item )
13904  .appendTo( this.button );
13905 
13906  if ( this.options.width !== false ) {
13907  this._resizeButton();
13908  }
13909 
13910  this._on( this.button, this._buttonEvents );
13911  this.button.one( "focusin", function() {
13912 
13913  // Delay rendering the menu items until the button receives focus.
13914  // The menu may have already been rendered via a programmatic open.
13915  if ( !that._rendered ) {
13916  that._refreshMenu();
13917  }
13918  } );
13919  },
13920 
13921  _drawMenu: function() {
13922  var that = this;
13923 
13924  // Create menu
13925  this.menu = $( "<ul>", {
13926  "aria-hidden": "true",
13927  "aria-labelledby": this.ids.button,
13928  id: this.ids.menu
13929  } );
13930 
13931  // Wrap menu
13932  this.menuWrap = $( "<div>" ).append( this.menu );
13933  this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
13934  this.menuWrap.appendTo( this._appendTo() );
13935 
13936  // Initialize menu widget
13937  this.menuInstance = this.menu
13938  .menu( {
13939  classes: {
13940  "ui-menu": "ui-corner-bottom"
13941  },
13942  role: "listbox",
13943  select: function( event, ui ) {
13944  event.preventDefault();
13945 
13946  // Support: IE8
13947  // If the item was selected via a click, the text selection
13948  // will be destroyed in IE
13949  that._setSelection();
13950 
13951  that._select( ui.item.data( "ui-selectmenu-item" ), event );
13952  },
13953  focus: function( event, ui ) {
13954  var item = ui.item.data( "ui-selectmenu-item" );
13955 
13956  // Prevent inital focus from firing and check if its a newly focused item
13957  if ( that.focusIndex != null && item.index !== that.focusIndex ) {
13958  that._trigger( "focus", event, { item: item } );
13959  if ( !that.isOpen ) {
13960  that._select( item, event );
13961  }
13962  }
13963  that.focusIndex = item.index;
13964 
13965  that.button.attr( "aria-activedescendant",
13966  that.menuItems.eq( item.index ).attr( "id" ) );
13967  }
13968  } )
13969  .menu( "instance" );
13970 
13971  // Don't close the menu on mouseleave
13972  this.menuInstance._off( this.menu, "mouseleave" );
13973 
13974  // Cancel the menu's collapseAll on document click
13975  this.menuInstance._closeOnDocumentClick = function() {
13976  return false;
13977  };
13978 
13979  // Selects often contain empty items, but never contain dividers
13980  this.menuInstance._isDivider = function() {
13981  return false;
13982  };
13983  },
13984 
13985  refresh: function() {
13986  this._refreshMenu();
13987  this.buttonItem.replaceWith(
13988  this.buttonItem = this._renderButtonItem(
13989 
13990  // Fall back to an empty object in case there are no options
13991  this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
13992  )
13993  );
13994  if ( this.options.width === null ) {
13995  this._resizeButton();
13996  }
13997  },
13998 
13999  _refreshMenu: function() {
14000  var item,
14001  options = this.element.find( "option" );
14002 
14003  this.menu.empty();
14004 
14005  this._parseOptions( options );
14006  this._renderMenu( this.menu, this.items );
14007 
14008  this.menuInstance.refresh();
14009  this.menuItems = this.menu.find( "li" )
14010  .not( ".ui-selectmenu-optgroup" )
14011  .find( ".ui-menu-item-wrapper" );
14012 
14013  this._rendered = true;
14014 
14015  if ( !options.length ) {
14016  return;
14017  }
14018 
14019  item = this._getSelectedItem();
14020 
14021  // Update the menu to have the correct item focused
14022  this.menuInstance.focus( null, item );
14023  this._setAria( item.data( "ui-selectmenu-item" ) );
14024 
14025  // Set disabled state
14026  this._setOption( "disabled", this.element.prop( "disabled" ) );
14027  },
14028 
14029  open: function( event ) {
14030  if ( this.options.disabled ) {
14031  return;
14032  }
14033 
14034  // If this is the first time the menu is being opened, render the items
14035  if ( !this._rendered ) {
14036  this._refreshMenu();
14037  } else {
14038 
14039  // Menu clears focus on close, reset focus to selected item
14040  this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14041  this.menuInstance.focus( null, this._getSelectedItem() );
14042  }
14043 
14044  // If there are no options, don't open the menu
14045  if ( !this.menuItems.length ) {
14046  return;
14047  }
14048 
14049  this.isOpen = true;
14050  this._toggleAttr();
14051  this._resizeMenu();
14052  this._position();
14053 
14054  this._on( this.document, this._documentClick );
14055 
14056  this._trigger( "open", event );
14057  },
14058 
14059  _position: function() {
14060  this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14061  },
14062 
14063  close: function( event ) {
14064  if ( !this.isOpen ) {
14065  return;
14066  }
14067 
14068  this.isOpen = false;
14069  this._toggleAttr();
14070 
14071  this.range = null;
14072  this._off( this.document );
14073 
14074  this._trigger( "close", event );
14075  },
14076 
14077  widget: function() {
14078  return this.button;
14079  },
14080 
14081  menuWidget: function() {
14082  return this.menu;
14083  },
14084 
14085  _renderButtonItem: function( item ) {
14086  var buttonItem = $( "<span>" );
14087 
14088  this._setText( buttonItem, item.label );
14089  this._addClass( buttonItem, "ui-selectmenu-text" );
14090 
14091  return buttonItem;
14092  },
14093 
14094  _renderMenu: function( ul, items ) {
14095  var that = this,
14096  currentOptgroup = "";
14097 
14098  $.each( items, function( index, item ) {
14099  var li;
14100 
14101  if ( item.optgroup !== currentOptgroup ) {
14102  li = $( "<li>", {
14103  text: item.optgroup
14104  } );
14105  that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14106  ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14107  " ui-state-disabled" :
14108  "" ) );
14109 
14110  li.appendTo( ul );
14111 
14112  currentOptgroup = item.optgroup;
14113  }
14114 
14115  that._renderItemData( ul, item );
14116  } );
14117  },
14118 
14119  _renderItemData: function( ul, item ) {
14120  return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14121  },
14122 
14123  _renderItem: function( ul, item ) {
14124  var li = $( "<li>" ),
14125  wrapper = $( "<div>", {
14126  title: item.element.attr( "title" )
14127  } );
14128 
14129  if ( item.disabled ) {
14130  this._addClass( li, null, "ui-state-disabled" );
14131  }
14132  this._setText( wrapper, item.label );
14133 
14134  return li.append( wrapper ).appendTo( ul );
14135  },
14136 
14137  _setText: function( element, value ) {
14138  if ( value ) {
14139  element.text( value );
14140  } else {
14141  element.html( "&#160;" );
14142  }
14143  },
14144 
14145  _move: function( direction, event ) {
14146  var item, next,
14147  filter = ".ui-menu-item";
14148 
14149  if ( this.isOpen ) {
14150  item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14151  } else {
14152  item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14153  filter += ":not(.ui-state-disabled)";
14154  }
14155 
14156  if ( direction === "first" || direction === "last" ) {
14157  next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14158  } else {
14159  next = item[ direction + "All" ]( filter ).eq( 0 );
14160  }
14161 
14162  if ( next.length ) {
14163  this.menuInstance.focus( event, next );
14164  }
14165  },
14166 
14167  _getSelectedItem: function() {
14168  return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14169  },
14170 
14171  _toggle: function( event ) {
14172  this[ this.isOpen ? "close" : "open" ]( event );
14173  },
14174 
14175  _setSelection: function() {
14176  var selection;
14177 
14178  if ( !this.range ) {
14179  return;
14180  }
14181 
14182  if ( window.getSelection ) {
14183  selection = window.getSelection();
14184  selection.removeAllRanges();
14185  selection.addRange( this.range );
14186 
14187  // Support: IE8
14188  } else {
14189  this.range.select();
14190  }
14191 
14192  // Support: IE
14193  // Setting the text selection kills the button focus in IE, but
14194  // restoring the focus doesn't kill the selection.
14195  this.button.focus();
14196  },
14197 
14198  _documentClick: {
14199  mousedown: function( event ) {
14200  if ( !this.isOpen ) {
14201  return;
14202  }
14203 
14204  if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14205  $.ui.escapeSelector( this.ids.button ) ).length ) {
14206  this.close( event );
14207  }
14208  }
14209  },
14210 
14211  _buttonEvents: {
14212 
14213  // Prevent text selection from being reset when interacting with the selectmenu (#10144)
14214  mousedown: function() {
14215  var selection;
14216 
14217  if ( window.getSelection ) {
14218  selection = window.getSelection();
14219  if ( selection.rangeCount ) {
14220  this.range = selection.getRangeAt( 0 );
14221  }
14222 
14223  // Support: IE8
14224  } else {
14225  this.range = document.selection.createRange();
14226  }
14227  },
14228 
14229  click: function( event ) {
14230  this._setSelection();
14231  this._toggle( event );
14232  },
14233 
14234  keydown: function( event ) {
14235  var preventDefault = true;
14236  switch ( event.keyCode ) {
14237  case $.ui.keyCode.TAB:
14238  case $.ui.keyCode.ESCAPE:
14239  this.close( event );
14240  preventDefault = false;
14241  break;
14242  case $.ui.keyCode.ENTER:
14243  if ( this.isOpen ) {
14244  this._selectFocusedItem( event );
14245  }
14246  break;
14247  case $.ui.keyCode.UP:
14248  if ( event.altKey ) {
14249  this._toggle( event );
14250  } else {
14251  this._move( "prev", event );
14252  }
14253  break;
14254  case $.ui.keyCode.DOWN:
14255  if ( event.altKey ) {
14256  this._toggle( event );
14257  } else {
14258  this._move( "next", event );
14259  }
14260  break;
14261  case $.ui.keyCode.SPACE:
14262  if ( this.isOpen ) {
14263  this._selectFocusedItem( event );
14264  } else {
14265  this._toggle( event );
14266  }
14267  break;
14268  case $.ui.keyCode.LEFT:
14269  this._move( "prev", event );
14270  break;
14271  case $.ui.keyCode.RIGHT:
14272  this._move( "next", event );
14273  break;
14274  case $.ui.keyCode.HOME:
14275  case $.ui.keyCode.PAGE_UP:
14276  this._move( "first", event );
14277  break;
14278  case $.ui.keyCode.END:
14279  case $.ui.keyCode.PAGE_DOWN:
14280  this._move( "last", event );
14281  break;
14282  default:
14283  this.menu.trigger( event );
14284  preventDefault = false;
14285  }
14286 
14287  if ( preventDefault ) {
14288  event.preventDefault();
14289  }
14290  }
14291  },
14292 
14293  _selectFocusedItem: function( event ) {
14294  var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14295  if ( !item.hasClass( "ui-state-disabled" ) ) {
14296  this._select( item.data( "ui-selectmenu-item" ), event );
14297  }
14298  },
14299 
14300  _select: function( item, event ) {
14301  var oldIndex = this.element[ 0 ].selectedIndex;
14302 
14303  // Change native select element
14304  this.element[ 0 ].selectedIndex = item.index;
14305  this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14306  this._setAria( item );
14307  this._trigger( "select", event, { item: item } );
14308 
14309  if ( item.index !== oldIndex ) {
14310  this._trigger( "change", event, { item: item } );
14311  }
14312 
14313  this.close( event );
14314  },
14315 
14316  _setAria: function( item ) {
14317  var id = this.menuItems.eq( item.index ).attr( "id" );
14318 
14319  this.button.attr( {
14320  "aria-labelledby": id,
14321  "aria-activedescendant": id
14322  } );
14323  this.menu.attr( "aria-activedescendant", id );
14324  },
14325 
14326  _setOption: function( key, value ) {
14327  if ( key === "icons" ) {
14328  var icon = this.button.find( "span.ui-icon" );
14329  this._removeClass( icon, null, this.options.icons.button )
14330  ._addClass( icon, null, value.button );
14331  }
14332 
14333  this._super( key, value );
14334 
14335  if ( key === "appendTo" ) {
14336  this.menuWrap.appendTo( this._appendTo() );
14337  }
14338 
14339  if ( key === "width" ) {
14340  this._resizeButton();
14341  }
14342  },
14343 
14344  _setOptionDisabled: function( value ) {
14345  this._super( value );
14346 
14347  this.menuInstance.option( "disabled", value );
14348  this.button.attr( "aria-disabled", value );
14349  this._toggleClass( this.button, null, "ui-state-disabled", value );
14350 
14351  this.element.prop( "disabled", value );
14352  if ( value ) {
14353  this.button.attr( "tabindex", -1 );
14354  this.close();
14355  } else {
14356  this.button.attr( "tabindex", 0 );
14357  }
14358  },
14359 
14360  _appendTo: function() {
14361  var element = this.options.appendTo;
14362 
14363  if ( element ) {
14364  element = element.jquery || element.nodeType ?
14365  $( element ) :
14366  this.document.find( element ).eq( 0 );
14367  }
14368 
14369  if ( !element || !element[ 0 ] ) {
14370  element = this.element.closest( ".ui-front, dialog" );
14371  }
14372 
14373  if ( !element.length ) {
14374  element = this.document[ 0 ].body;
14375  }
14376 
14377  return element;
14378  },
14379 
14380  _toggleAttr: function() {
14381  this.button.attr( "aria-expanded", this.isOpen );
14382 
14383  // We can't use two _toggleClass() calls here, because we need to make sure
14384  // we always remove classes first and add them second, otherwise if both classes have the
14385  // same theme class, it will be removed after we add it.
14386  this._removeClass( this.button, "ui-selectmenu-button-" +
14387  ( this.isOpen ? "closed" : "open" ) )
14388  ._addClass( this.button, "ui-selectmenu-button-" +
14389  ( this.isOpen ? "open" : "closed" ) )
14390  ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14391 
14392  this.menu.attr( "aria-hidden", !this.isOpen );
14393  },
14394 
14395  _resizeButton: function() {
14396  var width = this.options.width;
14397 
14398  // For `width: false`, just remove inline style and stop
14399  if ( width === false ) {
14400  this.button.css( "width", "" );
14401  return;
14402  }
14403 
14404  // For `width: null`, match the width of the original element
14405  if ( width === null ) {
14406  width = this.element.show().outerWidth();
14407  this.element.hide();
14408  }
14409 
14410  this.button.outerWidth( width );
14411  },
14412 
14413  _resizeMenu: function() {
14414  this.menu.outerWidth( Math.max(
14415  this.button.outerWidth(),
14416 
14417  // Support: IE10
14418  // IE10 wraps long text (possibly a rounding bug)
14419  // so we add 1px to avoid the wrapping
14420  this.menu.width( "" ).outerWidth() + 1
14421  ) );
14422  },
14423 
14424  _getCreateOptions: function() {
14425  var options = this._super();
14426 
14427  options.disabled = this.element.prop( "disabled" );
14428 
14429  return options;
14430  },
14431 
14432  _parseOptions: function( options ) {
14433  var that = this,
14434  data = [];
14435  options.each( function( index, item ) {
14436  data.push( that._parseOption( $( item ), index ) );
14437  } );
14438  this.items = data;
14439  },
14440 
14441  _parseOption: function( option, index ) {
14442  var optgroup = option.parent( "optgroup" );
14443 
14444  return {
14445  element: option,
14446  index: index,
14447  value: option.val(),
14448  label: option.text(),
14449  optgroup: optgroup.attr( "label" ) || "",
14450  disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14451  };
14452  },
14453 
14454  _destroy: function() {
14455  this._unbindFormResetHandler();
14456  this.menuWrap.remove();
14457  this.button.remove();
14458  this.element.show();
14459  this.element.removeUniqueId();
14460  this.labels.attr( "for", this.ids.element );
14461  }
14462 } ] );
14463 
14464 
14474 //>>label: Slider
14475 //>>group: Widgets
14476 //>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14477 //>>docs: http://api.jqueryui.com/slider/
14478 //>>demos: http://jqueryui.com/slider/
14479 //>>css.structure: ../../themes/base/core.css
14480 //>>css.structure: ../../themes/base/slider.css
14481 //>>css.theme: ../../themes/base/theme.css
14482 
14483 
14484 
14485 var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14486  version: "1.12.1",
14487  widgetEventPrefix: "slide",
14488 
14489  options: {
14490  animate: false,
14491  classes: {
14492  "ui-slider": "ui-corner-all",
14493  "ui-slider-handle": "ui-corner-all",
14494 
14495  // Note: ui-widget-header isn't the most fittingly semantic framework class for this
14496  // element, but worked best visually with a variety of themes
14497  "ui-slider-range": "ui-corner-all ui-widget-header"
14498  },
14499  distance: 0,
14500  max: 100,
14501  min: 0,
14502  orientation: "horizontal",
14503  range: false,
14504  step: 1,
14505  value: 0,
14506  values: null,
14507 
14508  // Callbacks
14509  change: null,
14510  slide: null,
14511  start: null,
14512  stop: null
14513  },
14514 
14515  // Number of pages in a slider
14516  // (how many times can you page up/down to go through the whole range)
14517  numPages: 5,
14518 
14519  _create: function() {
14520  this._keySliding = false;
14521  this._mouseSliding = false;
14522  this._animateOff = true;
14523  this._handleIndex = null;
14524  this._detectOrientation();
14525  this._mouseInit();
14526  this._calculateNewMax();
14527 
14528  this._addClass( "ui-slider ui-slider-" + this.orientation,
14529  "ui-widget ui-widget-content" );
14530 
14531  this._refresh();
14532 
14533  this._animateOff = false;
14534  },
14535 
14536  _refresh: function() {
14537  this._createRange();
14538  this._createHandles();
14539  this._setupEvents();
14540  this._refreshValue();
14541  },
14542 
14543  _createHandles: function() {
14544  var i, handleCount,
14545  options = this.options,
14546  existingHandles = this.element.find( ".ui-slider-handle" ),
14547  handle = "<span tabindex='0'></span>",
14548  handles = [];
14549 
14550  handleCount = ( options.values && options.values.length ) || 1;
14551 
14552  if ( existingHandles.length > handleCount ) {
14553  existingHandles.slice( handleCount ).remove();
14554  existingHandles = existingHandles.slice( 0, handleCount );
14555  }
14556 
14557  for ( i = existingHandles.length; i < handleCount; i++ ) {
14558  handles.push( handle );
14559  }
14560 
14561  this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14562 
14563  this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14564 
14565  this.handle = this.handles.eq( 0 );
14566 
14567  this.handles.each( function( i ) {
14568  $( this )
14569  .data( "ui-slider-handle-index", i )
14570  .attr( "tabIndex", 0 );
14571  } );
14572  },
14573 
14574  _createRange: function() {
14575  var options = this.options;
14576 
14577  if ( options.range ) {
14578  if ( options.range === true ) {
14579  if ( !options.values ) {
14580  options.values = [ this._valueMin(), this._valueMin() ];
14581  } else if ( options.values.length && options.values.length !== 2 ) {
14582  options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14583  } else if ( $.isArray( options.values ) ) {
14584  options.values = options.values.slice( 0 );
14585  }
14586  }
14587 
14588  if ( !this.range || !this.range.length ) {
14589  this.range = $( "<div>" )
14590  .appendTo( this.element );
14591 
14592  this._addClass( this.range, "ui-slider-range" );
14593  } else {
14594  this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14595 
14596  // Handle range switching from true to min/max
14597  this.range.css( {
14598  "left": "",
14599  "bottom": ""
14600  } );
14601  }
14602  if ( options.range === "min" || options.range === "max" ) {
14603  this._addClass( this.range, "ui-slider-range-" + options.range );
14604  }
14605  } else {
14606  if ( this.range ) {
14607  this.range.remove();
14608  }
14609  this.range = null;
14610  }
14611  },
14612 
14613  _setupEvents: function() {
14614  this._off( this.handles );
14615  this._on( this.handles, this._handleEvents );
14616  this._hoverable( this.handles );
14617  this._focusable( this.handles );
14618  },
14619 
14620  _destroy: function() {
14621  this.handles.remove();
14622  if ( this.range ) {
14623  this.range.remove();
14624  }
14625 
14626  this._mouseDestroy();
14627  },
14628 
14629  _mouseCapture: function( event ) {
14630  var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14631  that = this,
14632  o = this.options;
14633 
14634  if ( o.disabled ) {
14635  return false;
14636  }
14637 
14638  this.elementSize = {
14639  width: this.element.outerWidth(),
14640  height: this.element.outerHeight()
14641  };
14642  this.elementOffset = this.element.offset();
14643 
14644  position = { x: event.pageX, y: event.pageY };
14645  normValue = this._normValueFromMouse( position );
14646  distance = this._valueMax() - this._valueMin() + 1;
14647  this.handles.each( function( i ) {
14648  var thisDistance = Math.abs( normValue - that.values( i ) );
14649  if ( ( distance > thisDistance ) ||
14650  ( distance === thisDistance &&
14651  ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14652  distance = thisDistance;
14653  closestHandle = $( this );
14654  index = i;
14655  }
14656  } );
14657 
14658  allowed = this._start( event, index );
14659  if ( allowed === false ) {
14660  return false;
14661  }
14662  this._mouseSliding = true;
14663 
14664  this._handleIndex = index;
14665 
14666  this._addClass( closestHandle, null, "ui-state-active" );
14667  closestHandle.trigger( "focus" );
14668 
14669  offset = closestHandle.offset();
14670  mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14671  this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14672  left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14673  top: event.pageY - offset.top -
14674  ( closestHandle.height() / 2 ) -
14675  ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14676  ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14677  ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14678  };
14679 
14680  if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14681  this._slide( event, index, normValue );
14682  }
14683  this._animateOff = true;
14684  return true;
14685  },
14686 
14687  _mouseStart: function() {
14688  return true;
14689  },
14690 
14691  _mouseDrag: function( event ) {
14692  var position = { x: event.pageX, y: event.pageY },
14693  normValue = this._normValueFromMouse( position );
14694 
14695  this._slide( event, this._handleIndex, normValue );
14696 
14697  return false;
14698  },
14699 
14700  _mouseStop: function( event ) {
14701  this._removeClass( this.handles, null, "ui-state-active" );
14702  this._mouseSliding = false;
14703 
14704  this._stop( event, this._handleIndex );
14705  this._change( event, this._handleIndex );
14706 
14707  this._handleIndex = null;
14708  this._clickOffset = null;
14709  this._animateOff = false;
14710 
14711  return false;
14712  },
14713 
14714  _detectOrientation: function() {
14715  this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
14716  },
14717 
14718  _normValueFromMouse: function( position ) {
14719  var pixelTotal,
14720  pixelMouse,
14721  percentMouse,
14722  valueTotal,
14723  valueMouse;
14724 
14725  if ( this.orientation === "horizontal" ) {
14726  pixelTotal = this.elementSize.width;
14727  pixelMouse = position.x - this.elementOffset.left -
14728  ( this._clickOffset ? this._clickOffset.left : 0 );
14729  } else {
14730  pixelTotal = this.elementSize.height;
14731  pixelMouse = position.y - this.elementOffset.top -
14732  ( this._clickOffset ? this._clickOffset.top : 0 );
14733  }
14734 
14735  percentMouse = ( pixelMouse / pixelTotal );
14736  if ( percentMouse > 1 ) {
14737  percentMouse = 1;
14738  }
14739  if ( percentMouse < 0 ) {
14740  percentMouse = 0;
14741  }
14742  if ( this.orientation === "vertical" ) {
14743  percentMouse = 1 - percentMouse;
14744  }
14745 
14746  valueTotal = this._valueMax() - this._valueMin();
14747  valueMouse = this._valueMin() + percentMouse * valueTotal;
14748 
14749  return this._trimAlignValue( valueMouse );
14750  },
14751 
14752  _uiHash: function( index, value, values ) {
14753  var uiHash = {
14754  handle: this.handles[ index ],
14755  handleIndex: index,
14756  value: value !== undefined ? value : this.value()
14757  };
14758 
14759  if ( this._hasMultipleValues() ) {
14760  uiHash.value = value !== undefined ? value : this.values( index );
14761  uiHash.values = values || this.values();
14762  }
14763 
14764  return uiHash;
14765  },
14766 
14767  _hasMultipleValues: function() {
14768  return this.options.values && this.options.values.length;
14769  },
14770 
14771  _start: function( event, index ) {
14772  return this._trigger( "start", event, this._uiHash( index ) );
14773  },
14774 
14775  _slide: function( event, index, newVal ) {
14776  var allowed, otherVal,
14777  currentValue = this.value(),
14778  newValues = this.values();
14779 
14780  if ( this._hasMultipleValues() ) {
14781  otherVal = this.values( index ? 0 : 1 );
14782  currentValue = this.values( index );
14783 
14784  if ( this.options.values.length === 2 && this.options.range === true ) {
14785  newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
14786  }
14787 
14788  newValues[ index ] = newVal;
14789  }
14790 
14791  if ( newVal === currentValue ) {
14792  return;
14793  }
14794 
14795  allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
14796 
14797  // A slide can be canceled by returning false from the slide callback
14798  if ( allowed === false ) {
14799  return;
14800  }
14801 
14802  if ( this._hasMultipleValues() ) {
14803  this.values( index, newVal );
14804  } else {
14805  this.value( newVal );
14806  }
14807  },
14808 
14809  _stop: function( event, index ) {
14810  this._trigger( "stop", event, this._uiHash( index ) );
14811  },
14812 
14813  _change: function( event, index ) {
14814  if ( !this._keySliding && !this._mouseSliding ) {
14815 
14816  //store the last changed value index for reference when handles overlap
14817  this._lastChangedValue = index;
14818  this._trigger( "change", event, this._uiHash( index ) );
14819  }
14820  },
14821 
14822  value: function( newValue ) {
14823  if ( arguments.length ) {
14824  this.options.value = this._trimAlignValue( newValue );
14825  this._refreshValue();
14826  this._change( null, 0 );
14827  return;
14828  }
14829 
14830  return this._value();
14831  },
14832 
14833  values: function( index, newValue ) {
14834  var vals,
14835  newValues,
14836  i;
14837 
14838  if ( arguments.length > 1 ) {
14839  this.options.values[ index ] = this._trimAlignValue( newValue );
14840  this._refreshValue();
14841  this._change( null, index );
14842  return;
14843  }
14844 
14845  if ( arguments.length ) {
14846  if ( $.isArray( arguments[ 0 ] ) ) {
14847  vals = this.options.values;
14848  newValues = arguments[ 0 ];
14849  for ( i = 0; i < vals.length; i += 1 ) {
14850  vals[ i ] = this._trimAlignValue( newValues[ i ] );
14851  this._change( null, i );
14852  }
14853  this._refreshValue();
14854  } else {
14855  if ( this._hasMultipleValues() ) {
14856  return this._values( index );
14857  } else {
14858  return this.value();
14859  }
14860  }
14861  } else {
14862  return this._values();
14863  }
14864  },
14865 
14866  _setOption: function( key, value ) {
14867  var i,
14868  valsLength = 0;
14869 
14870  if ( key === "range" && this.options.range === true ) {
14871  if ( value === "min" ) {
14872  this.options.value = this._values( 0 );
14873  this.options.values = null;
14874  } else if ( value === "max" ) {
14875  this.options.value = this._values( this.options.values.length - 1 );
14876  this.options.values = null;
14877  }
14878  }
14879 
14880  if ( $.isArray( this.options.values ) ) {
14881  valsLength = this.options.values.length;
14882  }
14883 
14884  this._super( key, value );
14885 
14886  switch ( key ) {
14887  case "orientation":
14888  this._detectOrientation();
14889  this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
14890  ._addClass( "ui-slider-" + this.orientation );
14891  this._refreshValue();
14892  if ( this.options.range ) {
14893  this._refreshRange( value );
14894  }
14895 
14896  // Reset positioning from previous orientation
14897  this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
14898  break;
14899  case "value":
14900  this._animateOff = true;
14901  this._refreshValue();
14902  this._change( null, 0 );
14903  this._animateOff = false;
14904  break;
14905  case "values":
14906  this._animateOff = true;
14907  this._refreshValue();
14908 
14909  // Start from the last handle to prevent unreachable handles (#9046)
14910  for ( i = valsLength - 1; i >= 0; i-- ) {
14911  this._change( null, i );
14912  }
14913  this._animateOff = false;
14914  break;
14915  case "step":
14916  case "min":
14917  case "max":
14918  this._animateOff = true;
14919  this._calculateNewMax();
14920  this._refreshValue();
14921  this._animateOff = false;
14922  break;
14923  case "range":
14924  this._animateOff = true;
14925  this._refresh();
14926  this._animateOff = false;
14927  break;
14928  }
14929  },
14930 
14931  _setOptionDisabled: function( value ) {
14932  this._super( value );
14933 
14934  this._toggleClass( null, "ui-state-disabled", !!value );
14935  },
14936 
14937  //internal value getter
14938  // _value() returns value trimmed by min and max, aligned by step
14939  _value: function() {
14940  var val = this.options.value;
14941  val = this._trimAlignValue( val );
14942 
14943  return val;
14944  },
14945 
14946  //internal values getter
14947  // _values() returns array of values trimmed by min and max, aligned by step
14948  // _values( index ) returns single value trimmed by min and max, aligned by step
14949  _values: function( index ) {
14950  var val,
14951  vals,
14952  i;
14953 
14954  if ( arguments.length ) {
14955  val = this.options.values[ index ];
14956  val = this._trimAlignValue( val );
14957 
14958  return val;
14959  } else if ( this._hasMultipleValues() ) {
14960 
14961  // .slice() creates a copy of the array
14962  // this copy gets trimmed by min and max and then returned
14963  vals = this.options.values.slice();
14964  for ( i = 0; i < vals.length; i += 1 ) {
14965  vals[ i ] = this._trimAlignValue( vals[ i ] );
14966  }
14967 
14968  return vals;
14969  } else {
14970  return [];
14971  }
14972  },
14973 
14974  // Returns the step-aligned value that val is closest to, between (inclusive) min and max
14975  _trimAlignValue: function( val ) {
14976  if ( val <= this._valueMin() ) {
14977  return this._valueMin();
14978  }
14979  if ( val >= this._valueMax() ) {
14980  return this._valueMax();
14981  }
14982  var step = ( this.options.step > 0 ) ? this.options.step : 1,
14983  valModStep = ( val - this._valueMin() ) % step,
14984  alignValue = val - valModStep;
14985 
14986  if ( Math.abs( valModStep ) * 2 >= step ) {
14987  alignValue += ( valModStep > 0 ) ? step : ( -step );
14988  }
14989 
14990  // Since JavaScript has problems with large floats, round
14991  // the final value to 5 digits after the decimal point (see #4124)
14992  return parseFloat( alignValue.toFixed( 5 ) );
14993  },
14994 
14995  _calculateNewMax: function() {
14996  var max = this.options.max,
14997  min = this._valueMin(),
14998  step = this.options.step,
14999  aboveMin = Math.round( ( max - min ) / step ) * step;
15000  max = aboveMin + min;
15001  if ( max > this.options.max ) {
15002 
15003  //If max is not divisible by step, rounding off may increase its value
15004  max -= step;
15005  }
15006  this.max = parseFloat( max.toFixed( this._precision() ) );
15007  },
15008 
15009  _precision: function() {
15010  var precision = this._precisionOf( this.options.step );
15011  if ( this.options.min !== null ) {
15012  precision = Math.max( precision, this._precisionOf( this.options.min ) );
15013  }
15014  return precision;
15015  },
15016 
15017  _precisionOf: function( num ) {
15018  var str = num.toString(),
15019  decimal = str.indexOf( "." );
15020  return decimal === -1 ? 0 : str.length - decimal - 1;
15021  },
15022 
15023  _valueMin: function() {
15024  return this.options.min;
15025  },
15026 
15027  _valueMax: function() {
15028  return this.max;
15029  },
15030 
15031  _refreshRange: function( orientation ) {
15032  if ( orientation === "vertical" ) {
15033  this.range.css( { "width": "", "left": "" } );
15034  }
15035  if ( orientation === "horizontal" ) {
15036  this.range.css( { "height": "", "bottom": "" } );
15037  }
15038  },
15039 
15040  _refreshValue: function() {
15041  var lastValPercent, valPercent, value, valueMin, valueMax,
15042  oRange = this.options.range,
15043  o = this.options,
15044  that = this,
15045  animate = ( !this._animateOff ) ? o.animate : false,
15046  _set = {};
15047 
15048  if ( this._hasMultipleValues() ) {
15049  this.handles.each( function( i ) {
15050  valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15051  that._valueMin() ) * 100;
15052  _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15053  $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15054  if ( that.options.range === true ) {
15055  if ( that.orientation === "horizontal" ) {
15056  if ( i === 0 ) {
15057  that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15058  left: valPercent + "%"
15059  }, o.animate );
15060  }
15061  if ( i === 1 ) {
15062  that.range[ animate ? "animate" : "css" ]( {
15063  width: ( valPercent - lastValPercent ) + "%"
15064  }, {
15065  queue: false,
15066  duration: o.animate
15067  } );
15068  }
15069  } else {
15070  if ( i === 0 ) {
15071  that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15072  bottom: ( valPercent ) + "%"
15073  }, o.animate );
15074  }
15075  if ( i === 1 ) {
15076  that.range[ animate ? "animate" : "css" ]( {
15077  height: ( valPercent - lastValPercent ) + "%"
15078  }, {
15079  queue: false,
15080  duration: o.animate
15081  } );
15082  }
15083  }
15084  }
15085  lastValPercent = valPercent;
15086  } );
15087  } else {
15088  value = this.value();
15089  valueMin = this._valueMin();
15090  valueMax = this._valueMax();
15091  valPercent = ( valueMax !== valueMin ) ?
15092  ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15093  0;
15094  _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15095  this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15096 
15097  if ( oRange === "min" && this.orientation === "horizontal" ) {
15098  this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15099  width: valPercent + "%"
15100  }, o.animate );
15101  }
15102  if ( oRange === "max" && this.orientation === "horizontal" ) {
15103  this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15104  width: ( 100 - valPercent ) + "%"
15105  }, o.animate );
15106  }
15107  if ( oRange === "min" && this.orientation === "vertical" ) {
15108  this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15109  height: valPercent + "%"
15110  }, o.animate );
15111  }
15112  if ( oRange === "max" && this.orientation === "vertical" ) {
15113  this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15114  height: ( 100 - valPercent ) + "%"
15115  }, o.animate );
15116  }
15117  }
15118  },
15119 
15120  _handleEvents: {
15121  keydown: function( event ) {
15122  var allowed, curVal, newVal, step,
15123  index = $( event.target ).data( "ui-slider-handle-index" );
15124 
15125  switch ( event.keyCode ) {
15126  case $.ui.keyCode.HOME:
15127  case $.ui.keyCode.END:
15128  case $.ui.keyCode.PAGE_UP:
15129  case $.ui.keyCode.PAGE_DOWN:
15130  case $.ui.keyCode.UP:
15131  case $.ui.keyCode.RIGHT:
15132  case $.ui.keyCode.DOWN:
15133  case $.ui.keyCode.LEFT:
15134  event.preventDefault();
15135  if ( !this._keySliding ) {
15136  this._keySliding = true;
15137  this._addClass( $( event.target ), null, "ui-state-active" );
15138  allowed = this._start( event, index );
15139  if ( allowed === false ) {
15140  return;
15141  }
15142  }
15143  break;
15144  }
15145 
15146  step = this.options.step;
15147  if ( this._hasMultipleValues() ) {
15148  curVal = newVal = this.values( index );
15149  } else {
15150  curVal = newVal = this.value();
15151  }
15152 
15153  switch ( event.keyCode ) {
15154  case $.ui.keyCode.HOME:
15155  newVal = this._valueMin();
15156  break;
15157  case $.ui.keyCode.END:
15158  newVal = this._valueMax();
15159  break;
15160  case $.ui.keyCode.PAGE_UP:
15161  newVal = this._trimAlignValue(
15162  curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15163  );
15164  break;
15165  case $.ui.keyCode.PAGE_DOWN:
15166  newVal = this._trimAlignValue(
15167  curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15168  break;
15169  case $.ui.keyCode.UP:
15170  case $.ui.keyCode.RIGHT:
15171  if ( curVal === this._valueMax() ) {
15172  return;
15173  }
15174  newVal = this._trimAlignValue( curVal + step );
15175  break;
15176  case $.ui.keyCode.DOWN:
15177  case $.ui.keyCode.LEFT:
15178  if ( curVal === this._valueMin() ) {
15179  return;
15180  }
15181  newVal = this._trimAlignValue( curVal - step );
15182  break;
15183  }
15184 
15185  this._slide( event, index, newVal );
15186  },
15187  keyup: function( event ) {
15188  var index = $( event.target ).data( "ui-slider-handle-index" );
15189 
15190  if ( this._keySliding ) {
15191  this._keySliding = false;
15192  this._stop( event, index );
15193  this._change( event, index );
15194  this._removeClass( $( event.target ), null, "ui-state-active" );
15195  }
15196  }
15197  }
15198 } );
15199 
15200 
15210 //>>label: Sortable
15211 //>>group: Interactions
15212 //>>description: Enables items in a list to be sorted using the mouse.
15213 //>>docs: http://api.jqueryui.com/sortable/
15214 //>>demos: http://jqueryui.com/sortable/
15215 //>>css.structure: ../../themes/base/sortable.css
15216 
15217 
15218 
15219 var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15220  version: "1.12.1",
15221  widgetEventPrefix: "sort",
15222  ready: false,
15223  options: {
15224  appendTo: "parent",
15225  axis: false,
15226  connectWith: false,
15227  containment: false,
15228  cursor: "auto",
15229  cursorAt: false,
15230  dropOnEmpty: true,
15231  forcePlaceholderSize: false,
15232  forceHelperSize: false,
15233  grid: false,
15234  handle: false,
15235  helper: "original",
15236  items: "> *",
15237  opacity: false,
15238  placeholder: false,
15239  revert: false,
15240  scroll: true,
15241  scrollSensitivity: 20,
15242  scrollSpeed: 20,
15243  scope: "default",
15244  tolerance: "intersect",
15245  zIndex: 1000,
15246 
15247  // Callbacks
15248  activate: null,
15249  beforeStop: null,
15250  change: null,
15251  deactivate: null,
15252  out: null,
15253  over: null,
15254  receive: null,
15255  remove: null,
15256  sort: null,
15257  start: null,
15258  stop: null,
15259  update: null
15260  },
15261 
15262  _isOverAxis: function( x, reference, size ) {
15263  return ( x >= reference ) && ( x < ( reference + size ) );
15264  },
15265 
15266  _isFloating: function( item ) {
15267  return ( /left|right/ ).test( item.css( "float" ) ) ||
15268  ( /inline|table-cell/ ).test( item.css( "display" ) );
15269  },
15270 
15271  _create: function() {
15272  this.containerCache = {};
15273  this._addClass( "ui-sortable" );
15274 
15275  //Get the items
15276  this.refresh();
15277 
15278  //Let's determine the parent's offset
15279  this.offset = this.element.offset();
15280 
15281  //Initialize mouse events for interaction
15282  this._mouseInit();
15283 
15284  this._setHandleClassName();
15285 
15286  //We're ready to go
15287  this.ready = true;
15288 
15289  },
15290 
15291  _setOption: function( key, value ) {
15292  this._super( key, value );
15293 
15294  if ( key === "handle" ) {
15295  this._setHandleClassName();
15296  }
15297  },
15298 
15299  _setHandleClassName: function() {
15300  var that = this;
15301  this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15302  $.each( this.items, function() {
15303  that._addClass(
15304  this.instance.options.handle ?
15305  this.item.find( this.instance.options.handle ) :
15306  this.item,
15307  "ui-sortable-handle"
15308  );
15309  } );
15310  },
15311 
15312  _destroy: function() {
15313  this._mouseDestroy();
15314 
15315  for ( var i = this.items.length - 1; i >= 0; i-- ) {
15316  this.items[ i ].item.removeData( this.widgetName + "-item" );
15317  }
15318 
15319  return this;
15320  },
15321 
15322  _mouseCapture: function( event, overrideHandle ) {
15323  var currentItem = null,
15324  validHandle = false,
15325  that = this;
15326 
15327  if ( this.reverting ) {
15328  return false;
15329  }
15330 
15331  if ( this.options.disabled || this.options.type === "static" ) {
15332  return false;
15333  }
15334 
15335  //We have to refresh the items data once first
15336  this._refreshItems( event );
15337 
15338  //Find out if the clicked node (or one of its parents) is a actual item in this.items
15339  $( event.target ).parents().each( function() {
15340  if ( $.data( this, that.widgetName + "-item" ) === that ) {
15341  currentItem = $( this );
15342  return false;
15343  }
15344  } );
15345  if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15346  currentItem = $( event.target );
15347  }
15348 
15349  if ( !currentItem ) {
15350  return false;
15351  }
15352  if ( this.options.handle && !overrideHandle ) {
15353  $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15354  if ( this === event.target ) {
15355  validHandle = true;
15356  }
15357  } );
15358  if ( !validHandle ) {
15359  return false;
15360  }
15361  }
15362 
15363  this.currentItem = currentItem;
15364  this._removeCurrentsFromItems();
15365  return true;
15366 
15367  },
15368 
15369  _mouseStart: function( event, overrideHandle, noActivation ) {
15370 
15371  var i, body,
15372  o = this.options;
15373 
15374  this.currentContainer = this;
15375 
15376  //We only need to call refreshPositions, because the refreshItems call has been moved to
15377  // mouseCapture
15378  this.refreshPositions();
15379 
15380  //Create and append the visible helper
15381  this.helper = this._createHelper( event );
15382 
15383  //Cache the helper size
15384  this._cacheHelperProportions();
15385 
15386  /*
15387  * - Position generation -
15388  * This block generates everything position related - it's the core of draggables.
15389  */
15390 
15391  //Cache the margins of the original element
15392  this._cacheMargins();
15393 
15394  //Get the next scrolling parent
15395  this.scrollParent = this.helper.scrollParent();
15396 
15397  //The element's absolute position on the page minus margins
15398  this.offset = this.currentItem.offset();
15399  this.offset = {
15400  top: this.offset.top - this.margins.top,
15401  left: this.offset.left - this.margins.left
15402  };
15403 
15404  $.extend( this.offset, {
15405  click: { //Where the click happened, relative to the element
15406  left: event.pageX - this.offset.left,
15407  top: event.pageY - this.offset.top
15408  },
15409  parent: this._getParentOffset(),
15410 
15411  // This is a relative to absolute position minus the actual position calculation -
15412  // only used for relative positioned helper
15413  relative: this._getRelativeOffset()
15414  } );
15415 
15416  // Only after we got the offset, we can change the helper's position to absolute
15417  // TODO: Still need to figure out a way to make relative sorting possible
15418  this.helper.css( "position", "absolute" );
15419  this.cssPosition = this.helper.css( "position" );
15420 
15421  //Generate the original position
15422  this.originalPosition = this._generatePosition( event );
15423  this.originalPageX = event.pageX;
15424  this.originalPageY = event.pageY;
15425 
15426  //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15427  ( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
15428 
15429  //Cache the former DOM position
15430  this.domPosition = {
15431  prev: this.currentItem.prev()[ 0 ],
15432  parent: this.currentItem.parent()[ 0 ]
15433  };
15434 
15435  // If the helper is not the original, hide the original so it's not playing any role during
15436  // the drag, won't cause anything bad this way
15437  if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15438  this.currentItem.hide();
15439  }
15440 
15441  //Create the placeholder
15442  this._createPlaceholder();
15443 
15444  //Set a containment if given in the options
15445  if ( o.containment ) {
15446  this._setContainment();
15447  }
15448 
15449  if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15450  body = this.document.find( "body" );
15451 
15452  // Support: IE
15453  this.storedCursor = body.css( "cursor" );
15454  body.css( "cursor", o.cursor );
15455 
15456  this.storedStylesheet =
15457  $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15458  }
15459 
15460  if ( o.opacity ) { // opacity option
15461  if ( this.helper.css( "opacity" ) ) {
15462  this._storedOpacity = this.helper.css( "opacity" );
15463  }
15464  this.helper.css( "opacity", o.opacity );
15465  }
15466 
15467  if ( o.zIndex ) { // zIndex option
15468  if ( this.helper.css( "zIndex" ) ) {
15469  this._storedZIndex = this.helper.css( "zIndex" );
15470  }
15471  this.helper.css( "zIndex", o.zIndex );
15472  }
15473 
15474  //Prepare scrolling
15475  if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15476  this.scrollParent[ 0 ].tagName !== "HTML" ) {
15477  this.overflowOffset = this.scrollParent.offset();
15478  }
15479 
15480  //Call callbacks
15481  this._trigger( "start", event, this._uiHash() );
15482 
15483  //Recache the helper size
15484  if ( !this._preserveHelperProportions ) {
15485  this._cacheHelperProportions();
15486  }
15487 
15488  //Post "activate" events to possible containers
15489  if ( !noActivation ) {
15490  for ( i = this.containers.length - 1; i >= 0; i-- ) {
15491  this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15492  }
15493  }
15494 
15495  //Prepare possible droppables
15496  if ( $.ui.ddmanager ) {
15497  $.ui.ddmanager.current = this;
15498  }
15499 
15500  if ( $.ui.ddmanager && !o.dropBehaviour ) {
15501  $.ui.ddmanager.prepareOffsets( this, event );
15502  }
15503 
15504  this.dragging = true;
15505 
15506  this._addClass( this.helper, "ui-sortable-helper" );
15507 
15508  // Execute the drag once - this causes the helper not to be visiblebefore getting its
15509  // correct position
15510  this._mouseDrag( event );
15511  return true;
15512 
15513  },
15514 
15515  _mouseDrag: function( event ) {
15516  var i, item, itemElement, intersection,
15517  o = this.options,
15518  scrolled = false;
15519 
15520  //Compute the helpers position
15521  this.position = this._generatePosition( event );
15522  this.positionAbs = this._convertPositionTo( "absolute" );
15523 
15524  if ( !this.lastPositionAbs ) {
15525  this.lastPositionAbs = this.positionAbs;
15526  }
15527 
15528  //Do scrolling
15529  if ( this.options.scroll ) {
15530  if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15531  this.scrollParent[ 0 ].tagName !== "HTML" ) {
15532 
15533  if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15534  event.pageY < o.scrollSensitivity ) {
15535  this.scrollParent[ 0 ].scrollTop =
15536  scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15537  } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15538  this.scrollParent[ 0 ].scrollTop =
15539  scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15540  }
15541 
15542  if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15543  event.pageX < o.scrollSensitivity ) {
15544  this.scrollParent[ 0 ].scrollLeft = scrolled =
15545  this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15546  } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15547  this.scrollParent[ 0 ].scrollLeft = scrolled =
15548  this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15549  }
15550 
15551  } else {
15552 
15553  if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15554  scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15555  } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15556  o.scrollSensitivity ) {
15557  scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15558  }
15559 
15560  if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15561  scrolled = this.document.scrollLeft(
15562  this.document.scrollLeft() - o.scrollSpeed
15563  );
15564  } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15565  o.scrollSensitivity ) {
15566  scrolled = this.document.scrollLeft(
15567  this.document.scrollLeft() + o.scrollSpeed
15568  );
15569  }
15570 
15571  }
15572 
15573  if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
15574  $.ui.ddmanager.prepareOffsets( this, event );
15575  }
15576  }
15577 
15578  //Regenerate the absolute position used for position checks
15579  this.positionAbs = this._convertPositionTo( "absolute" );
15580 
15581  //Set the helper position
15582  if ( !this.options.axis || this.options.axis !== "y" ) {
15583  this.helper[ 0 ].style.left = this.position.left + "px";
15584  }
15585  if ( !this.options.axis || this.options.axis !== "x" ) {
15586  this.helper[ 0 ].style.top = this.position.top + "px";
15587  }
15588 
15589  //Rearrange
15590  for ( i = this.items.length - 1; i >= 0; i-- ) {
15591 
15592  //Cache variables and intersection, continue if no intersection
15593  item = this.items[ i ];
15594  itemElement = item.item[ 0 ];
15595  intersection = this._intersectsWithPointer( item );
15596  if ( !intersection ) {
15597  continue;
15598  }
15599 
15600  // Only put the placeholder inside the current Container, skip all
15601  // items from other containers. This works because when moving
15602  // an item from one container to another the
15603  // currentContainer is switched before the placeholder is moved.
15604  //
15605  // Without this, moving items in "sub-sortables" can cause
15606  // the placeholder to jitter between the outer and inner container.
15607  if ( item.instance !== this.currentContainer ) {
15608  continue;
15609  }
15610 
15611  // Cannot intersect with itself
15612  // no useless actions that have been done before
15613  // no action if the item moved is the parent of the item checked
15614  if ( itemElement !== this.currentItem[ 0 ] &&
15615  this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement &&
15616  !$.contains( this.placeholder[ 0 ], itemElement ) &&
15617  ( this.options.type === "semi-dynamic" ?
15618  !$.contains( this.element[ 0 ], itemElement ) :
15619  true
15620  )
15621  ) {
15622 
15623  this.direction = intersection === 1 ? "down" : "up";
15624 
15625  if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) {
15626  this._rearrange( event, item );
15627  } else {
15628  break;
15629  }
15630 
15631  this._trigger( "change", event, this._uiHash() );
15632  break;
15633  }
15634  }
15635 
15636  //Post events to containers
15637  this._contactContainers( event );
15638 
15639  //Interconnect with droppables
15640  if ( $.ui.ddmanager ) {
15641  $.ui.ddmanager.drag( this, event );
15642  }
15643 
15644  //Call callbacks
15645  this._trigger( "sort", event, this._uiHash() );
15646 
15647  this.lastPositionAbs = this.positionAbs;
15648  return false;
15649 
15650  },
15651 
15652  _mouseStop: function( event, noPropagation ) {
15653 
15654  if ( !event ) {
15655  return;
15656  }
15657 
15658  //If we are using droppables, inform the manager about the drop
15659  if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15660  $.ui.ddmanager.drop( this, event );
15661  }
15662 
15663  if ( this.options.revert ) {
15664  var that = this,
15665  cur = this.placeholder.offset(),
15666  axis = this.options.axis,
15667  animation = {};
15668 
15669  if ( !axis || axis === "x" ) {
15670  animation.left = cur.left - this.offset.parent.left - this.margins.left +
15671  ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15672  0 :
15673  this.offsetParent[ 0 ].scrollLeft
15674  );
15675  }
15676  if ( !axis || axis === "y" ) {
15677  animation.top = cur.top - this.offset.parent.top - this.margins.top +
15678  ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15679  0 :
15680  this.offsetParent[ 0 ].scrollTop
15681  );
15682  }
15683  this.reverting = true;
15684  $( this.helper ).animate(
15685  animation,
15686  parseInt( this.options.revert, 10 ) || 500,
15687  function() {
15688  that._clear( event );
15689  }
15690  );
15691  } else {
15692  this._clear( event, noPropagation );
15693  }
15694 
15695  return false;
15696 
15697  },
15698 
15699  cancel: function() {
15700 
15701  if ( this.dragging ) {
15702 
15703  this._mouseUp( new $.Event( "mouseup", { target: null } ) );
15704 
15705  if ( this.options.helper === "original" ) {
15706  this.currentItem.css( this._storedCSS );
15707  this._removeClass( this.currentItem, "ui-sortable-helper" );
15708  } else {
15709  this.currentItem.show();
15710  }
15711 
15712  //Post deactivating events to containers
15713  for ( var i = this.containers.length - 1; i >= 0; i-- ) {
15714  this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
15715  if ( this.containers[ i ].containerCache.over ) {
15716  this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
15717  this.containers[ i ].containerCache.over = 0;
15718  }
15719  }
15720 
15721  }
15722 
15723  if ( this.placeholder ) {
15724 
15725  //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
15726  // it unbinds ALL events from the original node!
15727  if ( this.placeholder[ 0 ].parentNode ) {
15728  this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
15729  }
15730  if ( this.options.helper !== "original" && this.helper &&
15731  this.helper[ 0 ].parentNode ) {
15732  this.helper.remove();
15733  }
15734 
15735  $.extend( this, {
15736  helper: null,
15737  dragging: false,
15738  reverting: false,
15739  _noFinalSort: null
15740  } );
15741 
15742  if ( this.domPosition.prev ) {
15743  $( this.domPosition.prev ).after( this.currentItem );
15744  } else {
15745  $( this.domPosition.parent ).prepend( this.currentItem );
15746  }
15747  }
15748 
15749  return this;
15750 
15751  },
15752 
15753  serialize: function( o ) {
15754 
15755  var items = this._getItemsAsjQuery( o && o.connected ),
15756  str = [];
15757  o = o || {};
15758 
15759  $( items ).each( function() {
15760  var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
15761  .match( o.expression || ( /(.+)[\-=_](.+)/ ) );
15762  if ( res ) {
15763  str.push(
15764  ( o.key || res[ 1 ] + "[]" ) +
15765  "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
15766  }
15767  } );
15768 
15769  if ( !str.length && o.key ) {
15770  str.push( o.key + "=" );
15771  }
15772 
15773  return str.join( "&" );
15774 
15775  },
15776 
15777  toArray: function( o ) {
15778 
15779  var items = this._getItemsAsjQuery( o && o.connected ),
15780  ret = [];
15781 
15782  o = o || {};
15783 
15784  items.each( function() {
15785  ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
15786  } );
15787  return ret;
15788 
15789  },
15790 
15791  /* Be careful with the following core functions */
15792  _intersectsWith: function( item ) {
15793 
15794  var x1 = this.positionAbs.left,
15795  x2 = x1 + this.helperProportions.width,
15796  y1 = this.positionAbs.top,
15797  y2 = y1 + this.helperProportions.height,
15798  l = item.left,
15799  r = l + item.width,
15800  t = item.top,
15801  b = t + item.height,
15802  dyClick = this.offset.click.top,
15803  dxClick = this.offset.click.left,
15804  isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
15805  ( y1 + dyClick ) < b ),
15806  isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
15807  ( x1 + dxClick ) < r ),
15808  isOverElement = isOverElementHeight && isOverElementWidth;
15809 
15810  if ( this.options.tolerance === "pointer" ||
15811  this.options.forcePointerForContainers ||
15812  ( this.options.tolerance !== "pointer" &&
15813  this.helperProportions[ this.floating ? "width" : "height" ] >
15814  item[ this.floating ? "width" : "height" ] )
15815  ) {
15816  return isOverElement;
15817  } else {
15818 
15819  return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
15820  x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
15821  t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
15822  y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
15823 
15824  }
15825  },
15826 
15827  _intersectsWithPointer: function( item ) {
15828  var verticalDirection, horizontalDirection,
15829  isOverElementHeight = ( this.options.axis === "x" ) ||
15830  this._isOverAxis(
15831  this.positionAbs.top + this.offset.click.top, item.top, item.height ),
15832  isOverElementWidth = ( this.options.axis === "y" ) ||
15833  this._isOverAxis(
15834  this.positionAbs.left + this.offset.click.left, item.left, item.width ),
15835  isOverElement = isOverElementHeight && isOverElementWidth;
15836 
15837  if ( !isOverElement ) {
15838  return false;
15839  }
15840 
15841  verticalDirection = this._getDragVerticalDirection();
15842  horizontalDirection = this._getDragHorizontalDirection();
15843 
15844  return this.floating ?
15845  ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 )
15846  : ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
15847 
15848  },
15849 
15850  _intersectsWithSides: function( item ) {
15851 
15852  var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
15853  this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
15854  isOverRightHalf = this._isOverAxis( this.positionAbs.left +
15855  this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
15856  verticalDirection = this._getDragVerticalDirection(),
15857  horizontalDirection = this._getDragHorizontalDirection();
15858 
15859  if ( this.floating && horizontalDirection ) {
15860  return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
15861  ( horizontalDirection === "left" && !isOverRightHalf ) );
15862  } else {
15863  return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
15864  ( verticalDirection === "up" && !isOverBottomHalf ) );
15865  }
15866 
15867  },
15868 
15869  _getDragVerticalDirection: function() {
15870  var delta = this.positionAbs.top - this.lastPositionAbs.top;
15871  return delta !== 0 && ( delta > 0 ? "down" : "up" );
15872  },
15873 
15874  _getDragHorizontalDirection: function() {
15875  var delta = this.positionAbs.left - this.lastPositionAbs.left;
15876  return delta !== 0 && ( delta > 0 ? "right" : "left" );
15877  },
15878 
15879  refresh: function( event ) {
15880  this._refreshItems( event );
15881  this._setHandleClassName();
15882  this.refreshPositions();
15883  return this;
15884  },
15885 
15886  _connectWith: function() {
15887  var options = this.options;
15888  return options.connectWith.constructor === String ?
15889  [ options.connectWith ] :
15890  options.connectWith;
15891  },
15892 
15893  _getItemsAsjQuery: function( connected ) {
15894 
15895  var i, j, cur, inst,
15896  items = [],
15897  queries = [],
15898  connectWith = this._connectWith();
15899 
15900  if ( connectWith && connected ) {
15901  for ( i = connectWith.length - 1; i >= 0; i-- ) {
15902  cur = $( connectWith[ i ], this.document[ 0 ] );
15903  for ( j = cur.length - 1; j >= 0; j-- ) {
15904  inst = $.data( cur[ j ], this.widgetFullName );
15905  if ( inst && inst !== this && !inst.options.disabled ) {
15906  queries.push( [ $.isFunction( inst.options.items ) ?
15907  inst.options.items.call( inst.element ) :
15908  $( inst.options.items, inst.element )
15909  .not( ".ui-sortable-helper" )
15910  .not( ".ui-sortable-placeholder" ), inst ] );
15911  }
15912  }
15913  }
15914  }
15915 
15916  queries.push( [ $.isFunction( this.options.items ) ?
15917  this.options.items
15918  .call( this.element, null, { options: this.options, item: this.currentItem } ) :
15919  $( this.options.items, this.element )
15920  .not( ".ui-sortable-helper" )
15921  .not( ".ui-sortable-placeholder" ), this ] );
15922 
15923  function addItems() {
15924  items.push( this );
15925  }
15926  for ( i = queries.length - 1; i >= 0; i-- ) {
15927  queries[ i ][ 0 ].each( addItems );
15928  }
15929 
15930  return $( items );
15931 
15932  },
15933 
15934  _removeCurrentsFromItems: function() {
15935 
15936  var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
15937 
15938  this.items = $.grep( this.items, function( item ) {
15939  for ( var j = 0; j < list.length; j++ ) {
15940  if ( list[ j ] === item.item[ 0 ] ) {
15941  return false;
15942  }
15943  }
15944  return true;
15945  } );
15946 
15947  },
15948 
15949  _refreshItems: function( event ) {
15950 
15951  this.items = [];
15952  this.containers = [ this ];
15953 
15954  var i, j, cur, inst, targetData, _queries, item, queriesLength,
15955  items = this.items,
15956  queries = [ [ $.isFunction( this.options.items ) ?
15957  this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
15958  $( this.options.items, this.element ), this ] ],
15959  connectWith = this._connectWith();
15960 
15961  //Shouldn't be run the first time through due to massive slow-down
15962  if ( connectWith && this.ready ) {
15963  for ( i = connectWith.length - 1; i >= 0; i-- ) {
15964  cur = $( connectWith[ i ], this.document[ 0 ] );
15965  for ( j = cur.length - 1; j >= 0; j-- ) {
15966  inst = $.data( cur[ j ], this.widgetFullName );
15967  if ( inst && inst !== this && !inst.options.disabled ) {
15968  queries.push( [ $.isFunction( inst.options.items ) ?
15969  inst.options.items
15970  .call( inst.element[ 0 ], event, { item: this.currentItem } ) :
15971  $( inst.options.items, inst.element ), inst ] );
15972  this.containers.push( inst );
15973  }
15974  }
15975  }
15976  }
15977 
15978  for ( i = queries.length - 1; i >= 0; i-- ) {
15979  targetData = queries[ i ][ 1 ];
15980  _queries = queries[ i ][ 0 ];
15981 
15982  for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
15983  item = $( _queries[ j ] );
15984 
15985  // Data for target checking (mouse manager)
15986  item.data( this.widgetName + "-item", targetData );
15987 
15988  items.push( {
15989  item: item,
15990  instance: targetData,
15991  width: 0, height: 0,
15992  left: 0, top: 0
15993  } );
15994  }
15995  }
15996 
15997  },
15998 
15999  refreshPositions: function( fast ) {
16000 
16001  // Determine whether items are being displayed horizontally
16002  this.floating = this.items.length ?
16003  this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16004  false;
16005 
16006  //This has to be redone because due to the item being moved out/into the offsetParent,
16007  // the offsetParent's position will change
16008  if ( this.offsetParent && this.helper ) {
16009  this.offset.parent = this._getParentOffset();
16010  }
16011 
16012  var i, item, t, p;
16013 
16014  for ( i = this.items.length - 1; i >= 0; i-- ) {
16015  item = this.items[ i ];
16016 
16017  //We ignore calculating positions of all connected containers when we're not over them
16018  if ( item.instance !== this.currentContainer && this.currentContainer &&
16019  item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16020  continue;
16021  }
16022 
16023  t = this.options.toleranceElement ?
16024  $( this.options.toleranceElement, item.item ) :
16025  item.item;
16026 
16027  if ( !fast ) {
16028  item.width = t.outerWidth();
16029  item.height = t.outerHeight();
16030  }
16031 
16032  p = t.offset();
16033  item.left = p.left;
16034  item.top = p.top;
16035  }
16036 
16037  if ( this.options.custom && this.options.custom.refreshContainers ) {
16038  this.options.custom.refreshContainers.call( this );
16039  } else {
16040  for ( i = this.containers.length - 1; i >= 0; i-- ) {
16041  p = this.containers[ i ].element.offset();
16042  this.containers[ i ].containerCache.left = p.left;
16043  this.containers[ i ].containerCache.top = p.top;
16044  this.containers[ i ].containerCache.width =
16045  this.containers[ i ].element.outerWidth();
16046  this.containers[ i ].containerCache.height =
16047  this.containers[ i ].element.outerHeight();
16048  }
16049  }
16050 
16051  return this;
16052  },
16053 
16054  _createPlaceholder: function( that ) {
16055  that = that || this;
16056  var className,
16057  o = that.options;
16058 
16059  if ( !o.placeholder || o.placeholder.constructor === String ) {
16060  className = o.placeholder;
16061  o.placeholder = {
16062  element: function() {
16063 
16064  var nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),
16065  element = $( "<" + nodeName + ">", that.document[ 0 ] );
16066 
16067  that._addClass( element, "ui-sortable-placeholder",
16068  className || that.currentItem[ 0 ].className )
16069  ._removeClass( element, "ui-sortable-helper" );
16070 
16071  if ( nodeName === "tbody" ) {
16072  that._createTrPlaceholder(
16073  that.currentItem.find( "tr" ).eq( 0 ),
16074  $( "<tr>", that.document[ 0 ] ).appendTo( element )
16075  );
16076  } else if ( nodeName === "tr" ) {
16077  that._createTrPlaceholder( that.currentItem, element );
16078  } else if ( nodeName === "img" ) {
16079  element.attr( "src", that.currentItem.attr( "src" ) );
16080  }
16081 
16082  if ( !className ) {
16083  element.css( "visibility", "hidden" );
16084  }
16085 
16086  return element;
16087  },
16088  update: function( container, p ) {
16089 
16090  // 1. If a className is set as 'placeholder option, we don't force sizes -
16091  // the class is responsible for that
16092  // 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16093  // class name is specified
16094  if ( className && !o.forcePlaceholderSize ) {
16095  return;
16096  }
16097 
16098  //If the element doesn't have a actual height by itself (without styles coming
16099  // from a stylesheet), it receives the inline height from the dragged item
16100  if ( !p.height() ) {
16101  p.height(
16102  that.currentItem.innerHeight() -
16103  parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16104  parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16105  }
16106  if ( !p.width() ) {
16107  p.width(
16108  that.currentItem.innerWidth() -
16109  parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16110  parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16111  }
16112  }
16113  };
16114  }
16115 
16116  //Create the placeholder
16117  that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16118 
16119  //Append it after the actual current item
16120  that.currentItem.after( that.placeholder );
16121 
16122  //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16123  o.placeholder.update( that, that.placeholder );
16124 
16125  },
16126 
16127  _createTrPlaceholder: function( sourceTr, targetTr ) {
16128  var that = this;
16129 
16130  sourceTr.children().each( function() {
16131  $( "<td>&#160;</td>", that.document[ 0 ] )
16132  .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16133  .appendTo( targetTr );
16134  } );
16135  },
16136 
16137  _contactContainers: function( event ) {
16138  var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16139  floating, axis,
16140  innermostContainer = null,
16141  innermostIndex = null;
16142 
16143  // Get innermost container that intersects with item
16144  for ( i = this.containers.length - 1; i >= 0; i-- ) {
16145 
16146  // Never consider a container that's located within the item itself
16147  if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16148  continue;
16149  }
16150 
16151  if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16152 
16153  // If we've already found a container and it's more "inner" than this, then continue
16154  if ( innermostContainer &&
16155  $.contains(
16156  this.containers[ i ].element[ 0 ],
16157  innermostContainer.element[ 0 ] ) ) {
16158  continue;
16159  }
16160 
16161  innermostContainer = this.containers[ i ];
16162  innermostIndex = i;
16163 
16164  } else {
16165 
16166  // container doesn't intersect. trigger "out" event if necessary
16167  if ( this.containers[ i ].containerCache.over ) {
16168  this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16169  this.containers[ i ].containerCache.over = 0;
16170  }
16171  }
16172 
16173  }
16174 
16175  // If no intersecting containers found, return
16176  if ( !innermostContainer ) {
16177  return;
16178  }
16179 
16180  // Move the item into the container if it's not there already
16181  if ( this.containers.length === 1 ) {
16182  if ( !this.containers[ innermostIndex ].containerCache.over ) {
16183  this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16184  this.containers[ innermostIndex ].containerCache.over = 1;
16185  }
16186  } else {
16187 
16188  // When entering a new container, we will find the item with the least distance and
16189  // append our item near it
16190  dist = 10000;
16191  itemWithLeastDistance = null;
16192  floating = innermostContainer.floating || this._isFloating( this.currentItem );
16193  posProperty = floating ? "left" : "top";
16194  sizeProperty = floating ? "width" : "height";
16195  axis = floating ? "pageX" : "pageY";
16196 
16197  for ( j = this.items.length - 1; j >= 0; j-- ) {
16198  if ( !$.contains(
16199  this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16200  ) {
16201  continue;
16202  }
16203  if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16204  continue;
16205  }
16206 
16207  cur = this.items[ j ].item.offset()[ posProperty ];
16208  nearBottom = false;
16209  if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16210  nearBottom = true;
16211  }
16212 
16213  if ( Math.abs( event[ axis ] - cur ) < dist ) {
16214  dist = Math.abs( event[ axis ] - cur );
16215  itemWithLeastDistance = this.items[ j ];
16216  this.direction = nearBottom ? "up" : "down";
16217  }
16218  }
16219 
16220  //Check if dropOnEmpty is enabled
16221  if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16222  return;
16223  }
16224 
16225  if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16226  if ( !this.currentContainer.containerCache.over ) {
16227  this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16228  this.currentContainer.containerCache.over = 1;
16229  }
16230  return;
16231  }
16232 
16233  itemWithLeastDistance ?
16234  this._rearrange( event, itemWithLeastDistance, null, true ) :
16235  this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16236  this._trigger( "change", event, this._uiHash() );
16237  this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16238  this.currentContainer = this.containers[ innermostIndex ];
16239 
16240  //Update the placeholder
16241  this.options.placeholder.update( this.currentContainer, this.placeholder );
16242 
16243  this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16244  this.containers[ innermostIndex ].containerCache.over = 1;
16245  }
16246 
16247  },
16248 
16249  _createHelper: function( event ) {
16250 
16251  var o = this.options,
16252  helper = $.isFunction( o.helper ) ?
16253  $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16254  ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16255 
16256  //Add the helper to the DOM if that didn't happen already
16257  if ( !helper.parents( "body" ).length ) {
16258  $( o.appendTo !== "parent" ?
16259  o.appendTo :
16260  this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );
16261  }
16262 
16263  if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16264  this._storedCSS = {
16265  width: this.currentItem[ 0 ].style.width,
16266  height: this.currentItem[ 0 ].style.height,
16267  position: this.currentItem.css( "position" ),
16268  top: this.currentItem.css( "top" ),
16269  left: this.currentItem.css( "left" )
16270  };
16271  }
16272 
16273  if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16274  helper.width( this.currentItem.width() );
16275  }
16276  if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16277  helper.height( this.currentItem.height() );
16278  }
16279 
16280  return helper;
16281 
16282  },
16283 
16284  _adjustOffsetFromHelper: function( obj ) {
16285  if ( typeof obj === "string" ) {
16286  obj = obj.split( " " );
16287  }
16288  if ( $.isArray( obj ) ) {
16289  obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16290  }
16291  if ( "left" in obj ) {
16292  this.offset.click.left = obj.left + this.margins.left;
16293  }
16294  if ( "right" in obj ) {
16295  this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16296  }
16297  if ( "top" in obj ) {
16298  this.offset.click.top = obj.top + this.margins.top;
16299  }
16300  if ( "bottom" in obj ) {
16301  this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16302  }
16303  },
16304 
16305  _getParentOffset: function() {
16306 
16307  //Get the offsetParent and cache its position
16308  this.offsetParent = this.helper.offsetParent();
16309  var po = this.offsetParent.offset();
16310 
16311  // This is a special case where we need to modify a offset calculated on start, since the
16312  // following happened:
16313  // 1. The position of the helper is absolute, so it's position is calculated based on the
16314  // next positioned parent
16315  // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16316  // the document, which means that the scroll is included in the initial calculation of the
16317  // offset of the parent, and never recalculated upon drag
16318  if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16319  $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16320  po.left += this.scrollParent.scrollLeft();
16321  po.top += this.scrollParent.scrollTop();
16322  }
16323 
16324  // This needs to be actually done for all browsers, since pageX/pageY includes this
16325  // information with an ugly IE fix
16326  if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
16327  ( this.offsetParent[ 0 ].tagName &&
16328  this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
16329  po = { top: 0, left: 0 };
16330  }
16331 
16332  return {
16333  top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16334  left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16335  };
16336 
16337  },
16338 
16339  _getRelativeOffset: function() {
16340 
16341  if ( this.cssPosition === "relative" ) {
16342  var p = this.currentItem.position();
16343  return {
16344  top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16345  this.scrollParent.scrollTop(),
16346  left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16347  this.scrollParent.scrollLeft()
16348  };
16349  } else {
16350  return { top: 0, left: 0 };
16351  }
16352 
16353  },
16354 
16355  _cacheMargins: function() {
16356  this.margins = {
16357  left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16358  top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16359  };
16360  },
16361 
16362  _cacheHelperProportions: function() {
16363  this.helperProportions = {
16364  width: this.helper.outerWidth(),
16365  height: this.helper.outerHeight()
16366  };
16367  },
16368 
16369  _setContainment: function() {
16370 
16371  var ce, co, over,
16372  o = this.options;
16373  if ( o.containment === "parent" ) {
16374  o.containment = this.helper[ 0 ].parentNode;
16375  }
16376  if ( o.containment === "document" || o.containment === "window" ) {
16377  this.containment = [
16378  0 - this.offset.relative.left - this.offset.parent.left,
16379  0 - this.offset.relative.top - this.offset.parent.top,
16380  o.containment === "document" ?
16381  this.document.width() :
16382  this.window.width() - this.helperProportions.width - this.margins.left,
16383  ( o.containment === "document" ?
16384  ( this.document.height() || document.body.parentNode.scrollHeight ) :
16385  this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16386  ) - this.helperProportions.height - this.margins.top
16387  ];
16388  }
16389 
16390  if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16391  ce = $( o.containment )[ 0 ];
16392  co = $( o.containment ).offset();
16393  over = ( $( ce ).css( "overflow" ) !== "hidden" );
16394 
16395  this.containment = [
16396  co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16397  ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16398  co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16399  ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16400  co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16401  ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16402  ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16403  this.helperProportions.width - this.margins.left,
16404  co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16405  ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16406  ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16407  this.helperProportions.height - this.margins.top
16408  ];
16409  }
16410 
16411  },
16412 
16413  _convertPositionTo: function( d, pos ) {
16414 
16415  if ( !pos ) {
16416  pos = this.position;
16417  }
16418  var mod = d === "absolute" ? 1 : -1,
16419  scroll = this.cssPosition === "absolute" &&
16420  !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16421  $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16422  this.offsetParent :
16423  this.scrollParent,
16424  scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16425 
16426  return {
16427  top: (
16428 
16429  // The absolute mouse position
16430  pos.top +
16431 
16432  // Only for relative positioned nodes: Relative offset from element to offset parent
16433  this.offset.relative.top * mod +
16434 
16435  // The offsetParent's offset without borders (offset + border)
16436  this.offset.parent.top * mod -
16437  ( ( this.cssPosition === "fixed" ?
16438  -this.scrollParent.scrollTop() :
16439  ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16440  ),
16441  left: (
16442 
16443  // The absolute mouse position
16444  pos.left +
16445 
16446  // Only for relative positioned nodes: Relative offset from element to offset parent
16447  this.offset.relative.left * mod +
16448 
16449  // The offsetParent's offset without borders (offset + border)
16450  this.offset.parent.left * mod -
16451  ( ( this.cssPosition === "fixed" ?
16452  -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16453  scroll.scrollLeft() ) * mod )
16454  )
16455  };
16456 
16457  },
16458 
16459  _generatePosition: function( event ) {
16460 
16461  var top, left,
16462  o = this.options,
16463  pageX = event.pageX,
16464  pageY = event.pageY,
16465  scroll = this.cssPosition === "absolute" &&
16466  !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16467  $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16468  this.offsetParent :
16469  this.scrollParent,
16470  scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16471 
16472  // This is another very weird special case that only happens for relative elements:
16473  // 1. If the css position is relative
16474  // 2. and the scroll parent is the document or similar to the offset parent
16475  // we have to refresh the relative offset during the scroll so there are no jumps
16476  if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16477  this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16478  this.offset.relative = this._getRelativeOffset();
16479  }
16480 
16481  /*
16482  * - Position constraining -
16483  * Constrain the position to a mix of grid, containment.
16484  */
16485 
16486  if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16487 
16488  if ( this.containment ) {
16489  if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16490  pageX = this.containment[ 0 ] + this.offset.click.left;
16491  }
16492  if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16493  pageY = this.containment[ 1 ] + this.offset.click.top;
16494  }
16495  if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16496  pageX = this.containment[ 2 ] + this.offset.click.left;
16497  }
16498  if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16499  pageY = this.containment[ 3 ] + this.offset.click.top;
16500  }
16501  }
16502 
16503  if ( o.grid ) {
16504  top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16505  o.grid[ 1 ] ) * o.grid[ 1 ];
16506  pageY = this.containment ?
16507  ( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16508  top - this.offset.click.top <= this.containment[ 3 ] ) ?
16509  top :
16510  ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16511  top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16512  top;
16513 
16514  left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16515  o.grid[ 0 ] ) * o.grid[ 0 ];
16516  pageX = this.containment ?
16517  ( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16518  left - this.offset.click.left <= this.containment[ 2 ] ) ?
16519  left :
16520  ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16521  left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16522  left;
16523  }
16524 
16525  }
16526 
16527  return {
16528  top: (
16529 
16530  // The absolute mouse position
16531  pageY -
16532 
16533  // Click offset (relative to the element)
16534  this.offset.click.top -
16535 
16536  // Only for relative positioned nodes: Relative offset from element to offset parent
16537  this.offset.relative.top -
16538 
16539  // The offsetParent's offset without borders (offset + border)
16540  this.offset.parent.top +
16541  ( ( this.cssPosition === "fixed" ?
16542  -this.scrollParent.scrollTop() :
16543  ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16544  ),
16545  left: (
16546 
16547  // The absolute mouse position
16548  pageX -
16549 
16550  // Click offset (relative to the element)
16551  this.offset.click.left -
16552 
16553  // Only for relative positioned nodes: Relative offset from element to offset parent
16554  this.offset.relative.left -
16555 
16556  // The offsetParent's offset without borders (offset + border)
16557  this.offset.parent.left +
16558  ( ( this.cssPosition === "fixed" ?
16559  -this.scrollParent.scrollLeft() :
16560  scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16561  )
16562  };
16563 
16564  },
16565 
16566  _rearrange: function( event, i, a, hardRefresh ) {
16567 
16568  a ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :
16569  i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16570  ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16571 
16572  //Various things done here to improve the performance:
16573  // 1. we create a setTimeout, that calls refreshPositions
16574  // 2. on the instance, we have a counter variable, that get's higher after every append
16575  // 3. on the local scope, we copy the counter variable, and check in the timeout,
16576  // if it's still the same
16577  // 4. this lets only the last addition to the timeout stack through
16578  this.counter = this.counter ? ++this.counter : 1;
16579  var counter = this.counter;
16580 
16581  this._delay( function() {
16582  if ( counter === this.counter ) {
16583 
16584  //Precompute after each DOM insertion, NOT on mousemove
16585  this.refreshPositions( !hardRefresh );
16586  }
16587  } );
16588 
16589  },
16590 
16591  _clear: function( event, noPropagation ) {
16592 
16593  this.reverting = false;
16594 
16595  // We delay all events that have to be triggered to after the point where the placeholder
16596  // has been removed and everything else normalized again
16597  var i,
16598  delayedTriggers = [];
16599 
16600  // We first have to update the dom position of the actual currentItem
16601  // Note: don't do it if the current item is already removed (by a user), or it gets
16602  // reappended (see #4088)
16603  if ( !this._noFinalSort && this.currentItem.parent().length ) {
16604  this.placeholder.before( this.currentItem );
16605  }
16606  this._noFinalSort = null;
16607 
16608  if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16609  for ( i in this._storedCSS ) {
16610  if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16611  this._storedCSS[ i ] = "";
16612  }
16613  }
16614  this.currentItem.css( this._storedCSS );
16615  this._removeClass( this.currentItem, "ui-sortable-helper" );
16616  } else {
16617  this.currentItem.show();
16618  }
16619 
16620  if ( this.fromOutside && !noPropagation ) {
16621  delayedTriggers.push( function( event ) {
16622  this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16623  } );
16624  }
16625  if ( ( this.fromOutside ||
16626  this.domPosition.prev !==
16627  this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16628  this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16629 
16630  // Trigger update callback if the DOM position has changed
16631  delayedTriggers.push( function( event ) {
16632  this._trigger( "update", event, this._uiHash() );
16633  } );
16634  }
16635 
16636  // Check if the items Container has Changed and trigger appropriate
16637  // events.
16638  if ( this !== this.currentContainer ) {
16639  if ( !noPropagation ) {
16640  delayedTriggers.push( function( event ) {
16641  this._trigger( "remove", event, this._uiHash() );
16642  } );
16643  delayedTriggers.push( ( function( c ) {
16644  return function( event ) {
16645  c._trigger( "receive", event, this._uiHash( this ) );
16646  };
16647  } ).call( this, this.currentContainer ) );
16648  delayedTriggers.push( ( function( c ) {
16649  return function( event ) {
16650  c._trigger( "update", event, this._uiHash( this ) );
16651  };
16652  } ).call( this, this.currentContainer ) );
16653  }
16654  }
16655 
16656  //Post events to containers
16657  function delayEvent( type, instance, container ) {
16658  return function( event ) {
16659  container._trigger( type, event, instance._uiHash( instance ) );
16660  };
16661  }
16662  for ( i = this.containers.length - 1; i >= 0; i-- ) {
16663  if ( !noPropagation ) {
16664  delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
16665  }
16666  if ( this.containers[ i ].containerCache.over ) {
16667  delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
16668  this.containers[ i ].containerCache.over = 0;
16669  }
16670  }
16671 
16672  //Do what was originally in plugins
16673  if ( this.storedCursor ) {
16674  this.document.find( "body" ).css( "cursor", this.storedCursor );
16675  this.storedStylesheet.remove();
16676  }
16677  if ( this._storedOpacity ) {
16678  this.helper.css( "opacity", this._storedOpacity );
16679  }
16680  if ( this._storedZIndex ) {
16681  this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
16682  }
16683 
16684  this.dragging = false;
16685 
16686  if ( !noPropagation ) {
16687  this._trigger( "beforeStop", event, this._uiHash() );
16688  }
16689 
16690  //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16691  // it unbinds ALL events from the original node!
16692  this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16693 
16694  if ( !this.cancelHelperRemoval ) {
16695  if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
16696  this.helper.remove();
16697  }
16698  this.helper = null;
16699  }
16700 
16701  if ( !noPropagation ) {
16702  for ( i = 0; i < delayedTriggers.length; i++ ) {
16703 
16704  // Trigger all delayed events
16705  delayedTriggers[ i ].call( this, event );
16706  }
16707  this._trigger( "stop", event, this._uiHash() );
16708  }
16709 
16710  this.fromOutside = false;
16711  return !this.cancelHelperRemoval;
16712 
16713  },
16714 
16715  _trigger: function() {
16716  if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
16717  this.cancel();
16718  }
16719  },
16720 
16721  _uiHash: function( _inst ) {
16722  var inst = _inst || this;
16723  return {
16724  helper: inst.helper,
16725  placeholder: inst.placeholder || $( [] ),
16726  position: inst.position,
16727  originalPosition: inst.originalPosition,
16728  offset: inst.positionAbs,
16729  item: inst.currentItem,
16730  sender: _inst ? _inst.element : null
16731  };
16732  }
16733 
16734 } );
16735 
16736 
16746 //>>label: Spinner
16747 //>>group: Widgets
16748 //>>description: Displays buttons to easily input numbers via the keyboard or mouse.
16749 //>>docs: http://api.jqueryui.com/spinner/
16750 //>>demos: http://jqueryui.com/spinner/
16751 //>>css.structure: ../../themes/base/core.css
16752 //>>css.structure: ../../themes/base/spinner.css
16753 //>>css.theme: ../../themes/base/theme.css
16754 
16755 
16756 
16757 function spinnerModifer( fn ) {
16758  return function() {
16759  var previous = this.element.val();
16760  fn.apply( this, arguments );
16761  this._refresh();
16762  if ( previous !== this.element.val() ) {
16763  this._trigger( "change" );
16764  }
16765  };
16766 }
16767 
16768 $.widget( "ui.spinner", {
16769  version: "1.12.1",
16770  defaultElement: "<input>",
16771  widgetEventPrefix: "spin",
16772  options: {
16773  classes: {
16774  "ui-spinner": "ui-corner-all",
16775  "ui-spinner-down": "ui-corner-br",
16776  "ui-spinner-up": "ui-corner-tr"
16777  },
16778  culture: null,
16779  icons: {
16780  down: "ui-icon-triangle-1-s",
16781  up: "ui-icon-triangle-1-n"
16782  },
16783  incremental: true,
16784  max: null,
16785  min: null,
16786  numberFormat: null,
16787  page: 10,
16788  step: 1,
16789 
16790  change: null,
16791  spin: null,
16792  start: null,
16793  stop: null
16794  },
16795 
16796  _create: function() {
16797 
16798  // handle string values that need to be parsed
16799  this._setOption( "max", this.options.max );
16800  this._setOption( "min", this.options.min );
16801  this._setOption( "step", this.options.step );
16802 
16803  // Only format if there is a value, prevents the field from being marked
16804  // as invalid in Firefox, see #9573.
16805  if ( this.value() !== "" ) {
16806 
16807  // Format the value, but don't constrain.
16808  this._value( this.element.val(), true );
16809  }
16810 
16811  this._draw();
16812  this._on( this._events );
16813  this._refresh();
16814 
16815  // Turning off autocomplete prevents the browser from remembering the
16816  // value when navigating through history, so we re-enable autocomplete
16817  // if the page is unloaded before the widget is destroyed. #7790
16818  this._on( this.window, {
16819  beforeunload: function() {
16820  this.element.removeAttr( "autocomplete" );
16821  }
16822  } );
16823  },
16824 
16825  _getCreateOptions: function() {
16826  var options = this._super();
16827  var element = this.element;
16828 
16829  $.each( [ "min", "max", "step" ], function( i, option ) {
16830  var value = element.attr( option );
16831  if ( value != null && value.length ) {
16832  options[ option ] = value;
16833  }
16834  } );
16835 
16836  return options;
16837  },
16838 
16839  _events: {
16840  keydown: function( event ) {
16841  if ( this._start( event ) && this._keydown( event ) ) {
16842  event.preventDefault();
16843  }
16844  },
16845  keyup: "_stop",
16846  focus: function() {
16847  this.previous = this.element.val();
16848  },
16849  blur: function( event ) {
16850  if ( this.cancelBlur ) {
16851  delete this.cancelBlur;
16852  return;
16853  }
16854 
16855  this._stop();
16856  this._refresh();
16857  if ( this.previous !== this.element.val() ) {
16858  this._trigger( "change", event );
16859  }
16860  },
16861  mousewheel: function( event, delta ) {
16862  if ( !delta ) {
16863  return;
16864  }
16865  if ( !this.spinning && !this._start( event ) ) {
16866  return false;
16867  }
16868 
16869  this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
16870  clearTimeout( this.mousewheelTimer );
16871  this.mousewheelTimer = this._delay( function() {
16872  if ( this.spinning ) {
16873  this._stop( event );
16874  }
16875  }, 100 );
16876  event.preventDefault();
16877  },
16878  "mousedown .ui-spinner-button": function( event ) {
16879  var previous;
16880 
16881  // We never want the buttons to have focus; whenever the user is
16882  // interacting with the spinner, the focus should be on the input.
16883  // If the input is focused then this.previous is properly set from
16884  // when the input first received focus. If the input is not focused
16885  // then we need to set this.previous based on the value before spinning.
16886  previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
16887  this.previous : this.element.val();
16888  function checkFocus() {
16889  var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
16890  if ( !isActive ) {
16891  this.element.trigger( "focus" );
16892  this.previous = previous;
16893 
16894  // support: IE
16895  // IE sets focus asynchronously, so we need to check if focus
16896  // moved off of the input because the user clicked on the button.
16897  this._delay( function() {
16898  this.previous = previous;
16899  } );
16900  }
16901  }
16902 
16903  // Ensure focus is on (or stays on) the text field
16904  event.preventDefault();
16905  checkFocus.call( this );
16906 
16907  // Support: IE
16908  // IE doesn't prevent moving focus even with event.preventDefault()
16909  // so we set a flag to know when we should ignore the blur event
16910  // and check (again) if focus moved off of the input.
16911  this.cancelBlur = true;
16912  this._delay( function() {
16913  delete this.cancelBlur;
16914  checkFocus.call( this );
16915  } );
16916 
16917  if ( this._start( event ) === false ) {
16918  return;
16919  }
16920 
16921  this._repeat( null, $( event.currentTarget )
16922  .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
16923  },
16924  "mouseup .ui-spinner-button": "_stop",
16925  "mouseenter .ui-spinner-button": function( event ) {
16926 
16927  // button will add ui-state-active if mouse was down while mouseleave and kept down
16928  if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
16929  return;
16930  }
16931 
16932  if ( this._start( event ) === false ) {
16933  return false;
16934  }
16935  this._repeat( null, $( event.currentTarget )
16936  .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
16937  },
16938 
16939  // TODO: do we really want to consider this a stop?
16940  // shouldn't we just stop the repeater and wait until mouseup before
16941  // we trigger the stop event?
16942  "mouseleave .ui-spinner-button": "_stop"
16943  },
16944 
16945  // Support mobile enhanced option and make backcompat more sane
16946  _enhance: function() {
16947  this.uiSpinner = this.element
16948  .attr( "autocomplete", "off" )
16949  .wrap( "<span>" )
16950  .parent()
16951 
16952  // Add buttons
16953  .append(
16954  "<a></a><a></a>"
16955  );
16956  },
16957 
16958  _draw: function() {
16959  this._enhance();
16960 
16961  this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
16962  this._addClass( "ui-spinner-input" );
16963 
16964  this.element.attr( "role", "spinbutton" );
16965 
16966  // Button bindings
16967  this.buttons = this.uiSpinner.children( "a" )
16968  .attr( "tabIndex", -1 )
16969  .attr( "aria-hidden", true )
16970  .button( {
16971  classes: {
16972  "ui-button": ""
16973  }
16974  } );
16975 
16976  // TODO: Right now button does not support classes this is already updated in button PR
16977  this._removeClass( this.buttons, "ui-corner-all" );
16978 
16979  this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
16980  this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
16981  this.buttons.first().button( {
16982  "icon": this.options.icons.up,
16983  "showLabel": false
16984  } );
16985  this.buttons.last().button( {
16986  "icon": this.options.icons.down,
16987  "showLabel": false
16988  } );
16989 
16990  // IE 6 doesn't understand height: 50% for the buttons
16991  // unless the wrapper has an explicit height
16992  if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
16993  this.uiSpinner.height() > 0 ) {
16994  this.uiSpinner.height( this.uiSpinner.height() );
16995  }
16996  },
16997 
16998  _keydown: function( event ) {
16999  var options = this.options,
17000  keyCode = $.ui.keyCode;
17001 
17002  switch ( event.keyCode ) {
17003  case keyCode.UP:
17004  this._repeat( null, 1, event );
17005  return true;
17006  case keyCode.DOWN:
17007  this._repeat( null, -1, event );
17008  return true;
17009  case keyCode.PAGE_UP:
17010  this._repeat( null, options.page, event );
17011  return true;
17012  case keyCode.PAGE_DOWN:
17013  this._repeat( null, -options.page, event );
17014  return true;
17015  }
17016 
17017  return false;
17018  },
17019 
17020  _start: function( event ) {
17021  if ( !this.spinning && this._trigger( "start", event ) === false ) {
17022  return false;
17023  }
17024 
17025  if ( !this.counter ) {
17026  this.counter = 1;
17027  }
17028  this.spinning = true;
17029  return true;
17030  },
17031 
17032  _repeat: function( i, steps, event ) {
17033  i = i || 500;
17034 
17035  clearTimeout( this.timer );
17036  this.timer = this._delay( function() {
17037  this._repeat( 40, steps, event );
17038  }, i );
17039 
17040  this._spin( steps * this.options.step, event );
17041  },
17042 
17043  _spin: function( step, event ) {
17044  var value = this.value() || 0;
17045 
17046  if ( !this.counter ) {
17047  this.counter = 1;
17048  }
17049 
17050  value = this._adjustValue( value + step * this._increment( this.counter ) );
17051 
17052  if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17053  this._value( value );
17054  this.counter++;
17055  }
17056  },
17057 
17058  _increment: function( i ) {
17059  var incremental = this.options.incremental;
17060 
17061  if ( incremental ) {
17062  return $.isFunction( incremental ) ?
17063  incremental( i ) :
17064  Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17065  }
17066 
17067  return 1;
17068  },
17069 
17070  _precision: function() {
17071  var precision = this._precisionOf( this.options.step );
17072  if ( this.options.min !== null ) {
17073  precision = Math.max( precision, this._precisionOf( this.options.min ) );
17074  }
17075  return precision;
17076  },
17077 
17078  _precisionOf: function( num ) {
17079  var str = num.toString(),
17080  decimal = str.indexOf( "." );
17081  return decimal === -1 ? 0 : str.length - decimal - 1;
17082  },
17083 
17084  _adjustValue: function( value ) {
17085  var base, aboveMin,
17086  options = this.options;
17087 
17088  // Make sure we're at a valid step
17089  // - find out where we are relative to the base (min or 0)
17090  base = options.min !== null ? options.min : 0;
17091  aboveMin = value - base;
17092 
17093  // - round to the nearest step
17094  aboveMin = Math.round( aboveMin / options.step ) * options.step;
17095 
17096  // - rounding is based on 0, so adjust back to our base
17097  value = base + aboveMin;
17098 
17099  // Fix precision from bad JS floating point math
17100  value = parseFloat( value.toFixed( this._precision() ) );
17101 
17102  // Clamp the value
17103  if ( options.max !== null && value > options.max ) {
17104  return options.max;
17105  }
17106  if ( options.min !== null && value < options.min ) {
17107  return options.min;
17108  }
17109 
17110  return value;
17111  },
17112 
17113  _stop: function( event ) {
17114  if ( !this.spinning ) {
17115  return;
17116  }
17117 
17118  clearTimeout( this.timer );
17119  clearTimeout( this.mousewheelTimer );
17120  this.counter = 0;
17121  this.spinning = false;
17122  this._trigger( "stop", event );
17123  },
17124 
17125  _setOption: function( key, value ) {
17126  var prevValue, first, last;
17127 
17128  if ( key === "culture" || key === "numberFormat" ) {
17129  prevValue = this._parse( this.element.val() );
17130  this.options[ key ] = value;
17131  this.element.val( this._format( prevValue ) );
17132  return;
17133  }
17134 
17135  if ( key === "max" || key === "min" || key === "step" ) {
17136  if ( typeof value === "string" ) {
17137  value = this._parse( value );
17138  }
17139  }
17140  if ( key === "icons" ) {
17141  first = this.buttons.first().find( ".ui-icon" );
17142  this._removeClass( first, null, this.options.icons.up );
17143  this._addClass( first, null, value.up );
17144  last = this.buttons.last().find( ".ui-icon" );
17145  this._removeClass( last, null, this.options.icons.down );
17146  this._addClass( last, null, value.down );
17147  }
17148 
17149  this._super( key, value );
17150  },
17151 
17152  _setOptionDisabled: function( value ) {
17153  this._super( value );
17154 
17155  this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17156  this.element.prop( "disabled", !!value );
17157  this.buttons.button( value ? "disable" : "enable" );
17158  },
17159 
17160  _setOptions: spinnerModifer( function( options ) {
17161  this._super( options );
17162  } ),
17163 
17164  _parse: function( val ) {
17165  if ( typeof val === "string" && val !== "" ) {
17166  val = window.Globalize && this.options.numberFormat ?
17167  Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17168  }
17169  return val === "" || isNaN( val ) ? null : val;
17170  },
17171 
17172  _format: function( value ) {
17173  if ( value === "" ) {
17174  return "";
17175  }
17176  return window.Globalize && this.options.numberFormat ?
17177  Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17178  value;
17179  },
17180 
17181  _refresh: function() {
17182  this.element.attr( {
17183  "aria-valuemin": this.options.min,
17184  "aria-valuemax": this.options.max,
17185 
17186  // TODO: what should we do with values that can't be parsed?
17187  "aria-valuenow": this._parse( this.element.val() )
17188  } );
17189  },
17190 
17191  isValid: function() {
17192  var value = this.value();
17193 
17194  // Null is invalid
17195  if ( value === null ) {
17196  return false;
17197  }
17198 
17199  // If value gets adjusted, it's invalid
17200  return value === this._adjustValue( value );
17201  },
17202 
17203  // Update the value without triggering change
17204  _value: function( value, allowAny ) {
17205  var parsed;
17206  if ( value !== "" ) {
17207  parsed = this._parse( value );
17208  if ( parsed !== null ) {
17209  if ( !allowAny ) {
17210  parsed = this._adjustValue( parsed );
17211  }
17212  value = this._format( parsed );
17213  }
17214  }
17215  this.element.val( value );
17216  this._refresh();
17217  },
17218 
17219  _destroy: function() {
17220  this.element
17221  .prop( "disabled", false )
17222  .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17223 
17224  this.uiSpinner.replaceWith( this.element );
17225  },
17226 
17227  stepUp: spinnerModifer( function( steps ) {
17228  this._stepUp( steps );
17229  } ),
17230  _stepUp: function( steps ) {
17231  if ( this._start() ) {
17232  this._spin( ( steps || 1 ) * this.options.step );
17233  this._stop();
17234  }
17235  },
17236 
17237  stepDown: spinnerModifer( function( steps ) {
17238  this._stepDown( steps );
17239  } ),
17240  _stepDown: function( steps ) {
17241  if ( this._start() ) {
17242  this._spin( ( steps || 1 ) * -this.options.step );
17243  this._stop();
17244  }
17245  },
17246 
17247  pageUp: spinnerModifer( function( pages ) {
17248  this._stepUp( ( pages || 1 ) * this.options.page );
17249  } ),
17250 
17251  pageDown: spinnerModifer( function( pages ) {
17252  this._stepDown( ( pages || 1 ) * this.options.page );
17253  } ),
17254 
17255  value: function( newVal ) {
17256  if ( !arguments.length ) {
17257  return this._parse( this.element.val() );
17258  }
17259  spinnerModifer( this._value ).call( this, newVal );
17260  },
17261 
17262  widget: function() {
17263  return this.uiSpinner;
17264  }
17265 } );
17266 
17267 // DEPRECATED
17268 // TODO: switch return back to widget declaration at top of file when this is removed
17269 if ( $.uiBackCompat !== false ) {
17270 
17271  // Backcompat for spinner html extension points
17272  $.widget( "ui.spinner", $.ui.spinner, {
17273  _enhance: function() {
17274  this.uiSpinner = this.element
17275  .attr( "autocomplete", "off" )
17276  .wrap( this._uiSpinnerHtml() )
17277  .parent()
17278 
17279  // Add buttons
17280  .append( this._buttonHtml() );
17281  },
17282  _uiSpinnerHtml: function() {
17283  return "<span>";
17284  },
17285 
17286  _buttonHtml: function() {
17287  return "<a></a><a></a>";
17288  }
17289  } );
17290 }
17291 
17292 var widgetsSpinner = $.ui.spinner;
17293 
17294 
17304 //>>label: Tabs
17305 //>>group: Widgets
17306 //>>description: Transforms a set of container elements into a tab structure.
17307 //>>docs: http://api.jqueryui.com/tabs/
17308 //>>demos: http://jqueryui.com/tabs/
17309 //>>css.structure: ../../themes/base/core.css
17310 //>>css.structure: ../../themes/base/tabs.css
17311 //>>css.theme: ../../themes/base/theme.css
17312 
17313 
17314 
17315 $.widget( "ui.tabs", {
17316  version: "1.12.1",
17317  delay: 300,
17318  options: {
17319  active: null,
17320  classes: {
17321  "ui-tabs": "ui-corner-all",
17322  "ui-tabs-nav": "ui-corner-all",
17323  "ui-tabs-panel": "ui-corner-bottom",
17324  "ui-tabs-tab": "ui-corner-top"
17325  },
17326  collapsible: false,
17327  event: "click",
17328  heightStyle: "content",
17329  hide: null,
17330  show: null,
17331 
17332  // Callbacks
17333  activate: null,
17334  beforeActivate: null,
17335  beforeLoad: null,
17336  load: null
17337  },
17338 
17339  _isLocal: ( function() {
17340  var rhash = /#.*$/;
17341 
17342  return function( anchor ) {
17343  var anchorUrl, locationUrl;
17344 
17345  anchorUrl = anchor.href.replace( rhash, "" );
17346  locationUrl = location.href.replace( rhash, "" );
17347 
17348  // Decoding may throw an error if the URL isn't UTF-8 (#9518)
17349  try {
17350  anchorUrl = decodeURIComponent( anchorUrl );
17351  } catch ( error ) {}
17352  try {
17353  locationUrl = decodeURIComponent( locationUrl );
17354  } catch ( error ) {}
17355 
17356  return anchor.hash.length > 1 && anchorUrl === locationUrl;
17357  };
17358  } )(),
17359 
17360  _create: function() {
17361  var that = this,
17362  options = this.options;
17363 
17364  this.running = false;
17365 
17366  this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17367  this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17368 
17369  this._processTabs();
17370  options.active = this._initialActive();
17371 
17372  // Take disabling tabs via class attribute from HTML
17373  // into account and update option properly.
17374  if ( $.isArray( options.disabled ) ) {
17375  options.disabled = $.unique( options.disabled.concat(
17376  $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17377  return that.tabs.index( li );
17378  } )
17379  ) ).sort();
17380  }
17381 
17382  // Check for length avoids error when initializing empty list
17383  if ( this.options.active !== false && this.anchors.length ) {
17384  this.active = this._findActive( options.active );
17385  } else {
17386  this.active = $();
17387  }
17388 
17389  this._refresh();
17390 
17391  if ( this.active.length ) {
17392  this.load( options.active );
17393  }
17394  },
17395 
17396  _initialActive: function() {
17397  var active = this.options.active,
17398  collapsible = this.options.collapsible,
17399  locationHash = location.hash.substring( 1 );
17400 
17401  if ( active === null ) {
17402 
17403  // check the fragment identifier in the URL
17404  if ( locationHash ) {
17405  this.tabs.each( function( i, tab ) {
17406  if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
17407  active = i;
17408  return false;
17409  }
17410  } );
17411  }
17412 
17413  // Check for a tab marked active via a class
17414  if ( active === null ) {
17415  active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17416  }
17417 
17418  // No active tab, set to false
17419  if ( active === null || active === -1 ) {
17420  active = this.tabs.length ? 0 : false;
17421  }
17422  }
17423 
17424  // Handle numbers: negative, out of range
17425  if ( active !== false ) {
17426  active = this.tabs.index( this.tabs.eq( active ) );
17427  if ( active === -1 ) {
17428  active = collapsible ? false : 0;
17429  }
17430  }
17431 
17432  // Don't allow collapsible: false and active: false
17433  if ( !collapsible && active === false && this.anchors.length ) {
17434  active = 0;
17435  }
17436 
17437  return active;
17438  },
17439 
17440  _getCreateEventData: function() {
17441  return {
17442  tab: this.active,
17443  panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17444  };
17445  },
17446 
17447  _tabKeydown: function( event ) {
17448  var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
17449  selectedIndex = this.tabs.index( focusedTab ),
17450  goingForward = true;
17451 
17452  if ( this._handlePageNav( event ) ) {
17453  return;
17454  }
17455 
17456  switch ( event.keyCode ) {
17457  case $.ui.keyCode.RIGHT:
17458  case $.ui.keyCode.DOWN:
17459  selectedIndex++;
17460  break;
17461  case $.ui.keyCode.UP:
17462  case $.ui.keyCode.LEFT:
17463  goingForward = false;
17464  selectedIndex--;
17465  break;
17466  case $.ui.keyCode.END:
17467  selectedIndex = this.anchors.length - 1;
17468  break;
17469  case $.ui.keyCode.HOME:
17470  selectedIndex = 0;
17471  break;
17472  case $.ui.keyCode.SPACE:
17473 
17474  // Activate only, no collapsing
17475  event.preventDefault();
17476  clearTimeout( this.activating );
17477  this._activate( selectedIndex );
17478  return;
17479  case $.ui.keyCode.ENTER:
17480 
17481  // Toggle (cancel delayed activation, allow collapsing)
17482  event.preventDefault();
17483  clearTimeout( this.activating );
17484 
17485  // Determine if we should collapse or activate
17486  this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17487  return;
17488  default:
17489  return;
17490  }
17491 
17492  // Focus the appropriate tab, based on which key was pressed
17493  event.preventDefault();
17494  clearTimeout( this.activating );
17495  selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17496 
17497  // Navigating with control/command key will prevent automatic activation
17498  if ( !event.ctrlKey && !event.metaKey ) {
17499 
17500  // Update aria-selected immediately so that AT think the tab is already selected.
17501  // Otherwise AT may confuse the user by stating that they need to activate the tab,
17502  // but the tab will already be activated by the time the announcement finishes.
17503  focusedTab.attr( "aria-selected", "false" );
17504  this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17505 
17506  this.activating = this._delay( function() {
17507  this.option( "active", selectedIndex );
17508  }, this.delay );
17509  }
17510  },
17511 
17512  _panelKeydown: function( event ) {
17513  if ( this._handlePageNav( event ) ) {
17514  return;
17515  }
17516 
17517  // Ctrl+up moves focus to the current tab
17518  if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17519  event.preventDefault();
17520  this.active.trigger( "focus" );
17521  }
17522  },
17523 
17524  // Alt+page up/down moves focus to the previous/next tab (and activates)
17525  _handlePageNav: function( event ) {
17526  if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17527  this._activate( this._focusNextTab( this.options.active - 1, false ) );
17528  return true;
17529  }
17530  if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17531  this._activate( this._focusNextTab( this.options.active + 1, true ) );
17532  return true;
17533  }
17534  },
17535 
17536  _findNextTab: function( index, goingForward ) {
17537  var lastTabIndex = this.tabs.length - 1;
17538 
17539  function constrain() {
17540  if ( index > lastTabIndex ) {
17541  index = 0;
17542  }
17543  if ( index < 0 ) {
17544  index = lastTabIndex;
17545  }
17546  return index;
17547  }
17548 
17549  while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17550  index = goingForward ? index + 1 : index - 1;
17551  }
17552 
17553  return index;
17554  },
17555 
17556  _focusNextTab: function( index, goingForward ) {
17557  index = this._findNextTab( index, goingForward );
17558  this.tabs.eq( index ).trigger( "focus" );
17559  return index;
17560  },
17561 
17562  _setOption: function( key, value ) {
17563  if ( key === "active" ) {
17564 
17565  // _activate() will handle invalid values and update this.options
17566  this._activate( value );
17567  return;
17568  }
17569 
17570  this._super( key, value );
17571 
17572  if ( key === "collapsible" ) {
17573  this._toggleClass( "ui-tabs-collapsible", null, value );
17574 
17575  // Setting collapsible: false while collapsed; open first panel
17576  if ( !value && this.options.active === false ) {
17577  this._activate( 0 );
17578  }
17579  }
17580 
17581  if ( key === "event" ) {
17582  this._setupEvents( value );
17583  }
17584 
17585  if ( key === "heightStyle" ) {
17586  this._setupHeightStyle( value );
17587  }
17588  },
17589 
17590  _sanitizeSelector: function( hash ) {
17591  return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
17592  },
17593 
17594  refresh: function() {
17595  var options = this.options,
17596  lis = this.tablist.children( ":has(a[href])" );
17597 
17598  // Get disabled tabs from class attribute from HTML
17599  // this will get converted to a boolean if needed in _refresh()
17600  options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17601  return lis.index( tab );
17602  } );
17603 
17604  this._processTabs();
17605 
17606  // Was collapsed or no tabs
17607  if ( options.active === false || !this.anchors.length ) {
17608  options.active = false;
17609  this.active = $();
17610 
17611  // was active, but active tab is gone
17612  } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17613 
17614  // all remaining tabs are disabled
17615  if ( this.tabs.length === options.disabled.length ) {
17616  options.active = false;
17617  this.active = $();
17618 
17619  // activate previous tab
17620  } else {
17621  this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17622  }
17623 
17624  // was active, active tab still exists
17625  } else {
17626 
17627  // make sure active index is correct
17628  options.active = this.tabs.index( this.active );
17629  }
17630 
17631  this._refresh();
17632  },
17633 
17634  _refresh: function() {
17635  this._setOptionDisabled( this.options.disabled );
17636  this._setupEvents( this.options.event );
17637  this._setupHeightStyle( this.options.heightStyle );
17638 
17639  this.tabs.not( this.active ).attr( {
17640  "aria-selected": "false",
17641  "aria-expanded": "false",
17642  tabIndex: -1
17643  } );
17644  this.panels.not( this._getPanelForTab( this.active ) )
17645  .hide()
17646  .attr( {
17647  "aria-hidden": "true"
17648  } );
17649 
17650  // Make sure one tab is in the tab order
17651  if ( !this.active.length ) {
17652  this.tabs.eq( 0 ).attr( "tabIndex", 0 );
17653  } else {
17654  this.active
17655  .attr( {
17656  "aria-selected": "true",
17657  "aria-expanded": "true",
17658  tabIndex: 0
17659  } );
17660  this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
17661  this._getPanelForTab( this.active )
17662  .show()
17663  .attr( {
17664  "aria-hidden": "false"
17665  } );
17666  }
17667  },
17668 
17669  _processTabs: function() {
17670  var that = this,
17671  prevTabs = this.tabs,
17672  prevAnchors = this.anchors,
17673  prevPanels = this.panels;
17674 
17675  this.tablist = this._getList().attr( "role", "tablist" );
17676  this._addClass( this.tablist, "ui-tabs-nav",
17677  "ui-helper-reset ui-helper-clearfix ui-widget-header" );
17678 
17679  // Prevent users from focusing disabled tabs via click
17680  this.tablist
17681  .on( "mousedown" + this.eventNamespace, "> li", function( event ) {
17682  if ( $( this ).is( ".ui-state-disabled" ) ) {
17683  event.preventDefault();
17684  }
17685  } )
17686 
17687  // Support: IE <9
17688  // Preventing the default action in mousedown doesn't prevent IE
17689  // from focusing the element, so if the anchor gets focused, blur.
17690  // We don't have to worry about focusing the previously focused
17691  // element since clicking on a non-focusable element should focus
17692  // the body anyway.
17693  .on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
17694  if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
17695  this.blur();
17696  }
17697  } );
17698 
17699  this.tabs = this.tablist.find( "> li:has(a[href])" )
17700  .attr( {
17701  role: "tab",
17702  tabIndex: -1
17703  } );
17704  this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
17705 
17706  this.anchors = this.tabs.map( function() {
17707  return $( "a", this )[ 0 ];
17708  } )
17709  .attr( {
17710  role: "presentation",
17711  tabIndex: -1
17712  } );
17713  this._addClass( this.anchors, "ui-tabs-anchor" );
17714 
17715  this.panels = $();
17716 
17717  this.anchors.each( function( i, anchor ) {
17718  var selector, panel, panelId,
17719  anchorId = $( anchor ).uniqueId().attr( "id" ),
17720  tab = $( anchor ).closest( "li" ),
17721  originalAriaControls = tab.attr( "aria-controls" );
17722 
17723  // Inline tab
17724  if ( that._isLocal( anchor ) ) {
17725  selector = anchor.hash;
17726  panelId = selector.substring( 1 );
17727  panel = that.element.find( that._sanitizeSelector( selector ) );
17728 
17729  // remote tab
17730  } else {
17731 
17732  // If the tab doesn't already have aria-controls,
17733  // generate an id by using a throw-away element
17734  panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
17735  selector = "#" + panelId;
17736  panel = that.element.find( selector );
17737  if ( !panel.length ) {
17738  panel = that._createPanel( panelId );
17739  panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
17740  }
17741  panel.attr( "aria-live", "polite" );
17742  }
17743 
17744  if ( panel.length ) {
17745  that.panels = that.panels.add( panel );
17746  }
17747  if ( originalAriaControls ) {
17748  tab.data( "ui-tabs-aria-controls", originalAriaControls );
17749  }
17750  tab.attr( {
17751  "aria-controls": panelId,
17752  "aria-labelledby": anchorId
17753  } );
17754  panel.attr( "aria-labelledby", anchorId );
17755  } );
17756 
17757  this.panels.attr( "role", "tabpanel" );
17758  this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
17759 
17760  // Avoid memory leaks (#10056)
17761  if ( prevTabs ) {
17762  this._off( prevTabs.not( this.tabs ) );
17763  this._off( prevAnchors.not( this.anchors ) );
17764  this._off( prevPanels.not( this.panels ) );
17765  }
17766  },
17767 
17768  // Allow overriding how to find the list for rare usage scenarios (#7715)
17769  _getList: function() {
17770  return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
17771  },
17772 
17773  _createPanel: function( id ) {
17774  return $( "<div>" )
17775  .attr( "id", id )
17776  .data( "ui-tabs-destroy", true );
17777  },
17778 
17779  _setOptionDisabled: function( disabled ) {
17780  var currentItem, li, i;
17781 
17782  if ( $.isArray( disabled ) ) {
17783  if ( !disabled.length ) {
17784  disabled = false;
17785  } else if ( disabled.length === this.anchors.length ) {
17786  disabled = true;
17787  }
17788  }
17789 
17790  // Disable tabs
17791  for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
17792  currentItem = $( li );
17793  if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
17794  currentItem.attr( "aria-disabled", "true" );
17795  this._addClass( currentItem, null, "ui-state-disabled" );
17796  } else {
17797  currentItem.removeAttr( "aria-disabled" );
17798  this._removeClass( currentItem, null, "ui-state-disabled" );
17799  }
17800  }
17801 
17802  this.options.disabled = disabled;
17803 
17804  this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
17805  disabled === true );
17806  },
17807 
17808  _setupEvents: function( event ) {
17809  var events = {};
17810  if ( event ) {
17811  $.each( event.split( " " ), function( index, eventName ) {
17812  events[ eventName ] = "_eventHandler";
17813  } );
17814  }
17815 
17816  this._off( this.anchors.add( this.tabs ).add( this.panels ) );
17817 
17818  // Always prevent the default action, even when disabled
17819  this._on( true, this.anchors, {
17820  click: function( event ) {
17821  event.preventDefault();
17822  }
17823  } );
17824  this._on( this.anchors, events );
17825  this._on( this.tabs, { keydown: "_tabKeydown" } );
17826  this._on( this.panels, { keydown: "_panelKeydown" } );
17827 
17828  this._focusable( this.tabs );
17829  this._hoverable( this.tabs );
17830  },
17831 
17832  _setupHeightStyle: function( heightStyle ) {
17833  var maxHeight,
17834  parent = this.element.parent();
17835 
17836  if ( heightStyle === "fill" ) {
17837  maxHeight = parent.height();
17838  maxHeight -= this.element.outerHeight() - this.element.height();
17839 
17840  this.element.siblings( ":visible" ).each( function() {
17841  var elem = $( this ),
17842  position = elem.css( "position" );
17843 
17844  if ( position === "absolute" || position === "fixed" ) {
17845  return;
17846  }
17847  maxHeight -= elem.outerHeight( true );
17848  } );
17849 
17850  this.element.children().not( this.panels ).each( function() {
17851  maxHeight -= $( this ).outerHeight( true );
17852  } );
17853 
17854  this.panels.each( function() {
17855  $( this ).height( Math.max( 0, maxHeight -
17856  $( this ).innerHeight() + $( this ).height() ) );
17857  } )
17858  .css( "overflow", "auto" );
17859  } else if ( heightStyle === "auto" ) {
17860  maxHeight = 0;
17861  this.panels.each( function() {
17862  maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
17863  } ).height( maxHeight );
17864  }
17865  },
17866 
17867  _eventHandler: function( event ) {
17868  var options = this.options,
17869  active = this.active,
17870  anchor = $( event.currentTarget ),
17871  tab = anchor.closest( "li" ),
17872  clickedIsActive = tab[ 0 ] === active[ 0 ],
17873  collapsing = clickedIsActive && options.collapsible,
17874  toShow = collapsing ? $() : this._getPanelForTab( tab ),
17875  toHide = !active.length ? $() : this._getPanelForTab( active ),
17876  eventData = {
17877  oldTab: active,
17878  oldPanel: toHide,
17879  newTab: collapsing ? $() : tab,
17880  newPanel: toShow
17881  };
17882 
17883  event.preventDefault();
17884 
17885  if ( tab.hasClass( "ui-state-disabled" ) ||
17886 
17887  // tab is already loading
17888  tab.hasClass( "ui-tabs-loading" ) ||
17889 
17890  // can't switch durning an animation
17891  this.running ||
17892 
17893  // click on active header, but not collapsible
17894  ( clickedIsActive && !options.collapsible ) ||
17895 
17896  // allow canceling activation
17897  ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
17898  return;
17899  }
17900 
17901  options.active = collapsing ? false : this.tabs.index( tab );
17902 
17903  this.active = clickedIsActive ? $() : tab;
17904  if ( this.xhr ) {
17905  this.xhr.abort();
17906  }
17907 
17908  if ( !toHide.length && !toShow.length ) {
17909  $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
17910  }
17911 
17912  if ( toShow.length ) {
17913  this.load( this.tabs.index( tab ), event );
17914  }
17915  this._toggle( event, eventData );
17916  },
17917 
17918  // Handles show/hide for selecting tabs
17919  _toggle: function( event, eventData ) {
17920  var that = this,
17921  toShow = eventData.newPanel,
17922  toHide = eventData.oldPanel;
17923 
17924  this.running = true;
17925 
17926  function complete() {
17927  that.running = false;
17928  that._trigger( "activate", event, eventData );
17929  }
17930 
17931  function show() {
17932  that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
17933 
17934  if ( toShow.length && that.options.show ) {
17935  that._show( toShow, that.options.show, complete );
17936  } else {
17937  toShow.show();
17938  complete();
17939  }
17940  }
17941 
17942  // Start out by hiding, then showing, then completing
17943  if ( toHide.length && this.options.hide ) {
17944  this._hide( toHide, this.options.hide, function() {
17945  that._removeClass( eventData.oldTab.closest( "li" ),
17946  "ui-tabs-active", "ui-state-active" );
17947  show();
17948  } );
17949  } else {
17950  this._removeClass( eventData.oldTab.closest( "li" ),
17951  "ui-tabs-active", "ui-state-active" );
17952  toHide.hide();
17953  show();
17954  }
17955 
17956  toHide.attr( "aria-hidden", "true" );
17957  eventData.oldTab.attr( {
17958  "aria-selected": "false",
17959  "aria-expanded": "false"
17960  } );
17961 
17962  // If we're switching tabs, remove the old tab from the tab order.
17963  // If we're opening from collapsed state, remove the previous tab from the tab order.
17964  // If we're collapsing, then keep the collapsing tab in the tab order.
17965  if ( toShow.length && toHide.length ) {
17966  eventData.oldTab.attr( "tabIndex", -1 );
17967  } else if ( toShow.length ) {
17968  this.tabs.filter( function() {
17969  return $( this ).attr( "tabIndex" ) === 0;
17970  } )
17971  .attr( "tabIndex", -1 );
17972  }
17973 
17974  toShow.attr( "aria-hidden", "false" );
17975  eventData.newTab.attr( {
17976  "aria-selected": "true",
17977  "aria-expanded": "true",
17978  tabIndex: 0
17979  } );
17980  },
17981 
17982  _activate: function( index ) {
17983  var anchor,
17984  active = this._findActive( index );
17985 
17986  // Trying to activate the already active panel
17987  if ( active[ 0 ] === this.active[ 0 ] ) {
17988  return;
17989  }
17990 
17991  // Trying to collapse, simulate a click on the current active header
17992  if ( !active.length ) {
17993  active = this.active;
17994  }
17995 
17996  anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
17997  this._eventHandler( {
17998  target: anchor,
17999  currentTarget: anchor,
18000  preventDefault: $.noop
18001  } );
18002  },
18003 
18004  _findActive: function( index ) {
18005  return index === false ? $() : this.tabs.eq( index );
18006  },
18007 
18008  _getIndex: function( index ) {
18009 
18010  // meta-function to give users option to provide a href string instead of a numerical index.
18011  if ( typeof index === "string" ) {
18012  index = this.anchors.index( this.anchors.filter( "[href$='" +
18013  $.ui.escapeSelector( index ) + "']" ) );
18014  }
18015 
18016  return index;
18017  },
18018 
18019  _destroy: function() {
18020  if ( this.xhr ) {
18021  this.xhr.abort();
18022  }
18023 
18024  this.tablist
18025  .removeAttr( "role" )
18026  .off( this.eventNamespace );
18027 
18028  this.anchors
18029  .removeAttr( "role tabIndex" )
18030  .removeUniqueId();
18031 
18032  this.tabs.add( this.panels ).each( function() {
18033  if ( $.data( this, "ui-tabs-destroy" ) ) {
18034  $( this ).remove();
18035  } else {
18036  $( this ).removeAttr( "role tabIndex " +
18037  "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18038  }
18039  } );
18040 
18041  this.tabs.each( function() {
18042  var li = $( this ),
18043  prev = li.data( "ui-tabs-aria-controls" );
18044  if ( prev ) {
18045  li
18046  .attr( "aria-controls", prev )
18047  .removeData( "ui-tabs-aria-controls" );
18048  } else {
18049  li.removeAttr( "aria-controls" );
18050  }
18051  } );
18052 
18053  this.panels.show();
18054 
18055  if ( this.options.heightStyle !== "content" ) {
18056  this.panels.css( "height", "" );
18057  }
18058  },
18059 
18060  enable: function( index ) {
18061  var disabled = this.options.disabled;
18062  if ( disabled === false ) {
18063  return;
18064  }
18065 
18066  if ( index === undefined ) {
18067  disabled = false;
18068  } else {
18069  index = this._getIndex( index );
18070  if ( $.isArray( disabled ) ) {
18071  disabled = $.map( disabled, function( num ) {
18072  return num !== index ? num : null;
18073  } );
18074  } else {
18075  disabled = $.map( this.tabs, function( li, num ) {
18076  return num !== index ? num : null;
18077  } );
18078  }
18079  }
18080  this._setOptionDisabled( disabled );
18081  },
18082 
18083  disable: function( index ) {
18084  var disabled = this.options.disabled;
18085  if ( disabled === true ) {
18086  return;
18087  }
18088 
18089  if ( index === undefined ) {
18090  disabled = true;
18091  } else {
18092  index = this._getIndex( index );
18093  if ( $.inArray( index, disabled ) !== -1 ) {
18094  return;
18095  }
18096  if ( $.isArray( disabled ) ) {
18097  disabled = $.merge( [ index ], disabled ).sort();
18098  } else {
18099  disabled = [ index ];
18100  }
18101  }
18102  this._setOptionDisabled( disabled );
18103  },
18104 
18105  load: function( index, event ) {
18106  index = this._getIndex( index );
18107  var that = this,
18108  tab = this.tabs.eq( index ),
18109  anchor = tab.find( ".ui-tabs-anchor" ),
18110  panel = this._getPanelForTab( tab ),
18111  eventData = {
18112  tab: tab,
18113  panel: panel
18114  },
18115  complete = function( jqXHR, status ) {
18116  if ( status === "abort" ) {
18117  that.panels.stop( false, true );
18118  }
18119 
18120  that._removeClass( tab, "ui-tabs-loading" );
18121  panel.removeAttr( "aria-busy" );
18122 
18123  if ( jqXHR === that.xhr ) {
18124  delete that.xhr;
18125  }
18126  };
18127 
18128  // Not remote
18129  if ( this._isLocal( anchor[ 0 ] ) ) {
18130  return;
18131  }
18132 
18133  this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18134 
18135  // Support: jQuery <1.8
18136  // jQuery <1.8 returns false if the request is canceled in beforeSend,
18137  // but as of 1.8, $.ajax() always returns a jqXHR object.
18138  if ( this.xhr && this.xhr.statusText !== "canceled" ) {
18139  this._addClass( tab, "ui-tabs-loading" );
18140  panel.attr( "aria-busy", "true" );
18141 
18142  this.xhr
18143  .done( function( response, status, jqXHR ) {
18144 
18145  // support: jQuery <1.8
18146  // http://bugs.jquery.com/ticket/11778
18147  setTimeout( function() {
18148  panel.html( response );
18149  that._trigger( "load", event, eventData );
18150 
18151  complete( jqXHR, status );
18152  }, 1 );
18153  } )
18154  .fail( function( jqXHR, status ) {
18155 
18156  // support: jQuery <1.8
18157  // http://bugs.jquery.com/ticket/11778
18158  setTimeout( function() {
18159  complete( jqXHR, status );
18160  }, 1 );
18161  } );
18162  }
18163  },
18164 
18165  _ajaxSettings: function( anchor, event, eventData ) {
18166  var that = this;
18167  return {
18168 
18169  // Support: IE <11 only
18170  // Strip any hash that exists to prevent errors with the Ajax request
18171  url: anchor.attr( "href" ).replace( /#.*$/, "" ),
18172  beforeSend: function( jqXHR, settings ) {
18173  return that._trigger( "beforeLoad", event,
18174  $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18175  }
18176  };
18177  },
18178 
18179  _getPanelForTab: function( tab ) {
18180  var id = $( tab ).attr( "aria-controls" );
18181  return this.element.find( this._sanitizeSelector( "#" + id ) );
18182  }
18183 } );
18184 
18185 // DEPRECATED
18186 // TODO: Switch return back to widget declaration at top of file when this is removed
18187 if ( $.uiBackCompat !== false ) {
18188 
18189  // Backcompat for ui-tab class (now ui-tabs-tab)
18190  $.widget( "ui.tabs", $.ui.tabs, {
18191  _processTabs: function() {
18192  this._superApply( arguments );
18193  this._addClass( this.tabs, "ui-tab" );
18194  }
18195  } );
18196 }
18197 
18198 var widgetsTabs = $.ui.tabs;
18199 
18200 
18210 //>>label: Tooltip
18211 //>>group: Widgets
18212 //>>description: Shows additional information for any element on hover or focus.
18213 //>>docs: http://api.jqueryui.com/tooltip/
18214 //>>demos: http://jqueryui.com/tooltip/
18215 //>>css.structure: ../../themes/base/core.css
18216 //>>css.structure: ../../themes/base/tooltip.css
18217 //>>css.theme: ../../themes/base/theme.css
18218 
18219 
18220 
18221 $.widget( "ui.tooltip", {
18222  version: "1.12.1",
18223  options: {
18224  classes: {
18225  "ui-tooltip": "ui-corner-all ui-widget-shadow"
18226  },
18227  content: function() {
18228 
18229  // support: IE<9, Opera in jQuery <1.7
18230  // .text() can't accept undefined, so coerce to a string
18231  var title = $( this ).attr( "title" ) || "";
18232 
18233  // Escape title, since we're going from an attribute to raw HTML
18234  return $( "<a>" ).text( title ).html();
18235  },
18236  hide: true,
18237 
18238  // Disabled elements have inconsistent behavior across browsers (#8661)
18239  items: "[title]:not([disabled])",
18240  position: {
18241  my: "left top+15",
18242  at: "left bottom",
18243  collision: "flipfit flip"
18244  },
18245  show: true,
18246  track: false,
18247 
18248  // Callbacks
18249  close: null,
18250  open: null
18251  },
18252 
18253  _addDescribedBy: function( elem, id ) {
18254  var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18255  describedby.push( id );
18256  elem
18257  .data( "ui-tooltip-id", id )
18258  .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
18259  },
18260 
18261  _removeDescribedBy: function( elem ) {
18262  var id = elem.data( "ui-tooltip-id" ),
18263  describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18264  index = $.inArray( id, describedby );
18265 
18266  if ( index !== -1 ) {
18267  describedby.splice( index, 1 );
18268  }
18269 
18270  elem.removeData( "ui-tooltip-id" );
18271  describedby = $.trim( describedby.join( " " ) );
18272  if ( describedby ) {
18273  elem.attr( "aria-describedby", describedby );
18274  } else {
18275  elem.removeAttr( "aria-describedby" );
18276  }
18277  },
18278 
18279  _create: function() {
18280  this._on( {
18281  mouseover: "open",
18282  focusin: "open"
18283  } );
18284 
18285  // IDs of generated tooltips, needed for destroy
18286  this.tooltips = {};
18287 
18288  // IDs of parent tooltips where we removed the title attribute
18289  this.parents = {};
18290 
18291  // Append the aria-live region so tooltips announce correctly
18292  this.liveRegion = $( "<div>" )
18293  .attr( {
18294  role: "log",
18295  "aria-live": "assertive",
18296  "aria-relevant": "additions"
18297  } )
18298  .appendTo( this.document[ 0 ].body );
18299  this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18300 
18301  this.disabledTitles = $( [] );
18302  },
18303 
18304  _setOption: function( key, value ) {
18305  var that = this;
18306 
18307  this._super( key, value );
18308 
18309  if ( key === "content" ) {
18310  $.each( this.tooltips, function( id, tooltipData ) {
18311  that._updateContent( tooltipData.element );
18312  } );
18313  }
18314  },
18315 
18316  _setOptionDisabled: function( value ) {
18317  this[ value ? "_disable" : "_enable" ]();
18318  },
18319 
18320  _disable: function() {
18321  var that = this;
18322 
18323  // Close open tooltips
18324  $.each( this.tooltips, function( id, tooltipData ) {
18325  var event = $.Event( "blur" );
18326  event.target = event.currentTarget = tooltipData.element[ 0 ];
18327  that.close( event, true );
18328  } );
18329 
18330  // Remove title attributes to prevent native tooltips
18331  this.disabledTitles = this.disabledTitles.add(
18332  this.element.find( this.options.items ).addBack()
18333  .filter( function() {
18334  var element = $( this );
18335  if ( element.is( "[title]" ) ) {
18336  return element
18337  .data( "ui-tooltip-title", element.attr( "title" ) )
18338  .removeAttr( "title" );
18339  }
18340  } )
18341  );
18342  },
18343 
18344  _enable: function() {
18345 
18346  // restore title attributes
18347  this.disabledTitles.each( function() {
18348  var element = $( this );
18349  if ( element.data( "ui-tooltip-title" ) ) {
18350  element.attr( "title", element.data( "ui-tooltip-title" ) );
18351  }
18352  } );
18353  this.disabledTitles = $( [] );
18354  },
18355 
18356  open: function( event ) {
18357  var that = this,
18358  target = $( event ? event.target : this.element )
18359 
18360  // we need closest here due to mouseover bubbling,
18361  // but always pointing at the same event target
18362  .closest( this.options.items );
18363 
18364  // No element to show a tooltip for or the tooltip is already open
18365  if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18366  return;
18367  }
18368 
18369  if ( target.attr( "title" ) ) {
18370  target.data( "ui-tooltip-title", target.attr( "title" ) );
18371  }
18372 
18373  target.data( "ui-tooltip-open", true );
18374 
18375  // Kill parent tooltips, custom or native, for hover
18376  if ( event && event.type === "mouseover" ) {
18377  target.parents().each( function() {
18378  var parent = $( this ),
18379  blurEvent;
18380  if ( parent.data( "ui-tooltip-open" ) ) {
18381  blurEvent = $.Event( "blur" );
18382  blurEvent.target = blurEvent.currentTarget = this;
18383  that.close( blurEvent, true );
18384  }
18385  if ( parent.attr( "title" ) ) {
18386  parent.uniqueId();
18387  that.parents[ this.id ] = {
18388  element: this,
18389  title: parent.attr( "title" )
18390  };
18391  parent.attr( "title", "" );
18392  }
18393  } );
18394  }
18395 
18396  this._registerCloseHandlers( event, target );
18397  this._updateContent( target, event );
18398  },
18399 
18400  _updateContent: function( target, event ) {
18401  var content,
18402  contentOption = this.options.content,
18403  that = this,
18404  eventType = event ? event.type : null;
18405 
18406  if ( typeof contentOption === "string" || contentOption.nodeType ||
18407  contentOption.jquery ) {
18408  return this._open( event, target, contentOption );
18409  }
18410 
18411  content = contentOption.call( target[ 0 ], function( response ) {
18412 
18413  // IE may instantly serve a cached response for ajax requests
18414  // delay this call to _open so the other call to _open runs first
18415  that._delay( function() {
18416 
18417  // Ignore async response if tooltip was closed already
18418  if ( !target.data( "ui-tooltip-open" ) ) {
18419  return;
18420  }
18421 
18422  // JQuery creates a special event for focusin when it doesn't
18423  // exist natively. To improve performance, the native event
18424  // object is reused and the type is changed. Therefore, we can't
18425  // rely on the type being correct after the event finished
18426  // bubbling, so we set it back to the previous value. (#8740)
18427  if ( event ) {
18428  event.type = eventType;
18429  }
18430  this._open( event, target, response );
18431  } );
18432  } );
18433  if ( content ) {
18434  this._open( event, target, content );
18435  }
18436  },
18437 
18438  _open: function( event, target, content ) {
18439  var tooltipData, tooltip, delayedShow, a11yContent,
18440  positionOption = $.extend( {}, this.options.position );
18441 
18442  if ( !content ) {
18443  return;
18444  }
18445 
18446  // Content can be updated multiple times. If the tooltip already
18447  // exists, then just update the content and bail.
18448  tooltipData = this._find( target );
18449  if ( tooltipData ) {
18450  tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18451  return;
18452  }
18453 
18454  // If we have a title, clear it to prevent the native tooltip
18455  // we have to check first to avoid defining a title if none exists
18456  // (we don't want to cause an element to start matching [title])
18457  //
18458  // We use removeAttr only for key events, to allow IE to export the correct
18459  // accessible attributes. For mouse events, set to empty string to avoid
18460  // native tooltip showing up (happens only when removing inside mouseover).
18461  if ( target.is( "[title]" ) ) {
18462  if ( event && event.type === "mouseover" ) {
18463  target.attr( "title", "" );
18464  } else {
18465  target.removeAttr( "title" );
18466  }
18467  }
18468 
18469  tooltipData = this._tooltip( target );
18470  tooltip = tooltipData.tooltip;
18471  this._addDescribedBy( target, tooltip.attr( "id" ) );
18472  tooltip.find( ".ui-tooltip-content" ).html( content );
18473 
18474  // Support: Voiceover on OS X, JAWS on IE <= 9
18475  // JAWS announces deletions even when aria-relevant="additions"
18476  // Voiceover will sometimes re-read the entire log region's contents from the beginning
18477  this.liveRegion.children().hide();
18478  a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18479  a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18480  a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18481  a11yContent.appendTo( this.liveRegion );
18482 
18483  function position( event ) {
18484  positionOption.of = event;
18485  if ( tooltip.is( ":hidden" ) ) {
18486  return;
18487  }
18488  tooltip.position( positionOption );
18489  }
18490  if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18491  this._on( this.document, {
18492  mousemove: position
18493  } );
18494 
18495  // trigger once to override element-relative positioning
18496  position( event );
18497  } else {
18498  tooltip.position( $.extend( {
18499  of: target
18500  }, this.options.position ) );
18501  }
18502 
18503  tooltip.hide();
18504 
18505  this._show( tooltip, this.options.show );
18506 
18507  // Handle tracking tooltips that are shown with a delay (#8644). As soon
18508  // as the tooltip is visible, position the tooltip using the most recent
18509  // event.
18510  // Adds the check to add the timers only when both delay and track options are set (#14682)
18511  if ( this.options.track && this.options.show && this.options.show.delay ) {
18512  delayedShow = this.delayedShow = setInterval( function() {
18513  if ( tooltip.is( ":visible" ) ) {
18514  position( positionOption.of );
18515  clearInterval( delayedShow );
18516  }
18517  }, $.fx.interval );
18518  }
18519 
18520  this._trigger( "open", event, { tooltip: tooltip } );
18521  },
18522 
18523  _registerCloseHandlers: function( event, target ) {
18524  var events = {
18525  keyup: function( event ) {
18526  if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18527  var fakeEvent = $.Event( event );
18528  fakeEvent.currentTarget = target[ 0 ];
18529  this.close( fakeEvent, true );
18530  }
18531  }
18532  };
18533 
18534  // Only bind remove handler for delegated targets. Non-delegated
18535  // tooltips will handle this in destroy.
18536  if ( target[ 0 ] !== this.element[ 0 ] ) {
18537  events.remove = function() {
18538  this._removeTooltip( this._find( target ).tooltip );
18539  };
18540  }
18541 
18542  if ( !event || event.type === "mouseover" ) {
18543  events.mouseleave = "close";
18544  }
18545  if ( !event || event.type === "focusin" ) {
18546  events.focusout = "close";
18547  }
18548  this._on( true, target, events );
18549  },
18550 
18551  close: function( event ) {
18552  var tooltip,
18553  that = this,
18554  target = $( event ? event.currentTarget : this.element ),
18555  tooltipData = this._find( target );
18556 
18557  // The tooltip may already be closed
18558  if ( !tooltipData ) {
18559 
18560  // We set ui-tooltip-open immediately upon open (in open()), but only set the
18561  // additional data once there's actually content to show (in _open()). So even if the
18562  // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18563  // the period between open() and _open().
18564  target.removeData( "ui-tooltip-open" );
18565  return;
18566  }
18567 
18568  tooltip = tooltipData.tooltip;
18569 
18570  // Disabling closes the tooltip, so we need to track when we're closing
18571  // to avoid an infinite loop in case the tooltip becomes disabled on close
18572  if ( tooltipData.closing ) {
18573  return;
18574  }
18575 
18576  // Clear the interval for delayed tracking tooltips
18577  clearInterval( this.delayedShow );
18578 
18579  // Only set title if we had one before (see comment in _open())
18580  // If the title attribute has changed since open(), don't restore
18581  if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18582  target.attr( "title", target.data( "ui-tooltip-title" ) );
18583  }
18584 
18585  this._removeDescribedBy( target );
18586 
18587  tooltipData.hiding = true;
18588  tooltip.stop( true );
18589  this._hide( tooltip, this.options.hide, function() {
18590  that._removeTooltip( $( this ) );
18591  } );
18592 
18593  target.removeData( "ui-tooltip-open" );
18594  this._off( target, "mouseleave focusout keyup" );
18595 
18596  // Remove 'remove' binding only on delegated targets
18597  if ( target[ 0 ] !== this.element[ 0 ] ) {
18598  this._off( target, "remove" );
18599  }
18600  this._off( this.document, "mousemove" );
18601 
18602  if ( event && event.type === "mouseleave" ) {
18603  $.each( this.parents, function( id, parent ) {
18604  $( parent.element ).attr( "title", parent.title );
18605  delete that.parents[ id ];
18606  } );
18607  }
18608 
18609  tooltipData.closing = true;
18610  this._trigger( "close", event, { tooltip: tooltip } );
18611  if ( !tooltipData.hiding ) {
18612  tooltipData.closing = false;
18613  }
18614  },
18615 
18616  _tooltip: function( element ) {
18617  var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18618  content = $( "<div>" ).appendTo( tooltip ),
18619  id = tooltip.uniqueId().attr( "id" );
18620 
18621  this._addClass( content, "ui-tooltip-content" );
18622  this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18623 
18624  tooltip.appendTo( this._appendTo( element ) );
18625 
18626  return this.tooltips[ id ] = {
18627  element: element,
18628  tooltip: tooltip
18629  };
18630  },
18631 
18632  _find: function( target ) {
18633  var id = target.data( "ui-tooltip-id" );
18634  return id ? this.tooltips[ id ] : null;
18635  },
18636 
18637  _removeTooltip: function( tooltip ) {
18638  tooltip.remove();
18639  delete this.tooltips[ tooltip.attr( "id" ) ];
18640  },
18641 
18642  _appendTo: function( target ) {
18643  var element = target.closest( ".ui-front, dialog" );
18644 
18645  if ( !element.length ) {
18646  element = this.document[ 0 ].body;
18647  }
18648 
18649  return element;
18650  },
18651 
18652  _destroy: function() {
18653  var that = this;
18654 
18655  // Close open tooltips
18656  $.each( this.tooltips, function( id, tooltipData ) {
18657 
18658  // Delegate to close method to handle common cleanup
18659  var event = $.Event( "blur" ),
18660  element = tooltipData.element;
18661  event.target = event.currentTarget = element[ 0 ];
18662  that.close( event, true );
18663 
18664  // Remove immediately; destroying an open tooltip doesn't use the
18665  // hide animation
18666  $( "#" + id ).remove();
18667 
18668  // Restore the title
18669  if ( element.data( "ui-tooltip-title" ) ) {
18670 
18671  // If the title attribute has changed since open(), don't restore
18672  if ( !element.attr( "title" ) ) {
18673  element.attr( "title", element.data( "ui-tooltip-title" ) );
18674  }
18675  element.removeData( "ui-tooltip-title" );
18676  }
18677  } );
18678  this.liveRegion.remove();
18679  }
18680 } );
18681 
18682 // DEPRECATED
18683 // TODO: Switch return back to widget declaration at top of file when this is removed
18684 if ( $.uiBackCompat !== false ) {
18685 
18686  // Backcompat for tooltipClass option
18687  $.widget( "ui.tooltip", $.ui.tooltip, {
18688  options: {
18689  tooltipClass: null
18690  },
18691  _tooltip: function() {
18692  var tooltipData = this._superApply( arguments );
18693  if ( this.options.tooltipClass ) {
18694  tooltipData.tooltip.addClass( this.options.tooltipClass );
18695  }
18696  return tooltipData;
18697  }
18698  } );
18699 }
18700 
18701 var widgetsTooltip = $.ui.tooltip;
18702 
18703 
18704 
18705 
18706 }));