iqvoc 4.8.0 → 4.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/app/assets/fonts/FiraMono-Regular.eot +0 -0
  4. data/app/assets/fonts/FiraMono-Regular.ttf +0 -0
  5. data/app/assets/fonts/FiraMono-Regular.woff +0 -0
  6. data/app/assets/fonts/FiraSans-Bold.eot +0 -0
  7. data/app/assets/fonts/FiraSans-Bold.ttf +0 -0
  8. data/app/assets/fonts/FiraSans-Bold.woff +0 -0
  9. data/app/assets/fonts/FiraSans-BoldItalic.eot +0 -0
  10. data/app/assets/fonts/FiraSans-BoldItalic.ttf +0 -0
  11. data/app/assets/fonts/FiraSans-BoldItalic.woff +0 -0
  12. data/app/assets/javascripts/framework.js +3 -2
  13. data/app/assets/javascripts/iqvoc/autocomplete.js +42 -0
  14. data/app/assets/javascripts/iqvoc/concept_mapper.js +4 -3
  15. data/app/assets/javascripts/iqvoc/entityselect.js.erb +19 -30
  16. data/app/assets/javascripts/iqvoc/federated_concept_mapper.js +14 -26
  17. data/app/assets/javascripts/iqvoc/iqvoc.js +15 -4
  18. data/app/assets/javascripts/iqvoc/manifest.js +1 -1
  19. data/app/assets/stylesheets/_framework.scss +2 -4
  20. data/app/assets/stylesheets/iqvoc/_manifest.scss +2 -2
  21. data/app/assets/stylesheets/iqvoc/components/_datepicker.scss +7 -0
  22. data/app/assets/stylesheets/iqvoc/components/typeahead.scss +56 -0
  23. data/app/assets/stylesheets/iqvoc/hacks/_hacks.scss +4 -0
  24. data/app/assets/stylesheets/iqvoc/settings/_bootstrap-variables.scss +8 -8
  25. data/app/assets/stylesheets/iqvoc/settings/_bootstrap.scss +5 -0
  26. data/app/assets/stylesheets/iqvoc/settings/_fonts.scss +25 -64
  27. data/app/views/pages/components.html.erb +44 -0
  28. data/lib/iqvoc/version.rb +1 -1
  29. data/vendor/assets/javascripts/pickadate/picker.date.js +1322 -0
  30. data/vendor/assets/javascripts/pickadate/picker.js +1061 -0
  31. data/vendor/assets/javascripts/typeahead.jquery.js +1184 -0
  32. data/vendor/assets/stylesheets/pickadate/classic.date.scss +278 -0
  33. data/vendor/assets/stylesheets/pickadate/classic.scss +109 -0
  34. metadata +19 -23
  35. data/app/assets/stylesheets/iqvoc/hacks/_jquery-ui_extensions.scss +0 -14
  36. data/vendor/assets/javascripts/jquery-ui.datepicker-de.js +0 -22
  37. data/vendor/assets/javascripts/jquery-ui.js +0 -4676
  38. data/vendor/assets/stylesheets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  39. data/vendor/assets/stylesheets/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
  40. data/vendor/assets/stylesheets/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  41. data/vendor/assets/stylesheets/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  42. data/vendor/assets/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  43. data/vendor/assets/stylesheets/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  44. data/vendor/assets/stylesheets/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  45. data/vendor/assets/stylesheets/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  46. data/vendor/assets/stylesheets/images/ui-icons_217bc0_256x240.png +0 -0
  47. data/vendor/assets/stylesheets/images/ui-icons_2e83ff_256x240.png +0 -0
  48. data/vendor/assets/stylesheets/images/ui-icons_469bdd_256x240.png +0 -0
  49. data/vendor/assets/stylesheets/images/ui-icons_6da8d5_256x240.png +0 -0
  50. data/vendor/assets/stylesheets/images/ui-icons_cd0a0a_256x240.png +0 -0
  51. data/vendor/assets/stylesheets/images/ui-icons_d8e7f3_256x240.png +0 -0
  52. data/vendor/assets/stylesheets/images/ui-icons_f9bd01_256x240.png +0 -0
  53. data/vendor/assets/stylesheets/jquery-ui.scss +0 -709
  54. data/vendor/assets/stylesheets/jquery-ui.structure.scss +0 -317
  55. data/vendor/assets/stylesheets/jquery-ui.theme.scss +0 -410
@@ -1,4676 +0,0 @@
1
- /*! jQuery UI - v1.11.2 - 2014-12-07
2
- * http://jqueryui.com
3
- * Includes: core.js, widget.js, position.js, autocomplete.js, datepicker.js, menu.js
4
- * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
5
-
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
- * jQuery UI Core 1.11.2
19
- * http://jqueryui.com
20
- *
21
- * Copyright 2014 jQuery Foundation and other contributors
22
- * Released under the MIT license.
23
- * http://jquery.org/license
24
- *
25
- * http://api.jqueryui.com/category/ui-core/
26
- */
27
-
28
-
29
- // $.ui might exist from components with no dependencies, e.g., $.ui.position
30
- $.ui = $.ui || {};
31
-
32
- $.extend( $.ui, {
33
- version: "1.11.2",
34
-
35
- keyCode: {
36
- BACKSPACE: 8,
37
- COMMA: 188,
38
- DELETE: 46,
39
- DOWN: 40,
40
- END: 35,
41
- ENTER: 13,
42
- ESCAPE: 27,
43
- HOME: 36,
44
- LEFT: 37,
45
- PAGE_DOWN: 34,
46
- PAGE_UP: 33,
47
- PERIOD: 190,
48
- RIGHT: 39,
49
- SPACE: 32,
50
- TAB: 9,
51
- UP: 38
52
- }
53
- });
54
-
55
- // plugins
56
- $.fn.extend({
57
- scrollParent: function( includeHidden ) {
58
- var position = this.css( "position" ),
59
- excludeStaticParent = position === "absolute",
60
- overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
61
- scrollParent = this.parents().filter( function() {
62
- var parent = $( this );
63
- if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
64
- return false;
65
- }
66
- return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
67
- }).eq( 0 );
68
-
69
- return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
70
- },
71
-
72
- uniqueId: (function() {
73
- var uuid = 0;
74
-
75
- return function() {
76
- return this.each(function() {
77
- if ( !this.id ) {
78
- this.id = "ui-id-" + ( ++uuid );
79
- }
80
- });
81
- };
82
- })(),
83
-
84
- removeUniqueId: function() {
85
- return this.each(function() {
86
- if ( /^ui-id-\d+$/.test( this.id ) ) {
87
- $( this ).removeAttr( "id" );
88
- }
89
- });
90
- }
91
- });
92
-
93
- // selectors
94
- function focusable( element, isTabIndexNotNaN ) {
95
- var map, mapName, img,
96
- nodeName = element.nodeName.toLowerCase();
97
- if ( "area" === nodeName ) {
98
- map = element.parentNode;
99
- mapName = map.name;
100
- if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
101
- return false;
102
- }
103
- img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
104
- return !!img && visible( img );
105
- }
106
- return ( /input|select|textarea|button|object/.test( nodeName ) ?
107
- !element.disabled :
108
- "a" === nodeName ?
109
- element.href || isTabIndexNotNaN :
110
- isTabIndexNotNaN) &&
111
- // the element and all of its ancestors must be visible
112
- visible( element );
113
- }
114
-
115
- function visible( element ) {
116
- return $.expr.filters.visible( element ) &&
117
- !$( element ).parents().addBack().filter(function() {
118
- return $.css( this, "visibility" ) === "hidden";
119
- }).length;
120
- }
121
-
122
- $.extend( $.expr[ ":" ], {
123
- data: $.expr.createPseudo ?
124
- $.expr.createPseudo(function( dataName ) {
125
- return function( elem ) {
126
- return !!$.data( elem, dataName );
127
- };
128
- }) :
129
- // support: jQuery <1.8
130
- function( elem, i, match ) {
131
- return !!$.data( elem, match[ 3 ] );
132
- },
133
-
134
- focusable: function( element ) {
135
- return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
136
- },
137
-
138
- tabbable: function( element ) {
139
- var tabIndex = $.attr( element, "tabindex" ),
140
- isTabIndexNaN = isNaN( tabIndex );
141
- return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
142
- }
143
- });
144
-
145
- // support: jQuery <1.8
146
- if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
147
- $.each( [ "Width", "Height" ], function( i, name ) {
148
- var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
149
- type = name.toLowerCase(),
150
- orig = {
151
- innerWidth: $.fn.innerWidth,
152
- innerHeight: $.fn.innerHeight,
153
- outerWidth: $.fn.outerWidth,
154
- outerHeight: $.fn.outerHeight
155
- };
156
-
157
- function reduce( elem, size, border, margin ) {
158
- $.each( side, function() {
159
- size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
160
- if ( border ) {
161
- size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
162
- }
163
- if ( margin ) {
164
- size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
165
- }
166
- });
167
- return size;
168
- }
169
-
170
- $.fn[ "inner" + name ] = function( size ) {
171
- if ( size === undefined ) {
172
- return orig[ "inner" + name ].call( this );
173
- }
174
-
175
- return this.each(function() {
176
- $( this ).css( type, reduce( this, size ) + "px" );
177
- });
178
- };
179
-
180
- $.fn[ "outer" + name] = function( size, margin ) {
181
- if ( typeof size !== "number" ) {
182
- return orig[ "outer" + name ].call( this, size );
183
- }
184
-
185
- return this.each(function() {
186
- $( this).css( type, reduce( this, size, true, margin ) + "px" );
187
- });
188
- };
189
- });
190
- }
191
-
192
- // support: jQuery <1.8
193
- if ( !$.fn.addBack ) {
194
- $.fn.addBack = function( selector ) {
195
- return this.add( selector == null ?
196
- this.prevObject : this.prevObject.filter( selector )
197
- );
198
- };
199
- }
200
-
201
- // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
202
- if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
203
- $.fn.removeData = (function( removeData ) {
204
- return function( key ) {
205
- if ( arguments.length ) {
206
- return removeData.call( this, $.camelCase( key ) );
207
- } else {
208
- return removeData.call( this );
209
- }
210
- };
211
- })( $.fn.removeData );
212
- }
213
-
214
- // deprecated
215
- $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
216
-
217
- $.fn.extend({
218
- focus: (function( orig ) {
219
- return function( delay, fn ) {
220
- return typeof delay === "number" ?
221
- this.each(function() {
222
- var elem = this;
223
- setTimeout(function() {
224
- $( elem ).focus();
225
- if ( fn ) {
226
- fn.call( elem );
227
- }
228
- }, delay );
229
- }) :
230
- orig.apply( this, arguments );
231
- };
232
- })( $.fn.focus ),
233
-
234
- disableSelection: (function() {
235
- var eventType = "onselectstart" in document.createElement( "div" ) ?
236
- "selectstart" :
237
- "mousedown";
238
-
239
- return function() {
240
- return this.bind( eventType + ".ui-disableSelection", function( event ) {
241
- event.preventDefault();
242
- });
243
- };
244
- })(),
245
-
246
- enableSelection: function() {
247
- return this.unbind( ".ui-disableSelection" );
248
- },
249
-
250
- zIndex: function( zIndex ) {
251
- if ( zIndex !== undefined ) {
252
- return this.css( "zIndex", zIndex );
253
- }
254
-
255
- if ( this.length ) {
256
- var elem = $( this[ 0 ] ), position, value;
257
- while ( elem.length && elem[ 0 ] !== document ) {
258
- // Ignore z-index if position is set to a value where z-index is ignored by the browser
259
- // This makes behavior of this function consistent across browsers
260
- // WebKit always returns auto if the element is positioned
261
- position = elem.css( "position" );
262
- if ( position === "absolute" || position === "relative" || position === "fixed" ) {
263
- // IE returns 0 when zIndex is not specified
264
- // other browsers return a string
265
- // we ignore the case of nested elements with an explicit value of 0
266
- // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
267
- value = parseInt( elem.css( "zIndex" ), 10 );
268
- if ( !isNaN( value ) && value !== 0 ) {
269
- return value;
270
- }
271
- }
272
- elem = elem.parent();
273
- }
274
- }
275
-
276
- return 0;
277
- }
278
- });
279
-
280
- // $.ui.plugin is deprecated. Use $.widget() extensions instead.
281
- $.ui.plugin = {
282
- add: function( module, option, set ) {
283
- var i,
284
- proto = $.ui[ module ].prototype;
285
- for ( i in set ) {
286
- proto.plugins[ i ] = proto.plugins[ i ] || [];
287
- proto.plugins[ i ].push( [ option, set[ i ] ] );
288
- }
289
- },
290
- call: function( instance, name, args, allowDisconnected ) {
291
- var i,
292
- set = instance.plugins[ name ];
293
-
294
- if ( !set ) {
295
- return;
296
- }
297
-
298
- if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
299
- return;
300
- }
301
-
302
- for ( i = 0; i < set.length; i++ ) {
303
- if ( instance.options[ set[ i ][ 0 ] ] ) {
304
- set[ i ][ 1 ].apply( instance.element, args );
305
- }
306
- }
307
- }
308
- };
309
-
310
-
311
- /*!
312
- * jQuery UI Widget 1.11.2
313
- * http://jqueryui.com
314
- *
315
- * Copyright 2014 jQuery Foundation and other contributors
316
- * Released under the MIT license.
317
- * http://jquery.org/license
318
- *
319
- * http://api.jqueryui.com/jQuery.widget/
320
- */
321
-
322
-
323
- var widget_uuid = 0,
324
- widget_slice = Array.prototype.slice;
325
-
326
- $.cleanData = (function( orig ) {
327
- return function( elems ) {
328
- var events, elem, i;
329
- for ( i = 0; (elem = elems[i]) != null; i++ ) {
330
- try {
331
-
332
- // Only trigger remove when necessary to save time
333
- events = $._data( elem, "events" );
334
- if ( events && events.remove ) {
335
- $( elem ).triggerHandler( "remove" );
336
- }
337
-
338
- // http://bugs.jquery.com/ticket/8235
339
- } catch ( e ) {}
340
- }
341
- orig( elems );
342
- };
343
- })( $.cleanData );
344
-
345
- $.widget = function( name, base, prototype ) {
346
- var fullName, existingConstructor, constructor, basePrototype,
347
- // proxiedPrototype allows the provided prototype to remain unmodified
348
- // so that it can be used as a mixin for multiple widgets (#8876)
349
- proxiedPrototype = {},
350
- namespace = name.split( "." )[ 0 ];
351
-
352
- name = name.split( "." )[ 1 ];
353
- fullName = namespace + "-" + name;
354
-
355
- if ( !prototype ) {
356
- prototype = base;
357
- base = $.Widget;
358
- }
359
-
360
- // create selector for plugin
361
- $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
362
- return !!$.data( elem, fullName );
363
- };
364
-
365
- $[ namespace ] = $[ namespace ] || {};
366
- existingConstructor = $[ namespace ][ name ];
367
- constructor = $[ namespace ][ name ] = function( options, element ) {
368
- // allow instantiation without "new" keyword
369
- if ( !this._createWidget ) {
370
- return new constructor( options, element );
371
- }
372
-
373
- // allow instantiation without initializing for simple inheritance
374
- // must use "new" keyword (the code above always passes args)
375
- if ( arguments.length ) {
376
- this._createWidget( options, element );
377
- }
378
- };
379
- // extend with the existing constructor to carry over any static properties
380
- $.extend( constructor, existingConstructor, {
381
- version: prototype.version,
382
- // copy the object used to create the prototype in case we need to
383
- // redefine the widget later
384
- _proto: $.extend( {}, prototype ),
385
- // track widgets that inherit from this widget in case this widget is
386
- // redefined after a widget inherits from it
387
- _childConstructors: []
388
- });
389
-
390
- basePrototype = new base();
391
- // we need to make the options hash a property directly on the new instance
392
- // otherwise we'll modify the options hash on the prototype that we're
393
- // inheriting from
394
- basePrototype.options = $.widget.extend( {}, basePrototype.options );
395
- $.each( prototype, function( prop, value ) {
396
- if ( !$.isFunction( value ) ) {
397
- proxiedPrototype[ prop ] = value;
398
- return;
399
- }
400
- proxiedPrototype[ prop ] = (function() {
401
- var _super = function() {
402
- return base.prototype[ prop ].apply( this, arguments );
403
- },
404
- _superApply = function( args ) {
405
- return base.prototype[ prop ].apply( this, args );
406
- };
407
- return function() {
408
- var __super = this._super,
409
- __superApply = this._superApply,
410
- returnValue;
411
-
412
- this._super = _super;
413
- this._superApply = _superApply;
414
-
415
- returnValue = value.apply( this, arguments );
416
-
417
- this._super = __super;
418
- this._superApply = __superApply;
419
-
420
- return returnValue;
421
- };
422
- })();
423
- });
424
- constructor.prototype = $.widget.extend( basePrototype, {
425
- // TODO: remove support for widgetEventPrefix
426
- // always use the name + a colon as the prefix, e.g., draggable:start
427
- // don't prefix for widgets that aren't DOM-based
428
- widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
429
- }, proxiedPrototype, {
430
- constructor: constructor,
431
- namespace: namespace,
432
- widgetName: name,
433
- widgetFullName: fullName
434
- });
435
-
436
- // If this widget is being redefined then we need to find all widgets that
437
- // are inheriting from it and redefine all of them so that they inherit from
438
- // the new version of this widget. We're essentially trying to replace one
439
- // level in the prototype chain.
440
- if ( existingConstructor ) {
441
- $.each( existingConstructor._childConstructors, function( i, child ) {
442
- var childPrototype = child.prototype;
443
-
444
- // redefine the child widget using the same prototype that was
445
- // originally used, but inherit from the new version of the base
446
- $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
447
- });
448
- // remove the list of existing child constructors from the old constructor
449
- // so the old child constructors can be garbage collected
450
- delete existingConstructor._childConstructors;
451
- } else {
452
- base._childConstructors.push( constructor );
453
- }
454
-
455
- $.widget.bridge( name, constructor );
456
-
457
- return constructor;
458
- };
459
-
460
- $.widget.extend = function( target ) {
461
- var input = widget_slice.call( arguments, 1 ),
462
- inputIndex = 0,
463
- inputLength = input.length,
464
- key,
465
- value;
466
- for ( ; inputIndex < inputLength; inputIndex++ ) {
467
- for ( key in input[ inputIndex ] ) {
468
- value = input[ inputIndex ][ key ];
469
- if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
470
- // Clone objects
471
- if ( $.isPlainObject( value ) ) {
472
- target[ key ] = $.isPlainObject( target[ key ] ) ?
473
- $.widget.extend( {}, target[ key ], value ) :
474
- // Don't extend strings, arrays, etc. with objects
475
- $.widget.extend( {}, value );
476
- // Copy everything else by reference
477
- } else {
478
- target[ key ] = value;
479
- }
480
- }
481
- }
482
- }
483
- return target;
484
- };
485
-
486
- $.widget.bridge = function( name, object ) {
487
- var fullName = object.prototype.widgetFullName || name;
488
- $.fn[ name ] = function( options ) {
489
- var isMethodCall = typeof options === "string",
490
- args = widget_slice.call( arguments, 1 ),
491
- returnValue = this;
492
-
493
- // allow multiple hashes to be passed on init
494
- options = !isMethodCall && args.length ?
495
- $.widget.extend.apply( null, [ options ].concat(args) ) :
496
- options;
497
-
498
- if ( isMethodCall ) {
499
- this.each(function() {
500
- var methodValue,
501
- instance = $.data( this, fullName );
502
- if ( options === "instance" ) {
503
- returnValue = instance;
504
- return false;
505
- }
506
- if ( !instance ) {
507
- return $.error( "cannot call methods on " + name + " prior to initialization; " +
508
- "attempted to call method '" + options + "'" );
509
- }
510
- if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
511
- return $.error( "no such method '" + options + "' for " + name + " widget instance" );
512
- }
513
- methodValue = instance[ options ].apply( instance, args );
514
- if ( methodValue !== instance && methodValue !== undefined ) {
515
- returnValue = methodValue && methodValue.jquery ?
516
- returnValue.pushStack( methodValue.get() ) :
517
- methodValue;
518
- return false;
519
- }
520
- });
521
- } else {
522
- this.each(function() {
523
- var instance = $.data( this, fullName );
524
- if ( instance ) {
525
- instance.option( options || {} );
526
- if ( instance._init ) {
527
- instance._init();
528
- }
529
- } else {
530
- $.data( this, fullName, new object( options, this ) );
531
- }
532
- });
533
- }
534
-
535
- return returnValue;
536
- };
537
- };
538
-
539
- $.Widget = function( /* options, element */ ) {};
540
- $.Widget._childConstructors = [];
541
-
542
- $.Widget.prototype = {
543
- widgetName: "widget",
544
- widgetEventPrefix: "",
545
- defaultElement: "<div>",
546
- options: {
547
- disabled: false,
548
-
549
- // callbacks
550
- create: null
551
- },
552
- _createWidget: function( options, element ) {
553
- element = $( element || this.defaultElement || this )[ 0 ];
554
- this.element = $( element );
555
- this.uuid = widget_uuid++;
556
- this.eventNamespace = "." + this.widgetName + this.uuid;
557
-
558
- this.bindings = $();
559
- this.hoverable = $();
560
- this.focusable = $();
561
-
562
- if ( element !== this ) {
563
- $.data( element, this.widgetFullName, this );
564
- this._on( true, this.element, {
565
- remove: function( event ) {
566
- if ( event.target === element ) {
567
- this.destroy();
568
- }
569
- }
570
- });
571
- this.document = $( element.style ?
572
- // element within the document
573
- element.ownerDocument :
574
- // element is window or document
575
- element.document || element );
576
- this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
577
- }
578
-
579
- this.options = $.widget.extend( {},
580
- this.options,
581
- this._getCreateOptions(),
582
- options );
583
-
584
- this._create();
585
- this._trigger( "create", null, this._getCreateEventData() );
586
- this._init();
587
- },
588
- _getCreateOptions: $.noop,
589
- _getCreateEventData: $.noop,
590
- _create: $.noop,
591
- _init: $.noop,
592
-
593
- destroy: function() {
594
- this._destroy();
595
- // we can probably remove the unbind calls in 2.0
596
- // all event bindings should go through this._on()
597
- this.element
598
- .unbind( this.eventNamespace )
599
- .removeData( this.widgetFullName )
600
- // support: jquery <1.6.3
601
- // http://bugs.jquery.com/ticket/9413
602
- .removeData( $.camelCase( this.widgetFullName ) );
603
- this.widget()
604
- .unbind( this.eventNamespace )
605
- .removeAttr( "aria-disabled" )
606
- .removeClass(
607
- this.widgetFullName + "-disabled " +
608
- "ui-state-disabled" );
609
-
610
- // clean up events and states
611
- this.bindings.unbind( this.eventNamespace );
612
- this.hoverable.removeClass( "ui-state-hover" );
613
- this.focusable.removeClass( "ui-state-focus" );
614
- },
615
- _destroy: $.noop,
616
-
617
- widget: function() {
618
- return this.element;
619
- },
620
-
621
- option: function( key, value ) {
622
- var options = key,
623
- parts,
624
- curOption,
625
- i;
626
-
627
- if ( arguments.length === 0 ) {
628
- // don't return a reference to the internal hash
629
- return $.widget.extend( {}, this.options );
630
- }
631
-
632
- if ( typeof key === "string" ) {
633
- // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
634
- options = {};
635
- parts = key.split( "." );
636
- key = parts.shift();
637
- if ( parts.length ) {
638
- curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
639
- for ( i = 0; i < parts.length - 1; i++ ) {
640
- curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
641
- curOption = curOption[ parts[ i ] ];
642
- }
643
- key = parts.pop();
644
- if ( arguments.length === 1 ) {
645
- return curOption[ key ] === undefined ? null : curOption[ key ];
646
- }
647
- curOption[ key ] = value;
648
- } else {
649
- if ( arguments.length === 1 ) {
650
- return this.options[ key ] === undefined ? null : this.options[ key ];
651
- }
652
- options[ key ] = value;
653
- }
654
- }
655
-
656
- this._setOptions( options );
657
-
658
- return this;
659
- },
660
- _setOptions: function( options ) {
661
- var key;
662
-
663
- for ( key in options ) {
664
- this._setOption( key, options[ key ] );
665
- }
666
-
667
- return this;
668
- },
669
- _setOption: function( key, value ) {
670
- this.options[ key ] = value;
671
-
672
- if ( key === "disabled" ) {
673
- this.widget()
674
- .toggleClass( this.widgetFullName + "-disabled", !!value );
675
-
676
- // If the widget is becoming disabled, then nothing is interactive
677
- if ( value ) {
678
- this.hoverable.removeClass( "ui-state-hover" );
679
- this.focusable.removeClass( "ui-state-focus" );
680
- }
681
- }
682
-
683
- return this;
684
- },
685
-
686
- enable: function() {
687
- return this._setOptions({ disabled: false });
688
- },
689
- disable: function() {
690
- return this._setOptions({ disabled: true });
691
- },
692
-
693
- _on: function( suppressDisabledCheck, element, handlers ) {
694
- var delegateElement,
695
- instance = this;
696
-
697
- // no suppressDisabledCheck flag, shuffle arguments
698
- if ( typeof suppressDisabledCheck !== "boolean" ) {
699
- handlers = element;
700
- element = suppressDisabledCheck;
701
- suppressDisabledCheck = false;
702
- }
703
-
704
- // no element argument, shuffle and use this.element
705
- if ( !handlers ) {
706
- handlers = element;
707
- element = this.element;
708
- delegateElement = this.widget();
709
- } else {
710
- element = delegateElement = $( element );
711
- this.bindings = this.bindings.add( element );
712
- }
713
-
714
- $.each( handlers, function( event, handler ) {
715
- function handlerProxy() {
716
- // allow widgets to customize the disabled handling
717
- // - disabled as an array instead of boolean
718
- // - disabled class as method for disabling individual parts
719
- if ( !suppressDisabledCheck &&
720
- ( instance.options.disabled === true ||
721
- $( this ).hasClass( "ui-state-disabled" ) ) ) {
722
- return;
723
- }
724
- return ( typeof handler === "string" ? instance[ handler ] : handler )
725
- .apply( instance, arguments );
726
- }
727
-
728
- // copy the guid so direct unbinding works
729
- if ( typeof handler !== "string" ) {
730
- handlerProxy.guid = handler.guid =
731
- handler.guid || handlerProxy.guid || $.guid++;
732
- }
733
-
734
- var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
735
- eventName = match[1] + instance.eventNamespace,
736
- selector = match[2];
737
- if ( selector ) {
738
- delegateElement.delegate( selector, eventName, handlerProxy );
739
- } else {
740
- element.bind( eventName, handlerProxy );
741
- }
742
- });
743
- },
744
-
745
- _off: function( element, eventName ) {
746
- eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
747
- this.eventNamespace;
748
- element.unbind( eventName ).undelegate( eventName );
749
-
750
- // Clear the stack to avoid memory leaks (#10056)
751
- this.bindings = $( this.bindings.not( element ).get() );
752
- this.focusable = $( this.focusable.not( element ).get() );
753
- this.hoverable = $( this.hoverable.not( element ).get() );
754
- },
755
-
756
- _delay: function( handler, delay ) {
757
- function handlerProxy() {
758
- return ( typeof handler === "string" ? instance[ handler ] : handler )
759
- .apply( instance, arguments );
760
- }
761
- var instance = this;
762
- return setTimeout( handlerProxy, delay || 0 );
763
- },
764
-
765
- _hoverable: function( element ) {
766
- this.hoverable = this.hoverable.add( element );
767
- this._on( element, {
768
- mouseenter: function( event ) {
769
- $( event.currentTarget ).addClass( "ui-state-hover" );
770
- },
771
- mouseleave: function( event ) {
772
- $( event.currentTarget ).removeClass( "ui-state-hover" );
773
- }
774
- });
775
- },
776
-
777
- _focusable: function( element ) {
778
- this.focusable = this.focusable.add( element );
779
- this._on( element, {
780
- focusin: function( event ) {
781
- $( event.currentTarget ).addClass( "ui-state-focus" );
782
- },
783
- focusout: function( event ) {
784
- $( event.currentTarget ).removeClass( "ui-state-focus" );
785
- }
786
- });
787
- },
788
-
789
- _trigger: function( type, event, data ) {
790
- var prop, orig,
791
- callback = this.options[ type ];
792
-
793
- data = data || {};
794
- event = $.Event( event );
795
- event.type = ( type === this.widgetEventPrefix ?
796
- type :
797
- this.widgetEventPrefix + type ).toLowerCase();
798
- // the original event may come from any element
799
- // so we need to reset the target on the new event
800
- event.target = this.element[ 0 ];
801
-
802
- // copy original event properties over to the new event
803
- orig = event.originalEvent;
804
- if ( orig ) {
805
- for ( prop in orig ) {
806
- if ( !( prop in event ) ) {
807
- event[ prop ] = orig[ prop ];
808
- }
809
- }
810
- }
811
-
812
- this.element.trigger( event, data );
813
- return !( $.isFunction( callback ) &&
814
- callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
815
- event.isDefaultPrevented() );
816
- }
817
- };
818
-
819
- $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
820
- $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
821
- if ( typeof options === "string" ) {
822
- options = { effect: options };
823
- }
824
- var hasOptions,
825
- effectName = !options ?
826
- method :
827
- options === true || typeof options === "number" ?
828
- defaultEffect :
829
- options.effect || defaultEffect;
830
- options = options || {};
831
- if ( typeof options === "number" ) {
832
- options = { duration: options };
833
- }
834
- hasOptions = !$.isEmptyObject( options );
835
- options.complete = callback;
836
- if ( options.delay ) {
837
- element.delay( options.delay );
838
- }
839
- if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
840
- element[ method ]( options );
841
- } else if ( effectName !== method && element[ effectName ] ) {
842
- element[ effectName ]( options.duration, options.easing, callback );
843
- } else {
844
- element.queue(function( next ) {
845
- $( this )[ method ]();
846
- if ( callback ) {
847
- callback.call( element[ 0 ] );
848
- }
849
- next();
850
- });
851
- }
852
- };
853
- });
854
-
855
- var widget = $.widget;
856
-
857
-
858
- /*!
859
- * jQuery UI Position 1.11.2
860
- * http://jqueryui.com
861
- *
862
- * Copyright 2014 jQuery Foundation and other contributors
863
- * Released under the MIT license.
864
- * http://jquery.org/license
865
- *
866
- * http://api.jqueryui.com/position/
867
- */
868
-
869
- (function() {
870
-
871
- $.ui = $.ui || {};
872
-
873
- var cachedScrollbarWidth, supportsOffsetFractions,
874
- max = Math.max,
875
- abs = Math.abs,
876
- round = Math.round,
877
- rhorizontal = /left|center|right/,
878
- rvertical = /top|center|bottom/,
879
- roffset = /[\+\-]\d+(\.[\d]+)?%?/,
880
- rposition = /^\w+/,
881
- rpercent = /%$/,
882
- _position = $.fn.position;
883
-
884
- function getOffsets( offsets, width, height ) {
885
- return [
886
- parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
887
- parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
888
- ];
889
- }
890
-
891
- function parseCss( element, property ) {
892
- return parseInt( $.css( element, property ), 10 ) || 0;
893
- }
894
-
895
- function getDimensions( elem ) {
896
- var raw = elem[0];
897
- if ( raw.nodeType === 9 ) {
898
- return {
899
- width: elem.width(),
900
- height: elem.height(),
901
- offset: { top: 0, left: 0 }
902
- };
903
- }
904
- if ( $.isWindow( raw ) ) {
905
- return {
906
- width: elem.width(),
907
- height: elem.height(),
908
- offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
909
- };
910
- }
911
- if ( raw.preventDefault ) {
912
- return {
913
- width: 0,
914
- height: 0,
915
- offset: { top: raw.pageY, left: raw.pageX }
916
- };
917
- }
918
- return {
919
- width: elem.outerWidth(),
920
- height: elem.outerHeight(),
921
- offset: elem.offset()
922
- };
923
- }
924
-
925
- $.position = {
926
- scrollbarWidth: function() {
927
- if ( cachedScrollbarWidth !== undefined ) {
928
- return cachedScrollbarWidth;
929
- }
930
- var w1, w2,
931
- div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
932
- innerDiv = div.children()[0];
933
-
934
- $( "body" ).append( div );
935
- w1 = innerDiv.offsetWidth;
936
- div.css( "overflow", "scroll" );
937
-
938
- w2 = innerDiv.offsetWidth;
939
-
940
- if ( w1 === w2 ) {
941
- w2 = div[0].clientWidth;
942
- }
943
-
944
- div.remove();
945
-
946
- return (cachedScrollbarWidth = w1 - w2);
947
- },
948
- getScrollInfo: function( within ) {
949
- var overflowX = within.isWindow || within.isDocument ? "" :
950
- within.element.css( "overflow-x" ),
951
- overflowY = within.isWindow || within.isDocument ? "" :
952
- within.element.css( "overflow-y" ),
953
- hasOverflowX = overflowX === "scroll" ||
954
- ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
955
- hasOverflowY = overflowY === "scroll" ||
956
- ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
957
- return {
958
- width: hasOverflowY ? $.position.scrollbarWidth() : 0,
959
- height: hasOverflowX ? $.position.scrollbarWidth() : 0
960
- };
961
- },
962
- getWithinInfo: function( element ) {
963
- var withinElement = $( element || window ),
964
- isWindow = $.isWindow( withinElement[0] ),
965
- isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
966
- return {
967
- element: withinElement,
968
- isWindow: isWindow,
969
- isDocument: isDocument,
970
- offset: withinElement.offset() || { left: 0, top: 0 },
971
- scrollLeft: withinElement.scrollLeft(),
972
- scrollTop: withinElement.scrollTop(),
973
-
974
- // support: jQuery 1.6.x
975
- // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
976
- width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
977
- height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
978
- };
979
- }
980
- };
981
-
982
- $.fn.position = function( options ) {
983
- if ( !options || !options.of ) {
984
- return _position.apply( this, arguments );
985
- }
986
-
987
- // make a copy, we don't want to modify arguments
988
- options = $.extend( {}, options );
989
-
990
- var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
991
- target = $( options.of ),
992
- within = $.position.getWithinInfo( options.within ),
993
- scrollInfo = $.position.getScrollInfo( within ),
994
- collision = ( options.collision || "flip" ).split( " " ),
995
- offsets = {};
996
-
997
- dimensions = getDimensions( target );
998
- if ( target[0].preventDefault ) {
999
- // force left top to allow flipping
1000
- options.at = "left top";
1001
- }
1002
- targetWidth = dimensions.width;
1003
- targetHeight = dimensions.height;
1004
- targetOffset = dimensions.offset;
1005
- // clone to reuse original targetOffset later
1006
- basePosition = $.extend( {}, targetOffset );
1007
-
1008
- // force my and at to have valid horizontal and vertical positions
1009
- // if a value is missing or invalid, it will be converted to center
1010
- $.each( [ "my", "at" ], function() {
1011
- var pos = ( options[ this ] || "" ).split( " " ),
1012
- horizontalOffset,
1013
- verticalOffset;
1014
-
1015
- if ( pos.length === 1) {
1016
- pos = rhorizontal.test( pos[ 0 ] ) ?
1017
- pos.concat( [ "center" ] ) :
1018
- rvertical.test( pos[ 0 ] ) ?
1019
- [ "center" ].concat( pos ) :
1020
- [ "center", "center" ];
1021
- }
1022
- pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1023
- pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1024
-
1025
- // calculate offsets
1026
- horizontalOffset = roffset.exec( pos[ 0 ] );
1027
- verticalOffset = roffset.exec( pos[ 1 ] );
1028
- offsets[ this ] = [
1029
- horizontalOffset ? horizontalOffset[ 0 ] : 0,
1030
- verticalOffset ? verticalOffset[ 0 ] : 0
1031
- ];
1032
-
1033
- // reduce to just the positions without the offsets
1034
- options[ this ] = [
1035
- rposition.exec( pos[ 0 ] )[ 0 ],
1036
- rposition.exec( pos[ 1 ] )[ 0 ]
1037
- ];
1038
- });
1039
-
1040
- // normalize collision option
1041
- if ( collision.length === 1 ) {
1042
- collision[ 1 ] = collision[ 0 ];
1043
- }
1044
-
1045
- if ( options.at[ 0 ] === "right" ) {
1046
- basePosition.left += targetWidth;
1047
- } else if ( options.at[ 0 ] === "center" ) {
1048
- basePosition.left += targetWidth / 2;
1049
- }
1050
-
1051
- if ( options.at[ 1 ] === "bottom" ) {
1052
- basePosition.top += targetHeight;
1053
- } else if ( options.at[ 1 ] === "center" ) {
1054
- basePosition.top += targetHeight / 2;
1055
- }
1056
-
1057
- atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1058
- basePosition.left += atOffset[ 0 ];
1059
- basePosition.top += atOffset[ 1 ];
1060
-
1061
- return this.each(function() {
1062
- var collisionPosition, using,
1063
- elem = $( this ),
1064
- elemWidth = elem.outerWidth(),
1065
- elemHeight = elem.outerHeight(),
1066
- marginLeft = parseCss( this, "marginLeft" ),
1067
- marginTop = parseCss( this, "marginTop" ),
1068
- collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1069
- collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1070
- position = $.extend( {}, basePosition ),
1071
- myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1072
-
1073
- if ( options.my[ 0 ] === "right" ) {
1074
- position.left -= elemWidth;
1075
- } else if ( options.my[ 0 ] === "center" ) {
1076
- position.left -= elemWidth / 2;
1077
- }
1078
-
1079
- if ( options.my[ 1 ] === "bottom" ) {
1080
- position.top -= elemHeight;
1081
- } else if ( options.my[ 1 ] === "center" ) {
1082
- position.top -= elemHeight / 2;
1083
- }
1084
-
1085
- position.left += myOffset[ 0 ];
1086
- position.top += myOffset[ 1 ];
1087
-
1088
- // if the browser doesn't support fractions, then round for consistent results
1089
- if ( !supportsOffsetFractions ) {
1090
- position.left = round( position.left );
1091
- position.top = round( position.top );
1092
- }
1093
-
1094
- collisionPosition = {
1095
- marginLeft: marginLeft,
1096
- marginTop: marginTop
1097
- };
1098
-
1099
- $.each( [ "left", "top" ], function( i, dir ) {
1100
- if ( $.ui.position[ collision[ i ] ] ) {
1101
- $.ui.position[ collision[ i ] ][ dir ]( position, {
1102
- targetWidth: targetWidth,
1103
- targetHeight: targetHeight,
1104
- elemWidth: elemWidth,
1105
- elemHeight: elemHeight,
1106
- collisionPosition: collisionPosition,
1107
- collisionWidth: collisionWidth,
1108
- collisionHeight: collisionHeight,
1109
- offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1110
- my: options.my,
1111
- at: options.at,
1112
- within: within,
1113
- elem: elem
1114
- });
1115
- }
1116
- });
1117
-
1118
- if ( options.using ) {
1119
- // adds feedback as second argument to using callback, if present
1120
- using = function( props ) {
1121
- var left = targetOffset.left - position.left,
1122
- right = left + targetWidth - elemWidth,
1123
- top = targetOffset.top - position.top,
1124
- bottom = top + targetHeight - elemHeight,
1125
- feedback = {
1126
- target: {
1127
- element: target,
1128
- left: targetOffset.left,
1129
- top: targetOffset.top,
1130
- width: targetWidth,
1131
- height: targetHeight
1132
- },
1133
- element: {
1134
- element: elem,
1135
- left: position.left,
1136
- top: position.top,
1137
- width: elemWidth,
1138
- height: elemHeight
1139
- },
1140
- horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1141
- vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1142
- };
1143
- if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1144
- feedback.horizontal = "center";
1145
- }
1146
- if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1147
- feedback.vertical = "middle";
1148
- }
1149
- if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1150
- feedback.important = "horizontal";
1151
- } else {
1152
- feedback.important = "vertical";
1153
- }
1154
- options.using.call( this, props, feedback );
1155
- };
1156
- }
1157
-
1158
- elem.offset( $.extend( position, { using: using } ) );
1159
- });
1160
- };
1161
-
1162
- $.ui.position = {
1163
- fit: {
1164
- left: function( position, data ) {
1165
- var within = data.within,
1166
- withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1167
- outerWidth = within.width,
1168
- collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1169
- overLeft = withinOffset - collisionPosLeft,
1170
- overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1171
- newOverRight;
1172
-
1173
- // element is wider than within
1174
- if ( data.collisionWidth > outerWidth ) {
1175
- // element is initially over the left side of within
1176
- if ( overLeft > 0 && overRight <= 0 ) {
1177
- newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1178
- position.left += overLeft - newOverRight;
1179
- // element is initially over right side of within
1180
- } else if ( overRight > 0 && overLeft <= 0 ) {
1181
- position.left = withinOffset;
1182
- // element is initially over both left and right sides of within
1183
- } else {
1184
- if ( overLeft > overRight ) {
1185
- position.left = withinOffset + outerWidth - data.collisionWidth;
1186
- } else {
1187
- position.left = withinOffset;
1188
- }
1189
- }
1190
- // too far left -> align with left edge
1191
- } else if ( overLeft > 0 ) {
1192
- position.left += overLeft;
1193
- // too far right -> align with right edge
1194
- } else if ( overRight > 0 ) {
1195
- position.left -= overRight;
1196
- // adjust based on position and margin
1197
- } else {
1198
- position.left = max( position.left - collisionPosLeft, position.left );
1199
- }
1200
- },
1201
- top: function( position, data ) {
1202
- var within = data.within,
1203
- withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1204
- outerHeight = data.within.height,
1205
- collisionPosTop = position.top - data.collisionPosition.marginTop,
1206
- overTop = withinOffset - collisionPosTop,
1207
- overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1208
- newOverBottom;
1209
-
1210
- // element is taller than within
1211
- if ( data.collisionHeight > outerHeight ) {
1212
- // element is initially over the top of within
1213
- if ( overTop > 0 && overBottom <= 0 ) {
1214
- newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1215
- position.top += overTop - newOverBottom;
1216
- // element is initially over bottom of within
1217
- } else if ( overBottom > 0 && overTop <= 0 ) {
1218
- position.top = withinOffset;
1219
- // element is initially over both top and bottom of within
1220
- } else {
1221
- if ( overTop > overBottom ) {
1222
- position.top = withinOffset + outerHeight - data.collisionHeight;
1223
- } else {
1224
- position.top = withinOffset;
1225
- }
1226
- }
1227
- // too far up -> align with top
1228
- } else if ( overTop > 0 ) {
1229
- position.top += overTop;
1230
- // too far down -> align with bottom edge
1231
- } else if ( overBottom > 0 ) {
1232
- position.top -= overBottom;
1233
- // adjust based on position and margin
1234
- } else {
1235
- position.top = max( position.top - collisionPosTop, position.top );
1236
- }
1237
- }
1238
- },
1239
- flip: {
1240
- left: function( position, data ) {
1241
- var within = data.within,
1242
- withinOffset = within.offset.left + within.scrollLeft,
1243
- outerWidth = within.width,
1244
- offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1245
- collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1246
- overLeft = collisionPosLeft - offsetLeft,
1247
- overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1248
- myOffset = data.my[ 0 ] === "left" ?
1249
- -data.elemWidth :
1250
- data.my[ 0 ] === "right" ?
1251
- data.elemWidth :
1252
- 0,
1253
- atOffset = data.at[ 0 ] === "left" ?
1254
- data.targetWidth :
1255
- data.at[ 0 ] === "right" ?
1256
- -data.targetWidth :
1257
- 0,
1258
- offset = -2 * data.offset[ 0 ],
1259
- newOverRight,
1260
- newOverLeft;
1261
-
1262
- if ( overLeft < 0 ) {
1263
- newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1264
- if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1265
- position.left += myOffset + atOffset + offset;
1266
- }
1267
- } else if ( overRight > 0 ) {
1268
- newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1269
- if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1270
- position.left += myOffset + atOffset + offset;
1271
- }
1272
- }
1273
- },
1274
- top: function( position, data ) {
1275
- var within = data.within,
1276
- withinOffset = within.offset.top + within.scrollTop,
1277
- outerHeight = within.height,
1278
- offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1279
- collisionPosTop = position.top - data.collisionPosition.marginTop,
1280
- overTop = collisionPosTop - offsetTop,
1281
- overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1282
- top = data.my[ 1 ] === "top",
1283
- myOffset = top ?
1284
- -data.elemHeight :
1285
- data.my[ 1 ] === "bottom" ?
1286
- data.elemHeight :
1287
- 0,
1288
- atOffset = data.at[ 1 ] === "top" ?
1289
- data.targetHeight :
1290
- data.at[ 1 ] === "bottom" ?
1291
- -data.targetHeight :
1292
- 0,
1293
- offset = -2 * data.offset[ 1 ],
1294
- newOverTop,
1295
- newOverBottom;
1296
- if ( overTop < 0 ) {
1297
- newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1298
- if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
1299
- position.top += myOffset + atOffset + offset;
1300
- }
1301
- } else if ( overBottom > 0 ) {
1302
- newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1303
- if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
1304
- position.top += myOffset + atOffset + offset;
1305
- }
1306
- }
1307
- }
1308
- },
1309
- flipfit: {
1310
- left: function() {
1311
- $.ui.position.flip.left.apply( this, arguments );
1312
- $.ui.position.fit.left.apply( this, arguments );
1313
- },
1314
- top: function() {
1315
- $.ui.position.flip.top.apply( this, arguments );
1316
- $.ui.position.fit.top.apply( this, arguments );
1317
- }
1318
- }
1319
- };
1320
-
1321
- // fraction support test
1322
- (function() {
1323
- var testElement, testElementParent, testElementStyle, offsetLeft, i,
1324
- body = document.getElementsByTagName( "body" )[ 0 ],
1325
- div = document.createElement( "div" );
1326
-
1327
- //Create a "fake body" for testing based on method used in jQuery.support
1328
- testElement = document.createElement( body ? "div" : "body" );
1329
- testElementStyle = {
1330
- visibility: "hidden",
1331
- width: 0,
1332
- height: 0,
1333
- border: 0,
1334
- margin: 0,
1335
- background: "none"
1336
- };
1337
- if ( body ) {
1338
- $.extend( testElementStyle, {
1339
- position: "absolute",
1340
- left: "-1000px",
1341
- top: "-1000px"
1342
- });
1343
- }
1344
- for ( i in testElementStyle ) {
1345
- testElement.style[ i ] = testElementStyle[ i ];
1346
- }
1347
- testElement.appendChild( div );
1348
- testElementParent = body || document.documentElement;
1349
- testElementParent.insertBefore( testElement, testElementParent.firstChild );
1350
-
1351
- div.style.cssText = "position: absolute; left: 10.7432222px;";
1352
-
1353
- offsetLeft = $( div ).offset().left;
1354
- supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1355
-
1356
- testElement.innerHTML = "";
1357
- testElementParent.removeChild( testElement );
1358
- })();
1359
-
1360
- })();
1361
-
1362
- var position = $.ui.position;
1363
-
1364
-
1365
- /*!
1366
- * jQuery UI Menu 1.11.2
1367
- * http://jqueryui.com
1368
- *
1369
- * Copyright 2014 jQuery Foundation and other contributors
1370
- * Released under the MIT license.
1371
- * http://jquery.org/license
1372
- *
1373
- * http://api.jqueryui.com/menu/
1374
- */
1375
-
1376
-
1377
- var menu = $.widget( "ui.menu", {
1378
- version: "1.11.2",
1379
- defaultElement: "<ul>",
1380
- delay: 300,
1381
- options: {
1382
- icons: {
1383
- submenu: "ui-icon-carat-1-e"
1384
- },
1385
- items: "> *",
1386
- menus: "ul",
1387
- position: {
1388
- my: "left-1 top",
1389
- at: "right top"
1390
- },
1391
- role: "menu",
1392
-
1393
- // callbacks
1394
- blur: null,
1395
- focus: null,
1396
- select: null
1397
- },
1398
-
1399
- _create: function() {
1400
- this.activeMenu = this.element;
1401
-
1402
- // Flag used to prevent firing of the click handler
1403
- // as the event bubbles up through nested menus
1404
- this.mouseHandled = false;
1405
- this.element
1406
- .uniqueId()
1407
- .addClass( "ui-menu ui-widget ui-widget-content" )
1408
- .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
1409
- .attr({
1410
- role: this.options.role,
1411
- tabIndex: 0
1412
- });
1413
-
1414
- if ( this.options.disabled ) {
1415
- this.element
1416
- .addClass( "ui-state-disabled" )
1417
- .attr( "aria-disabled", "true" );
1418
- }
1419
-
1420
- this._on({
1421
- // Prevent focus from sticking to links inside menu after clicking
1422
- // them (focus should always stay on UL during navigation).
1423
- "mousedown .ui-menu-item": function( event ) {
1424
- event.preventDefault();
1425
- },
1426
- "click .ui-menu-item": function( event ) {
1427
- var target = $( event.target );
1428
- if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
1429
- this.select( event );
1430
-
1431
- // Only set the mouseHandled flag if the event will bubble, see #9469.
1432
- if ( !event.isPropagationStopped() ) {
1433
- this.mouseHandled = true;
1434
- }
1435
-
1436
- // Open submenu on click
1437
- if ( target.has( ".ui-menu" ).length ) {
1438
- this.expand( event );
1439
- } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
1440
-
1441
- // Redirect focus to the menu
1442
- this.element.trigger( "focus", [ true ] );
1443
-
1444
- // If the active item is on the top level, let it stay active.
1445
- // Otherwise, blur the active item since it is no longer visible.
1446
- if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
1447
- clearTimeout( this.timer );
1448
- }
1449
- }
1450
- }
1451
- },
1452
- "mouseenter .ui-menu-item": function( event ) {
1453
- // Ignore mouse events while typeahead is active, see #10458.
1454
- // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
1455
- // is over an item in the menu
1456
- if ( this.previousFilter ) {
1457
- return;
1458
- }
1459
- var target = $( event.currentTarget );
1460
- // Remove ui-state-active class from siblings of the newly focused menu item
1461
- // to avoid a jump caused by adjacent elements both having a class with a border
1462
- target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
1463
- this.focus( event, target );
1464
- },
1465
- mouseleave: "collapseAll",
1466
- "mouseleave .ui-menu": "collapseAll",
1467
- focus: function( event, keepActiveItem ) {
1468
- // If there's already an active item, keep it active
1469
- // If not, activate the first item
1470
- var item = this.active || this.element.find( this.options.items ).eq( 0 );
1471
-
1472
- if ( !keepActiveItem ) {
1473
- this.focus( event, item );
1474
- }
1475
- },
1476
- blur: function( event ) {
1477
- this._delay(function() {
1478
- if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
1479
- this.collapseAll( event );
1480
- }
1481
- });
1482
- },
1483
- keydown: "_keydown"
1484
- });
1485
-
1486
- this.refresh();
1487
-
1488
- // Clicks outside of a menu collapse any open menus
1489
- this._on( this.document, {
1490
- click: function( event ) {
1491
- if ( this._closeOnDocumentClick( event ) ) {
1492
- this.collapseAll( event );
1493
- }
1494
-
1495
- // Reset the mouseHandled flag
1496
- this.mouseHandled = false;
1497
- }
1498
- });
1499
- },
1500
-
1501
- _destroy: function() {
1502
- // Destroy (sub)menus
1503
- this.element
1504
- .removeAttr( "aria-activedescendant" )
1505
- .find( ".ui-menu" ).addBack()
1506
- .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
1507
- .removeAttr( "role" )
1508
- .removeAttr( "tabIndex" )
1509
- .removeAttr( "aria-labelledby" )
1510
- .removeAttr( "aria-expanded" )
1511
- .removeAttr( "aria-hidden" )
1512
- .removeAttr( "aria-disabled" )
1513
- .removeUniqueId()
1514
- .show();
1515
-
1516
- // Destroy menu items
1517
- this.element.find( ".ui-menu-item" )
1518
- .removeClass( "ui-menu-item" )
1519
- .removeAttr( "role" )
1520
- .removeAttr( "aria-disabled" )
1521
- .removeUniqueId()
1522
- .removeClass( "ui-state-hover" )
1523
- .removeAttr( "tabIndex" )
1524
- .removeAttr( "role" )
1525
- .removeAttr( "aria-haspopup" )
1526
- .children().each( function() {
1527
- var elem = $( this );
1528
- if ( elem.data( "ui-menu-submenu-carat" ) ) {
1529
- elem.remove();
1530
- }
1531
- });
1532
-
1533
- // Destroy menu dividers
1534
- this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
1535
- },
1536
-
1537
- _keydown: function( event ) {
1538
- var match, prev, character, skip,
1539
- preventDefault = true;
1540
-
1541
- switch ( event.keyCode ) {
1542
- case $.ui.keyCode.PAGE_UP:
1543
- this.previousPage( event );
1544
- break;
1545
- case $.ui.keyCode.PAGE_DOWN:
1546
- this.nextPage( event );
1547
- break;
1548
- case $.ui.keyCode.HOME:
1549
- this._move( "first", "first", event );
1550
- break;
1551
- case $.ui.keyCode.END:
1552
- this._move( "last", "last", event );
1553
- break;
1554
- case $.ui.keyCode.UP:
1555
- this.previous( event );
1556
- break;
1557
- case $.ui.keyCode.DOWN:
1558
- this.next( event );
1559
- break;
1560
- case $.ui.keyCode.LEFT:
1561
- this.collapse( event );
1562
- break;
1563
- case $.ui.keyCode.RIGHT:
1564
- if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
1565
- this.expand( event );
1566
- }
1567
- break;
1568
- case $.ui.keyCode.ENTER:
1569
- case $.ui.keyCode.SPACE:
1570
- this._activate( event );
1571
- break;
1572
- case $.ui.keyCode.ESCAPE:
1573
- this.collapse( event );
1574
- break;
1575
- default:
1576
- preventDefault = false;
1577
- prev = this.previousFilter || "";
1578
- character = String.fromCharCode( event.keyCode );
1579
- skip = false;
1580
-
1581
- clearTimeout( this.filterTimer );
1582
-
1583
- if ( character === prev ) {
1584
- skip = true;
1585
- } else {
1586
- character = prev + character;
1587
- }
1588
-
1589
- match = this._filterMenuItems( character );
1590
- match = skip && match.index( this.active.next() ) !== -1 ?
1591
- this.active.nextAll( ".ui-menu-item" ) :
1592
- match;
1593
-
1594
- // If no matches on the current filter, reset to the last character pressed
1595
- // to move down the menu to the first item that starts with that character
1596
- if ( !match.length ) {
1597
- character = String.fromCharCode( event.keyCode );
1598
- match = this._filterMenuItems( character );
1599
- }
1600
-
1601
- if ( match.length ) {
1602
- this.focus( event, match );
1603
- this.previousFilter = character;
1604
- this.filterTimer = this._delay(function() {
1605
- delete this.previousFilter;
1606
- }, 1000 );
1607
- } else {
1608
- delete this.previousFilter;
1609
- }
1610
- }
1611
-
1612
- if ( preventDefault ) {
1613
- event.preventDefault();
1614
- }
1615
- },
1616
-
1617
- _activate: function( event ) {
1618
- if ( !this.active.is( ".ui-state-disabled" ) ) {
1619
- if ( this.active.is( "[aria-haspopup='true']" ) ) {
1620
- this.expand( event );
1621
- } else {
1622
- this.select( event );
1623
- }
1624
- }
1625
- },
1626
-
1627
- refresh: function() {
1628
- var menus, items,
1629
- that = this,
1630
- icon = this.options.icons.submenu,
1631
- submenus = this.element.find( this.options.menus );
1632
-
1633
- this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
1634
-
1635
- // Initialize nested menus
1636
- submenus.filter( ":not(.ui-menu)" )
1637
- .addClass( "ui-menu ui-widget ui-widget-content ui-front" )
1638
- .hide()
1639
- .attr({
1640
- role: this.options.role,
1641
- "aria-hidden": "true",
1642
- "aria-expanded": "false"
1643
- })
1644
- .each(function() {
1645
- var menu = $( this ),
1646
- item = menu.parent(),
1647
- submenuCarat = $( "<span>" )
1648
- .addClass( "ui-menu-icon ui-icon " + icon )
1649
- .data( "ui-menu-submenu-carat", true );
1650
-
1651
- item
1652
- .attr( "aria-haspopup", "true" )
1653
- .prepend( submenuCarat );
1654
- menu.attr( "aria-labelledby", item.attr( "id" ) );
1655
- });
1656
-
1657
- menus = submenus.add( this.element );
1658
- items = menus.find( this.options.items );
1659
-
1660
- // Initialize menu-items containing spaces and/or dashes only as dividers
1661
- items.not( ".ui-menu-item" ).each(function() {
1662
- var item = $( this );
1663
- if ( that._isDivider( item ) ) {
1664
- item.addClass( "ui-widget-content ui-menu-divider" );
1665
- }
1666
- });
1667
-
1668
- // Don't refresh list items that are already adapted
1669
- items.not( ".ui-menu-item, .ui-menu-divider" )
1670
- .addClass( "ui-menu-item" )
1671
- .uniqueId()
1672
- .attr({
1673
- tabIndex: -1,
1674
- role: this._itemRole()
1675
- });
1676
-
1677
- // Add aria-disabled attribute to any disabled menu item
1678
- items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
1679
-
1680
- // If the active item has been removed, blur the menu
1681
- if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1682
- this.blur();
1683
- }
1684
- },
1685
-
1686
- _itemRole: function() {
1687
- return {
1688
- menu: "menuitem",
1689
- listbox: "option"
1690
- }[ this.options.role ];
1691
- },
1692
-
1693
- _setOption: function( key, value ) {
1694
- if ( key === "icons" ) {
1695
- this.element.find( ".ui-menu-icon" )
1696
- .removeClass( this.options.icons.submenu )
1697
- .addClass( value.submenu );
1698
- }
1699
- if ( key === "disabled" ) {
1700
- this.element
1701
- .toggleClass( "ui-state-disabled", !!value )
1702
- .attr( "aria-disabled", value );
1703
- }
1704
- this._super( key, value );
1705
- },
1706
-
1707
- focus: function( event, item ) {
1708
- var nested, focused;
1709
- this.blur( event, event && event.type === "focus" );
1710
-
1711
- this._scrollIntoView( item );
1712
-
1713
- this.active = item.first();
1714
- focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
1715
- // Only update aria-activedescendant if there's a role
1716
- // otherwise we assume focus is managed elsewhere
1717
- if ( this.options.role ) {
1718
- this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
1719
- }
1720
-
1721
- // Highlight active parent menu item, if any
1722
- this.active
1723
- .parent()
1724
- .closest( ".ui-menu-item" )
1725
- .addClass( "ui-state-active" );
1726
-
1727
- if ( event && event.type === "keydown" ) {
1728
- this._close();
1729
- } else {
1730
- this.timer = this._delay(function() {
1731
- this._close();
1732
- }, this.delay );
1733
- }
1734
-
1735
- nested = item.children( ".ui-menu" );
1736
- if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
1737
- this._startOpening(nested);
1738
- }
1739
- this.activeMenu = item.parent();
1740
-
1741
- this._trigger( "focus", event, { item: item } );
1742
- },
1743
-
1744
- _scrollIntoView: function( item ) {
1745
- var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
1746
- if ( this._hasScroll() ) {
1747
- borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
1748
- paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
1749
- offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
1750
- scroll = this.activeMenu.scrollTop();
1751
- elementHeight = this.activeMenu.height();
1752
- itemHeight = item.outerHeight();
1753
-
1754
- if ( offset < 0 ) {
1755
- this.activeMenu.scrollTop( scroll + offset );
1756
- } else if ( offset + itemHeight > elementHeight ) {
1757
- this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
1758
- }
1759
- }
1760
- },
1761
-
1762
- blur: function( event, fromFocus ) {
1763
- if ( !fromFocus ) {
1764
- clearTimeout( this.timer );
1765
- }
1766
-
1767
- if ( !this.active ) {
1768
- return;
1769
- }
1770
-
1771
- this.active.removeClass( "ui-state-focus" );
1772
- this.active = null;
1773
-
1774
- this._trigger( "blur", event, { item: this.active } );
1775
- },
1776
-
1777
- _startOpening: function( submenu ) {
1778
- clearTimeout( this.timer );
1779
-
1780
- // Don't open if already open fixes a Firefox bug that caused a .5 pixel
1781
- // shift in the submenu position when mousing over the carat icon
1782
- if ( submenu.attr( "aria-hidden" ) !== "true" ) {
1783
- return;
1784
- }
1785
-
1786
- this.timer = this._delay(function() {
1787
- this._close();
1788
- this._open( submenu );
1789
- }, this.delay );
1790
- },
1791
-
1792
- _open: function( submenu ) {
1793
- var position = $.extend({
1794
- of: this.active
1795
- }, this.options.position );
1796
-
1797
- clearTimeout( this.timer );
1798
- this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
1799
- .hide()
1800
- .attr( "aria-hidden", "true" );
1801
-
1802
- submenu
1803
- .show()
1804
- .removeAttr( "aria-hidden" )
1805
- .attr( "aria-expanded", "true" )
1806
- .position( position );
1807
- },
1808
-
1809
- collapseAll: function( event, all ) {
1810
- clearTimeout( this.timer );
1811
- this.timer = this._delay(function() {
1812
- // If we were passed an event, look for the submenu that contains the event
1813
- var currentMenu = all ? this.element :
1814
- $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
1815
-
1816
- // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
1817
- if ( !currentMenu.length ) {
1818
- currentMenu = this.element;
1819
- }
1820
-
1821
- this._close( currentMenu );
1822
-
1823
- this.blur( event );
1824
- this.activeMenu = currentMenu;
1825
- }, this.delay );
1826
- },
1827
-
1828
- // With no arguments, closes the currently active menu - if nothing is active
1829
- // it closes all menus. If passed an argument, it will search for menus BELOW
1830
- _close: function( startMenu ) {
1831
- if ( !startMenu ) {
1832
- startMenu = this.active ? this.active.parent() : this.element;
1833
- }
1834
-
1835
- startMenu
1836
- .find( ".ui-menu" )
1837
- .hide()
1838
- .attr( "aria-hidden", "true" )
1839
- .attr( "aria-expanded", "false" )
1840
- .end()
1841
- .find( ".ui-state-active" ).not( ".ui-state-focus" )
1842
- .removeClass( "ui-state-active" );
1843
- },
1844
-
1845
- _closeOnDocumentClick: function( event ) {
1846
- return !$( event.target ).closest( ".ui-menu" ).length;
1847
- },
1848
-
1849
- _isDivider: function( item ) {
1850
-
1851
- // Match hyphen, em dash, en dash
1852
- return !/[^\-\u2014\u2013\s]/.test( item.text() );
1853
- },
1854
-
1855
- collapse: function( event ) {
1856
- var newItem = this.active &&
1857
- this.active.parent().closest( ".ui-menu-item", this.element );
1858
- if ( newItem && newItem.length ) {
1859
- this._close();
1860
- this.focus( event, newItem );
1861
- }
1862
- },
1863
-
1864
- expand: function( event ) {
1865
- var newItem = this.active &&
1866
- this.active
1867
- .children( ".ui-menu " )
1868
- .find( this.options.items )
1869
- .first();
1870
-
1871
- if ( newItem && newItem.length ) {
1872
- this._open( newItem.parent() );
1873
-
1874
- // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
1875
- this._delay(function() {
1876
- this.focus( event, newItem );
1877
- });
1878
- }
1879
- },
1880
-
1881
- next: function( event ) {
1882
- this._move( "next", "first", event );
1883
- },
1884
-
1885
- previous: function( event ) {
1886
- this._move( "prev", "last", event );
1887
- },
1888
-
1889
- isFirstItem: function() {
1890
- return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
1891
- },
1892
-
1893
- isLastItem: function() {
1894
- return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
1895
- },
1896
-
1897
- _move: function( direction, filter, event ) {
1898
- var next;
1899
- if ( this.active ) {
1900
- if ( direction === "first" || direction === "last" ) {
1901
- next = this.active
1902
- [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
1903
- .eq( -1 );
1904
- } else {
1905
- next = this.active
1906
- [ direction + "All" ]( ".ui-menu-item" )
1907
- .eq( 0 );
1908
- }
1909
- }
1910
- if ( !next || !next.length || !this.active ) {
1911
- next = this.activeMenu.find( this.options.items )[ filter ]();
1912
- }
1913
-
1914
- this.focus( event, next );
1915
- },
1916
-
1917
- nextPage: function( event ) {
1918
- var item, base, height;
1919
-
1920
- if ( !this.active ) {
1921
- this.next( event );
1922
- return;
1923
- }
1924
- if ( this.isLastItem() ) {
1925
- return;
1926
- }
1927
- if ( this._hasScroll() ) {
1928
- base = this.active.offset().top;
1929
- height = this.element.height();
1930
- this.active.nextAll( ".ui-menu-item" ).each(function() {
1931
- item = $( this );
1932
- return item.offset().top - base - height < 0;
1933
- });
1934
-
1935
- this.focus( event, item );
1936
- } else {
1937
- this.focus( event, this.activeMenu.find( this.options.items )
1938
- [ !this.active ? "first" : "last" ]() );
1939
- }
1940
- },
1941
-
1942
- previousPage: function( event ) {
1943
- var item, base, height;
1944
- if ( !this.active ) {
1945
- this.next( event );
1946
- return;
1947
- }
1948
- if ( this.isFirstItem() ) {
1949
- return;
1950
- }
1951
- if ( this._hasScroll() ) {
1952
- base = this.active.offset().top;
1953
- height = this.element.height();
1954
- this.active.prevAll( ".ui-menu-item" ).each(function() {
1955
- item = $( this );
1956
- return item.offset().top - base + height > 0;
1957
- });
1958
-
1959
- this.focus( event, item );
1960
- } else {
1961
- this.focus( event, this.activeMenu.find( this.options.items ).first() );
1962
- }
1963
- },
1964
-
1965
- _hasScroll: function() {
1966
- return this.element.outerHeight() < this.element.prop( "scrollHeight" );
1967
- },
1968
-
1969
- select: function( event ) {
1970
- // TODO: It should never be possible to not have an active item at this
1971
- // point, but the tests don't trigger mouseenter before click.
1972
- this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
1973
- var ui = { item: this.active };
1974
- if ( !this.active.has( ".ui-menu" ).length ) {
1975
- this.collapseAll( event, true );
1976
- }
1977
- this._trigger( "select", event, ui );
1978
- },
1979
-
1980
- _filterMenuItems: function(character) {
1981
- var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
1982
- regex = new RegExp( "^" + escapedCharacter, "i" );
1983
-
1984
- return this.activeMenu
1985
- .find( this.options.items )
1986
-
1987
- // Only match on items, not dividers or other content (#10571)
1988
- .filter( ".ui-menu-item" )
1989
- .filter(function() {
1990
- return regex.test( $.trim( $( this ).text() ) );
1991
- });
1992
- }
1993
- });
1994
-
1995
-
1996
- /*!
1997
- * jQuery UI Autocomplete 1.11.2
1998
- * http://jqueryui.com
1999
- *
2000
- * Copyright 2014 jQuery Foundation and other contributors
2001
- * Released under the MIT license.
2002
- * http://jquery.org/license
2003
- *
2004
- * http://api.jqueryui.com/autocomplete/
2005
- */
2006
-
2007
-
2008
- $.widget( "ui.autocomplete", {
2009
- version: "1.11.2",
2010
- defaultElement: "<input>",
2011
- options: {
2012
- appendTo: null,
2013
- autoFocus: false,
2014
- delay: 300,
2015
- minLength: 1,
2016
- position: {
2017
- my: "left top",
2018
- at: "left bottom",
2019
- collision: "none"
2020
- },
2021
- source: null,
2022
-
2023
- // callbacks
2024
- change: null,
2025
- close: null,
2026
- focus: null,
2027
- open: null,
2028
- response: null,
2029
- search: null,
2030
- select: null
2031
- },
2032
-
2033
- requestIndex: 0,
2034
- pending: 0,
2035
-
2036
- _create: function() {
2037
- // Some browsers only repeat keydown events, not keypress events,
2038
- // so we use the suppressKeyPress flag to determine if we've already
2039
- // handled the keydown event. #7269
2040
- // Unfortunately the code for & in keypress is the same as the up arrow,
2041
- // so we use the suppressKeyPressRepeat flag to avoid handling keypress
2042
- // events when we know the keydown event was used to modify the
2043
- // search term. #7799
2044
- var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2045
- nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2046
- isTextarea = nodeName === "textarea",
2047
- isInput = nodeName === "input";
2048
-
2049
- this.isMultiLine =
2050
- // Textareas are always multi-line
2051
- isTextarea ? true :
2052
- // Inputs are always single-line, even if inside a contentEditable element
2053
- // IE also treats inputs as contentEditable
2054
- isInput ? false :
2055
- // All other element types are determined by whether or not they're contentEditable
2056
- this.element.prop( "isContentEditable" );
2057
-
2058
- this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2059
- this.isNewMenu = true;
2060
-
2061
- this.element
2062
- .addClass( "ui-autocomplete-input" )
2063
- .attr( "autocomplete", "off" );
2064
-
2065
- this._on( this.element, {
2066
- keydown: function( event ) {
2067
- if ( this.element.prop( "readOnly" ) ) {
2068
- suppressKeyPress = true;
2069
- suppressInput = true;
2070
- suppressKeyPressRepeat = true;
2071
- return;
2072
- }
2073
-
2074
- suppressKeyPress = false;
2075
- suppressInput = false;
2076
- suppressKeyPressRepeat = false;
2077
- var keyCode = $.ui.keyCode;
2078
- switch ( event.keyCode ) {
2079
- case keyCode.PAGE_UP:
2080
- suppressKeyPress = true;
2081
- this._move( "previousPage", event );
2082
- break;
2083
- case keyCode.PAGE_DOWN:
2084
- suppressKeyPress = true;
2085
- this._move( "nextPage", event );
2086
- break;
2087
- case keyCode.UP:
2088
- suppressKeyPress = true;
2089
- this._keyEvent( "previous", event );
2090
- break;
2091
- case keyCode.DOWN:
2092
- suppressKeyPress = true;
2093
- this._keyEvent( "next", event );
2094
- break;
2095
- case keyCode.ENTER:
2096
- // when menu is open and has focus
2097
- if ( this.menu.active ) {
2098
- // #6055 - Opera still allows the keypress to occur
2099
- // which causes forms to submit
2100
- suppressKeyPress = true;
2101
- event.preventDefault();
2102
- this.menu.select( event );
2103
- }
2104
- break;
2105
- case keyCode.TAB:
2106
- if ( this.menu.active ) {
2107
- this.menu.select( event );
2108
- }
2109
- break;
2110
- case keyCode.ESCAPE:
2111
- if ( this.menu.element.is( ":visible" ) ) {
2112
- if ( !this.isMultiLine ) {
2113
- this._value( this.term );
2114
- }
2115
- this.close( event );
2116
- // Different browsers have different default behavior for escape
2117
- // Single press can mean undo or clear
2118
- // Double press in IE means clear the whole form
2119
- event.preventDefault();
2120
- }
2121
- break;
2122
- default:
2123
- suppressKeyPressRepeat = true;
2124
- // search timeout should be triggered before the input value is changed
2125
- this._searchTimeout( event );
2126
- break;
2127
- }
2128
- },
2129
- keypress: function( event ) {
2130
- if ( suppressKeyPress ) {
2131
- suppressKeyPress = false;
2132
- if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2133
- event.preventDefault();
2134
- }
2135
- return;
2136
- }
2137
- if ( suppressKeyPressRepeat ) {
2138
- return;
2139
- }
2140
-
2141
- // replicate some key handlers to allow them to repeat in Firefox and Opera
2142
- var keyCode = $.ui.keyCode;
2143
- switch ( event.keyCode ) {
2144
- case keyCode.PAGE_UP:
2145
- this._move( "previousPage", event );
2146
- break;
2147
- case keyCode.PAGE_DOWN:
2148
- this._move( "nextPage", event );
2149
- break;
2150
- case keyCode.UP:
2151
- this._keyEvent( "previous", event );
2152
- break;
2153
- case keyCode.DOWN:
2154
- this._keyEvent( "next", event );
2155
- break;
2156
- }
2157
- },
2158
- input: function( event ) {
2159
- if ( suppressInput ) {
2160
- suppressInput = false;
2161
- event.preventDefault();
2162
- return;
2163
- }
2164
- this._searchTimeout( event );
2165
- },
2166
- focus: function() {
2167
- this.selectedItem = null;
2168
- this.previous = this._value();
2169
- },
2170
- blur: function( event ) {
2171
- if ( this.cancelBlur ) {
2172
- delete this.cancelBlur;
2173
- return;
2174
- }
2175
-
2176
- clearTimeout( this.searching );
2177
- this.close( event );
2178
- this._change( event );
2179
- }
2180
- });
2181
-
2182
- this._initSource();
2183
- this.menu = $( "<ul>" )
2184
- .addClass( "ui-autocomplete ui-front" )
2185
- .appendTo( this._appendTo() )
2186
- .menu({
2187
- // disable ARIA support, the live region takes care of that
2188
- role: null
2189
- })
2190
- .hide()
2191
- .menu( "instance" );
2192
-
2193
- this._on( this.menu.element, {
2194
- mousedown: function( event ) {
2195
- // prevent moving focus out of the text field
2196
- event.preventDefault();
2197
-
2198
- // IE doesn't prevent moving focus even with event.preventDefault()
2199
- // so we set a flag to know when we should ignore the blur event
2200
- this.cancelBlur = true;
2201
- this._delay(function() {
2202
- delete this.cancelBlur;
2203
- });
2204
-
2205
- // clicking on the scrollbar causes focus to shift to the body
2206
- // but we can't detect a mouseup or a click immediately afterward
2207
- // so we have to track the next mousedown and close the menu if
2208
- // the user clicks somewhere outside of the autocomplete
2209
- var menuElement = this.menu.element[ 0 ];
2210
- if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2211
- this._delay(function() {
2212
- var that = this;
2213
- this.document.one( "mousedown", function( event ) {
2214
- if ( event.target !== that.element[ 0 ] &&
2215
- event.target !== menuElement &&
2216
- !$.contains( menuElement, event.target ) ) {
2217
- that.close();
2218
- }
2219
- });
2220
- });
2221
- }
2222
- },
2223
- menufocus: function( event, ui ) {
2224
- var label, item;
2225
- // support: Firefox
2226
- // Prevent accidental activation of menu items in Firefox (#7024 #9118)
2227
- if ( this.isNewMenu ) {
2228
- this.isNewMenu = false;
2229
- if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2230
- this.menu.blur();
2231
-
2232
- this.document.one( "mousemove", function() {
2233
- $( event.target ).trigger( event.originalEvent );
2234
- });
2235
-
2236
- return;
2237
- }
2238
- }
2239
-
2240
- item = ui.item.data( "ui-autocomplete-item" );
2241
- if ( false !== this._trigger( "focus", event, { item: item } ) ) {
2242
- // use value to match what will end up in the input, if it was a key event
2243
- if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
2244
- this._value( item.value );
2245
- }
2246
- }
2247
-
2248
- // Announce the value in the liveRegion
2249
- label = ui.item.attr( "aria-label" ) || item.value;
2250
- if ( label && $.trim( label ).length ) {
2251
- this.liveRegion.children().hide();
2252
- $( "<div>" ).text( label ).appendTo( this.liveRegion );
2253
- }
2254
- },
2255
- menuselect: function( event, ui ) {
2256
- var item = ui.item.data( "ui-autocomplete-item" ),
2257
- previous = this.previous;
2258
-
2259
- // only trigger when focus was lost (click on menu)
2260
- if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
2261
- this.element.focus();
2262
- this.previous = previous;
2263
- // #6109 - IE triggers two focus events and the second
2264
- // is asynchronous, so we need to reset the previous
2265
- // term synchronously and asynchronously :-(
2266
- this._delay(function() {
2267
- this.previous = previous;
2268
- this.selectedItem = item;
2269
- });
2270
- }
2271
-
2272
- if ( false !== this._trigger( "select", event, { item: item } ) ) {
2273
- this._value( item.value );
2274
- }
2275
- // reset the term after the select event
2276
- // this allows custom select handling to work properly
2277
- this.term = this._value();
2278
-
2279
- this.close( event );
2280
- this.selectedItem = item;
2281
- }
2282
- });
2283
-
2284
- this.liveRegion = $( "<span>", {
2285
- role: "status",
2286
- "aria-live": "assertive",
2287
- "aria-relevant": "additions"
2288
- })
2289
- .addClass( "ui-helper-hidden-accessible" )
2290
- .appendTo( this.document[ 0 ].body );
2291
-
2292
- // turning off autocomplete prevents the browser from remembering the
2293
- // value when navigating through history, so we re-enable autocomplete
2294
- // if the page is unloaded before the widget is destroyed. #7790
2295
- this._on( this.window, {
2296
- beforeunload: function() {
2297
- this.element.removeAttr( "autocomplete" );
2298
- }
2299
- });
2300
- },
2301
-
2302
- _destroy: function() {
2303
- clearTimeout( this.searching );
2304
- this.element
2305
- .removeClass( "ui-autocomplete-input" )
2306
- .removeAttr( "autocomplete" );
2307
- this.menu.element.remove();
2308
- this.liveRegion.remove();
2309
- },
2310
-
2311
- _setOption: function( key, value ) {
2312
- this._super( key, value );
2313
- if ( key === "source" ) {
2314
- this._initSource();
2315
- }
2316
- if ( key === "appendTo" ) {
2317
- this.menu.element.appendTo( this._appendTo() );
2318
- }
2319
- if ( key === "disabled" && value && this.xhr ) {
2320
- this.xhr.abort();
2321
- }
2322
- },
2323
-
2324
- _appendTo: function() {
2325
- var element = this.options.appendTo;
2326
-
2327
- if ( element ) {
2328
- element = element.jquery || element.nodeType ?
2329
- $( element ) :
2330
- this.document.find( element ).eq( 0 );
2331
- }
2332
-
2333
- if ( !element || !element[ 0 ] ) {
2334
- element = this.element.closest( ".ui-front" );
2335
- }
2336
-
2337
- if ( !element.length ) {
2338
- element = this.document[ 0 ].body;
2339
- }
2340
-
2341
- return element;
2342
- },
2343
-
2344
- _initSource: function() {
2345
- var array, url,
2346
- that = this;
2347
- if ( $.isArray( this.options.source ) ) {
2348
- array = this.options.source;
2349
- this.source = function( request, response ) {
2350
- response( $.ui.autocomplete.filter( array, request.term ) );
2351
- };
2352
- } else if ( typeof this.options.source === "string" ) {
2353
- url = this.options.source;
2354
- this.source = function( request, response ) {
2355
- if ( that.xhr ) {
2356
- that.xhr.abort();
2357
- }
2358
- that.xhr = $.ajax({
2359
- url: url,
2360
- data: request,
2361
- dataType: "json",
2362
- success: function( data ) {
2363
- response( data );
2364
- },
2365
- error: function() {
2366
- response([]);
2367
- }
2368
- });
2369
- };
2370
- } else {
2371
- this.source = this.options.source;
2372
- }
2373
- },
2374
-
2375
- _searchTimeout: function( event ) {
2376
- clearTimeout( this.searching );
2377
- this.searching = this._delay(function() {
2378
-
2379
- // Search if the value has changed, or if the user retypes the same value (see #7434)
2380
- var equalValues = this.term === this._value(),
2381
- menuVisible = this.menu.element.is( ":visible" ),
2382
- modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
2383
-
2384
- if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
2385
- this.selectedItem = null;
2386
- this.search( null, event );
2387
- }
2388
- }, this.options.delay );
2389
- },
2390
-
2391
- search: function( value, event ) {
2392
- value = value != null ? value : this._value();
2393
-
2394
- // always save the actual value, not the one passed as an argument
2395
- this.term = this._value();
2396
-
2397
- if ( value.length < this.options.minLength ) {
2398
- return this.close( event );
2399
- }
2400
-
2401
- if ( this._trigger( "search", event ) === false ) {
2402
- return;
2403
- }
2404
-
2405
- return this._search( value );
2406
- },
2407
-
2408
- _search: function( value ) {
2409
- this.pending++;
2410
- this.element.addClass( "ui-autocomplete-loading" );
2411
- this.cancelSearch = false;
2412
-
2413
- this.source( { term: value }, this._response() );
2414
- },
2415
-
2416
- _response: function() {
2417
- var index = ++this.requestIndex;
2418
-
2419
- return $.proxy(function( content ) {
2420
- if ( index === this.requestIndex ) {
2421
- this.__response( content );
2422
- }
2423
-
2424
- this.pending--;
2425
- if ( !this.pending ) {
2426
- this.element.removeClass( "ui-autocomplete-loading" );
2427
- }
2428
- }, this );
2429
- },
2430
-
2431
- __response: function( content ) {
2432
- if ( content ) {
2433
- content = this._normalize( content );
2434
- }
2435
- this._trigger( "response", null, { content: content } );
2436
- if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
2437
- this._suggest( content );
2438
- this._trigger( "open" );
2439
- } else {
2440
- // use ._close() instead of .close() so we don't cancel future searches
2441
- this._close();
2442
- }
2443
- },
2444
-
2445
- close: function( event ) {
2446
- this.cancelSearch = true;
2447
- this._close( event );
2448
- },
2449
-
2450
- _close: function( event ) {
2451
- if ( this.menu.element.is( ":visible" ) ) {
2452
- this.menu.element.hide();
2453
- this.menu.blur();
2454
- this.isNewMenu = true;
2455
- this._trigger( "close", event );
2456
- }
2457
- },
2458
-
2459
- _change: function( event ) {
2460
- if ( this.previous !== this._value() ) {
2461
- this._trigger( "change", event, { item: this.selectedItem } );
2462
- }
2463
- },
2464
-
2465
- _normalize: function( items ) {
2466
- // assume all items have the right format when the first item is complete
2467
- if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
2468
- return items;
2469
- }
2470
- return $.map( items, function( item ) {
2471
- if ( typeof item === "string" ) {
2472
- return {
2473
- label: item,
2474
- value: item
2475
- };
2476
- }
2477
- return $.extend( {}, item, {
2478
- label: item.label || item.value,
2479
- value: item.value || item.label
2480
- });
2481
- });
2482
- },
2483
-
2484
- _suggest: function( items ) {
2485
- var ul = this.menu.element.empty();
2486
- this._renderMenu( ul, items );
2487
- this.isNewMenu = true;
2488
- this.menu.refresh();
2489
-
2490
- // size and position menu
2491
- ul.show();
2492
- this._resizeMenu();
2493
- ul.position( $.extend({
2494
- of: this.element
2495
- }, this.options.position ) );
2496
-
2497
- if ( this.options.autoFocus ) {
2498
- this.menu.next();
2499
- }
2500
- },
2501
-
2502
- _resizeMenu: function() {
2503
- var ul = this.menu.element;
2504
- ul.outerWidth( Math.max(
2505
- // Firefox wraps long text (possibly a rounding bug)
2506
- // so we add 1px to avoid the wrapping (#7513)
2507
- ul.width( "" ).outerWidth() + 1,
2508
- this.element.outerWidth()
2509
- ) );
2510
- },
2511
-
2512
- _renderMenu: function( ul, items ) {
2513
- var that = this;
2514
- $.each( items, function( index, item ) {
2515
- that._renderItemData( ul, item );
2516
- });
2517
- },
2518
-
2519
- _renderItemData: function( ul, item ) {
2520
- return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
2521
- },
2522
-
2523
- _renderItem: function( ul, item ) {
2524
- return $( "<li>" ).text( item.label ).appendTo( ul );
2525
- },
2526
-
2527
- _move: function( direction, event ) {
2528
- if ( !this.menu.element.is( ":visible" ) ) {
2529
- this.search( null, event );
2530
- return;
2531
- }
2532
- if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
2533
- this.menu.isLastItem() && /^next/.test( direction ) ) {
2534
-
2535
- if ( !this.isMultiLine ) {
2536
- this._value( this.term );
2537
- }
2538
-
2539
- this.menu.blur();
2540
- return;
2541
- }
2542
- this.menu[ direction ]( event );
2543
- },
2544
-
2545
- widget: function() {
2546
- return this.menu.element;
2547
- },
2548
-
2549
- _value: function() {
2550
- return this.valueMethod.apply( this.element, arguments );
2551
- },
2552
-
2553
- _keyEvent: function( keyEvent, event ) {
2554
- if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2555
- this._move( keyEvent, event );
2556
-
2557
- // prevents moving cursor to beginning/end of the text field in some browsers
2558
- event.preventDefault();
2559
- }
2560
- }
2561
- });
2562
-
2563
- $.extend( $.ui.autocomplete, {
2564
- escapeRegex: function( value ) {
2565
- return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
2566
- },
2567
- filter: function( array, term ) {
2568
- var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
2569
- return $.grep( array, function( value ) {
2570
- return matcher.test( value.label || value.value || value );
2571
- });
2572
- }
2573
- });
2574
-
2575
- // live region extension, adding a `messages` option
2576
- // NOTE: This is an experimental API. We are still investigating
2577
- // a full solution for string manipulation and internationalization.
2578
- $.widget( "ui.autocomplete", $.ui.autocomplete, {
2579
- options: {
2580
- messages: {
2581
- noResults: "No search results.",
2582
- results: function( amount ) {
2583
- return amount + ( amount > 1 ? " results are" : " result is" ) +
2584
- " available, use up and down arrow keys to navigate.";
2585
- }
2586
- }
2587
- },
2588
-
2589
- __response: function( content ) {
2590
- var message;
2591
- this._superApply( arguments );
2592
- if ( this.options.disabled || this.cancelSearch ) {
2593
- return;
2594
- }
2595
- if ( content && content.length ) {
2596
- message = this.options.messages.results( content.length );
2597
- } else {
2598
- message = this.options.messages.noResults;
2599
- }
2600
- this.liveRegion.children().hide();
2601
- $( "<div>" ).text( message ).appendTo( this.liveRegion );
2602
- }
2603
- });
2604
-
2605
- var autocomplete = $.ui.autocomplete;
2606
-
2607
-
2608
- /*!
2609
- * jQuery UI Datepicker 1.11.2
2610
- * http://jqueryui.com
2611
- *
2612
- * Copyright 2014 jQuery Foundation and other contributors
2613
- * Released under the MIT license.
2614
- * http://jquery.org/license
2615
- *
2616
- * http://api.jqueryui.com/datepicker/
2617
- */
2618
-
2619
-
2620
- $.extend($.ui, { datepicker: { version: "1.11.2" } });
2621
-
2622
- var datepicker_instActive;
2623
-
2624
- function datepicker_getZindex( elem ) {
2625
- var position, value;
2626
- while ( elem.length && elem[ 0 ] !== document ) {
2627
- // Ignore z-index if position is set to a value where z-index is ignored by the browser
2628
- // This makes behavior of this function consistent across browsers
2629
- // WebKit always returns auto if the element is positioned
2630
- position = elem.css( "position" );
2631
- if ( position === "absolute" || position === "relative" || position === "fixed" ) {
2632
- // IE returns 0 when zIndex is not specified
2633
- // other browsers return a string
2634
- // we ignore the case of nested elements with an explicit value of 0
2635
- // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
2636
- value = parseInt( elem.css( "zIndex" ), 10 );
2637
- if ( !isNaN( value ) && value !== 0 ) {
2638
- return value;
2639
- }
2640
- }
2641
- elem = elem.parent();
2642
- }
2643
-
2644
- return 0;
2645
- }
2646
- /* Date picker manager.
2647
- Use the singleton instance of this class, $.datepicker, to interact with the date picker.
2648
- Settings for (groups of) date pickers are maintained in an instance object,
2649
- allowing multiple different settings on the same page. */
2650
-
2651
- function Datepicker() {
2652
- this._curInst = null; // The current instance in use
2653
- this._keyEvent = false; // If the last event was a key event
2654
- this._disabledInputs = []; // List of date picker inputs that have been disabled
2655
- this._datepickerShowing = false; // True if the popup picker is showing , false if not
2656
- this._inDialog = false; // True if showing within a "dialog", false if not
2657
- this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
2658
- this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
2659
- this._appendClass = "ui-datepicker-append"; // The name of the append marker class
2660
- this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
2661
- this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
2662
- this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
2663
- this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
2664
- this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
2665
- this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
2666
- this.regional = []; // Available regional settings, indexed by language code
2667
- this.regional[""] = { // Default regional settings
2668
- closeText: "Done", // Display text for close link
2669
- prevText: "Prev", // Display text for previous month link
2670
- nextText: "Next", // Display text for next month link
2671
- currentText: "Today", // Display text for current month link
2672
- monthNames: ["January","February","March","April","May","June",
2673
- "July","August","September","October","November","December"], // Names of months for drop-down and formatting
2674
- monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
2675
- dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
2676
- dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
2677
- dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
2678
- weekHeader: "Wk", // Column header for week of the year
2679
- dateFormat: "mm/dd/yy", // See format options on parseDate
2680
- firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
2681
- isRTL: false, // True if right-to-left language, false if left-to-right
2682
- showMonthAfterYear: false, // True if the year select precedes month, false for month then year
2683
- yearSuffix: "" // Additional text to append to the year in the month headers
2684
- };
2685
- this._defaults = { // Global defaults for all the date picker instances
2686
- showOn: "focus", // "focus" for popup on focus,
2687
- // "button" for trigger button, or "both" for either
2688
- showAnim: "fadeIn", // Name of jQuery animation for popup
2689
- showOptions: {}, // Options for enhanced animations
2690
- defaultDate: null, // Used when field is blank: actual date,
2691
- // +/-number for offset from today, null for today
2692
- appendText: "", // Display text following the input box, e.g. showing the format
2693
- buttonText: "...", // Text for trigger button
2694
- buttonImage: "", // URL for trigger button image
2695
- buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
2696
- hideIfNoPrevNext: false, // True to hide next/previous month links
2697
- // if not applicable, false to just disable them
2698
- navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
2699
- gotoCurrent: false, // True if today link goes back to current selection instead
2700
- changeMonth: false, // True if month can be selected directly, false if only prev/next
2701
- changeYear: false, // True if year can be selected directly, false if only prev/next
2702
- yearRange: "c-10:c+10", // Range of years to display in drop-down,
2703
- // either relative to today's year (-nn:+nn), relative to currently displayed year
2704
- // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
2705
- showOtherMonths: false, // True to show dates in other months, false to leave blank
2706
- selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
2707
- showWeek: false, // True to show week of the year, false to not show it
2708
- calculateWeek: this.iso8601Week, // How to calculate the week of the year,
2709
- // takes a Date and returns the number of the week for it
2710
- shortYearCutoff: "+10", // Short year values < this are in the current century,
2711
- // > this are in the previous century,
2712
- // string value starting with "+" for current year + value
2713
- minDate: null, // The earliest selectable date, or null for no limit
2714
- maxDate: null, // The latest selectable date, or null for no limit
2715
- duration: "fast", // Duration of display/closure
2716
- beforeShowDay: null, // Function that takes a date and returns an array with
2717
- // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
2718
- // [2] = cell title (optional), e.g. $.datepicker.noWeekends
2719
- beforeShow: null, // Function that takes an input field and
2720
- // returns a set of custom settings for the date picker
2721
- onSelect: null, // Define a callback function when a date is selected
2722
- onChangeMonthYear: null, // Define a callback function when the month or year is changed
2723
- onClose: null, // Define a callback function when the datepicker is closed
2724
- numberOfMonths: 1, // Number of months to show at a time
2725
- showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
2726
- stepMonths: 1, // Number of months to step back/forward
2727
- stepBigMonths: 12, // Number of months to step back/forward for the big links
2728
- altField: "", // Selector for an alternate field to store selected dates into
2729
- altFormat: "", // The date format to use for the alternate field
2730
- constrainInput: true, // The input is constrained by the current date format
2731
- showButtonPanel: false, // True to show button panel, false to not show it
2732
- autoSize: false, // True to size the input for the date format, false to leave as is
2733
- disabled: false // The initial disabled state
2734
- };
2735
- $.extend(this._defaults, this.regional[""]);
2736
- this.regional.en = $.extend( true, {}, this.regional[ "" ]);
2737
- this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
2738
- this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
2739
- }
2740
-
2741
- $.extend(Datepicker.prototype, {
2742
- /* Class name added to elements to indicate already configured with a date picker. */
2743
- markerClassName: "hasDatepicker",
2744
-
2745
- //Keep track of the maximum number of rows displayed (see #7043)
2746
- maxRows: 4,
2747
-
2748
- // TODO rename to "widget" when switching to widget factory
2749
- _widgetDatepicker: function() {
2750
- return this.dpDiv;
2751
- },
2752
-
2753
- /* Override the default settings for all instances of the date picker.
2754
- * @param settings object - the new settings to use as defaults (anonymous object)
2755
- * @return the manager object
2756
- */
2757
- setDefaults: function(settings) {
2758
- datepicker_extendRemove(this._defaults, settings || {});
2759
- return this;
2760
- },
2761
-
2762
- /* Attach the date picker to a jQuery selection.
2763
- * @param target element - the target input field or division or span
2764
- * @param settings object - the new settings to use for this date picker instance (anonymous)
2765
- */
2766
- _attachDatepicker: function(target, settings) {
2767
- var nodeName, inline, inst;
2768
- nodeName = target.nodeName.toLowerCase();
2769
- inline = (nodeName === "div" || nodeName === "span");
2770
- if (!target.id) {
2771
- this.uuid += 1;
2772
- target.id = "dp" + this.uuid;
2773
- }
2774
- inst = this._newInst($(target), inline);
2775
- inst.settings = $.extend({}, settings || {});
2776
- if (nodeName === "input") {
2777
- this._connectDatepicker(target, inst);
2778
- } else if (inline) {
2779
- this._inlineDatepicker(target, inst);
2780
- }
2781
- },
2782
-
2783
- /* Create a new instance object. */
2784
- _newInst: function(target, inline) {
2785
- var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
2786
- return {id: id, input: target, // associated target
2787
- selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
2788
- drawMonth: 0, drawYear: 0, // month being drawn
2789
- inline: inline, // is datepicker inline or not
2790
- dpDiv: (!inline ? this.dpDiv : // presentation div
2791
- datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
2792
- },
2793
-
2794
- /* Attach the date picker to an input field. */
2795
- _connectDatepicker: function(target, inst) {
2796
- var input = $(target);
2797
- inst.append = $([]);
2798
- inst.trigger = $([]);
2799
- if (input.hasClass(this.markerClassName)) {
2800
- return;
2801
- }
2802
- this._attachments(input, inst);
2803
- input.addClass(this.markerClassName).keydown(this._doKeyDown).
2804
- keypress(this._doKeyPress).keyup(this._doKeyUp);
2805
- this._autoSize(inst);
2806
- $.data(target, "datepicker", inst);
2807
- //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
2808
- if( inst.settings.disabled ) {
2809
- this._disableDatepicker( target );
2810
- }
2811
- },
2812
-
2813
- /* Make attachments based on settings. */
2814
- _attachments: function(input, inst) {
2815
- var showOn, buttonText, buttonImage,
2816
- appendText = this._get(inst, "appendText"),
2817
- isRTL = this._get(inst, "isRTL");
2818
-
2819
- if (inst.append) {
2820
- inst.append.remove();
2821
- }
2822
- if (appendText) {
2823
- inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
2824
- input[isRTL ? "before" : "after"](inst.append);
2825
- }
2826
-
2827
- input.unbind("focus", this._showDatepicker);
2828
-
2829
- if (inst.trigger) {
2830
- inst.trigger.remove();
2831
- }
2832
-
2833
- showOn = this._get(inst, "showOn");
2834
- if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
2835
- input.focus(this._showDatepicker);
2836
- }
2837
- if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
2838
- buttonText = this._get(inst, "buttonText");
2839
- buttonImage = this._get(inst, "buttonImage");
2840
- inst.trigger = $(this._get(inst, "buttonImageOnly") ?
2841
- $("<img/>").addClass(this._triggerClass).
2842
- attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
2843
- $("<button type='button'></button>").addClass(this._triggerClass).
2844
- html(!buttonImage ? buttonText : $("<img/>").attr(
2845
- { src:buttonImage, alt:buttonText, title:buttonText })));
2846
- input[isRTL ? "before" : "after"](inst.trigger);
2847
- inst.trigger.click(function() {
2848
- if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
2849
- $.datepicker._hideDatepicker();
2850
- } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
2851
- $.datepicker._hideDatepicker();
2852
- $.datepicker._showDatepicker(input[0]);
2853
- } else {
2854
- $.datepicker._showDatepicker(input[0]);
2855
- }
2856
- return false;
2857
- });
2858
- }
2859
- },
2860
-
2861
- /* Apply the maximum length for the date format. */
2862
- _autoSize: function(inst) {
2863
- if (this._get(inst, "autoSize") && !inst.inline) {
2864
- var findMax, max, maxI, i,
2865
- date = new Date(2009, 12 - 1, 20), // Ensure double digits
2866
- dateFormat = this._get(inst, "dateFormat");
2867
-
2868
- if (dateFormat.match(/[DM]/)) {
2869
- findMax = function(names) {
2870
- max = 0;
2871
- maxI = 0;
2872
- for (i = 0; i < names.length; i++) {
2873
- if (names[i].length > max) {
2874
- max = names[i].length;
2875
- maxI = i;
2876
- }
2877
- }
2878
- return maxI;
2879
- };
2880
- date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
2881
- "monthNames" : "monthNamesShort"))));
2882
- date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
2883
- "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
2884
- }
2885
- inst.input.attr("size", this._formatDate(inst, date).length);
2886
- }
2887
- },
2888
-
2889
- /* Attach an inline date picker to a div. */
2890
- _inlineDatepicker: function(target, inst) {
2891
- var divSpan = $(target);
2892
- if (divSpan.hasClass(this.markerClassName)) {
2893
- return;
2894
- }
2895
- divSpan.addClass(this.markerClassName).append(inst.dpDiv);
2896
- $.data(target, "datepicker", inst);
2897
- this._setDate(inst, this._getDefaultDate(inst), true);
2898
- this._updateDatepicker(inst);
2899
- this._updateAlternate(inst);
2900
- //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
2901
- if( inst.settings.disabled ) {
2902
- this._disableDatepicker( target );
2903
- }
2904
- // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
2905
- // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
2906
- inst.dpDiv.css( "display", "block" );
2907
- },
2908
-
2909
- /* Pop-up the date picker in a "dialog" box.
2910
- * @param input element - ignored
2911
- * @param date string or Date - the initial date to display
2912
- * @param onSelect function - the function to call when a date is selected
2913
- * @param settings object - update the dialog date picker instance's settings (anonymous object)
2914
- * @param pos int[2] - coordinates for the dialog's position within the screen or
2915
- * event - with x/y coordinates or
2916
- * leave empty for default (screen centre)
2917
- * @return the manager object
2918
- */
2919
- _dialogDatepicker: function(input, date, onSelect, settings, pos) {
2920
- var id, browserWidth, browserHeight, scrollX, scrollY,
2921
- inst = this._dialogInst; // internal instance
2922
-
2923
- if (!inst) {
2924
- this.uuid += 1;
2925
- id = "dp" + this.uuid;
2926
- this._dialogInput = $("<input type='text' id='" + id +
2927
- "' style='position: absolute; top: -100px; width: 0px;'/>");
2928
- this._dialogInput.keydown(this._doKeyDown);
2929
- $("body").append(this._dialogInput);
2930
- inst = this._dialogInst = this._newInst(this._dialogInput, false);
2931
- inst.settings = {};
2932
- $.data(this._dialogInput[0], "datepicker", inst);
2933
- }
2934
- datepicker_extendRemove(inst.settings, settings || {});
2935
- date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
2936
- this._dialogInput.val(date);
2937
-
2938
- this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
2939
- if (!this._pos) {
2940
- browserWidth = document.documentElement.clientWidth;
2941
- browserHeight = document.documentElement.clientHeight;
2942
- scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
2943
- scrollY = document.documentElement.scrollTop || document.body.scrollTop;
2944
- this._pos = // should use actual width/height below
2945
- [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
2946
- }
2947
-
2948
- // move input on screen for focus, but hidden behind dialog
2949
- this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
2950
- inst.settings.onSelect = onSelect;
2951
- this._inDialog = true;
2952
- this.dpDiv.addClass(this._dialogClass);
2953
- this._showDatepicker(this._dialogInput[0]);
2954
- if ($.blockUI) {
2955
- $.blockUI(this.dpDiv);
2956
- }
2957
- $.data(this._dialogInput[0], "datepicker", inst);
2958
- return this;
2959
- },
2960
-
2961
- /* Detach a datepicker from its control.
2962
- * @param target element - the target input field or division or span
2963
- */
2964
- _destroyDatepicker: function(target) {
2965
- var nodeName,
2966
- $target = $(target),
2967
- inst = $.data(target, "datepicker");
2968
-
2969
- if (!$target.hasClass(this.markerClassName)) {
2970
- return;
2971
- }
2972
-
2973
- nodeName = target.nodeName.toLowerCase();
2974
- $.removeData(target, "datepicker");
2975
- if (nodeName === "input") {
2976
- inst.append.remove();
2977
- inst.trigger.remove();
2978
- $target.removeClass(this.markerClassName).
2979
- unbind("focus", this._showDatepicker).
2980
- unbind("keydown", this._doKeyDown).
2981
- unbind("keypress", this._doKeyPress).
2982
- unbind("keyup", this._doKeyUp);
2983
- } else if (nodeName === "div" || nodeName === "span") {
2984
- $target.removeClass(this.markerClassName).empty();
2985
- }
2986
- },
2987
-
2988
- /* Enable the date picker to a jQuery selection.
2989
- * @param target element - the target input field or division or span
2990
- */
2991
- _enableDatepicker: function(target) {
2992
- var nodeName, inline,
2993
- $target = $(target),
2994
- inst = $.data(target, "datepicker");
2995
-
2996
- if (!$target.hasClass(this.markerClassName)) {
2997
- return;
2998
- }
2999
-
3000
- nodeName = target.nodeName.toLowerCase();
3001
- if (nodeName === "input") {
3002
- target.disabled = false;
3003
- inst.trigger.filter("button").
3004
- each(function() { this.disabled = false; }).end().
3005
- filter("img").css({opacity: "1.0", cursor: ""});
3006
- } else if (nodeName === "div" || nodeName === "span") {
3007
- inline = $target.children("." + this._inlineClass);
3008
- inline.children().removeClass("ui-state-disabled");
3009
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
3010
- prop("disabled", false);
3011
- }
3012
- this._disabledInputs = $.map(this._disabledInputs,
3013
- function(value) { return (value === target ? null : value); }); // delete entry
3014
- },
3015
-
3016
- /* Disable the date picker to a jQuery selection.
3017
- * @param target element - the target input field or division or span
3018
- */
3019
- _disableDatepicker: function(target) {
3020
- var nodeName, inline,
3021
- $target = $(target),
3022
- inst = $.data(target, "datepicker");
3023
-
3024
- if (!$target.hasClass(this.markerClassName)) {
3025
- return;
3026
- }
3027
-
3028
- nodeName = target.nodeName.toLowerCase();
3029
- if (nodeName === "input") {
3030
- target.disabled = true;
3031
- inst.trigger.filter("button").
3032
- each(function() { this.disabled = true; }).end().
3033
- filter("img").css({opacity: "0.5", cursor: "default"});
3034
- } else if (nodeName === "div" || nodeName === "span") {
3035
- inline = $target.children("." + this._inlineClass);
3036
- inline.children().addClass("ui-state-disabled");
3037
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
3038
- prop("disabled", true);
3039
- }
3040
- this._disabledInputs = $.map(this._disabledInputs,
3041
- function(value) { return (value === target ? null : value); }); // delete entry
3042
- this._disabledInputs[this._disabledInputs.length] = target;
3043
- },
3044
-
3045
- /* Is the first field in a jQuery collection disabled as a datepicker?
3046
- * @param target element - the target input field or division or span
3047
- * @return boolean - true if disabled, false if enabled
3048
- */
3049
- _isDisabledDatepicker: function(target) {
3050
- if (!target) {
3051
- return false;
3052
- }
3053
- for (var i = 0; i < this._disabledInputs.length; i++) {
3054
- if (this._disabledInputs[i] === target) {
3055
- return true;
3056
- }
3057
- }
3058
- return false;
3059
- },
3060
-
3061
- /* Retrieve the instance data for the target control.
3062
- * @param target element - the target input field or division or span
3063
- * @return object - the associated instance data
3064
- * @throws error if a jQuery problem getting data
3065
- */
3066
- _getInst: function(target) {
3067
- try {
3068
- return $.data(target, "datepicker");
3069
- }
3070
- catch (err) {
3071
- throw "Missing instance data for this datepicker";
3072
- }
3073
- },
3074
-
3075
- /* Update or retrieve the settings for a date picker attached to an input field or division.
3076
- * @param target element - the target input field or division or span
3077
- * @param name object - the new settings to update or
3078
- * string - the name of the setting to change or retrieve,
3079
- * when retrieving also "all" for all instance settings or
3080
- * "defaults" for all global defaults
3081
- * @param value any - the new value for the setting
3082
- * (omit if above is an object or to retrieve a value)
3083
- */
3084
- _optionDatepicker: function(target, name, value) {
3085
- var settings, date, minDate, maxDate,
3086
- inst = this._getInst(target);
3087
-
3088
- if (arguments.length === 2 && typeof name === "string") {
3089
- return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
3090
- (inst ? (name === "all" ? $.extend({}, inst.settings) :
3091
- this._get(inst, name)) : null));
3092
- }
3093
-
3094
- settings = name || {};
3095
- if (typeof name === "string") {
3096
- settings = {};
3097
- settings[name] = value;
3098
- }
3099
-
3100
- if (inst) {
3101
- if (this._curInst === inst) {
3102
- this._hideDatepicker();
3103
- }
3104
-
3105
- date = this._getDateDatepicker(target, true);
3106
- minDate = this._getMinMaxDate(inst, "min");
3107
- maxDate = this._getMinMaxDate(inst, "max");
3108
- datepicker_extendRemove(inst.settings, settings);
3109
- // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
3110
- if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
3111
- inst.settings.minDate = this._formatDate(inst, minDate);
3112
- }
3113
- if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
3114
- inst.settings.maxDate = this._formatDate(inst, maxDate);
3115
- }
3116
- if ( "disabled" in settings ) {
3117
- if ( settings.disabled ) {
3118
- this._disableDatepicker(target);
3119
- } else {
3120
- this._enableDatepicker(target);
3121
- }
3122
- }
3123
- this._attachments($(target), inst);
3124
- this._autoSize(inst);
3125
- this._setDate(inst, date);
3126
- this._updateAlternate(inst);
3127
- this._updateDatepicker(inst);
3128
- }
3129
- },
3130
-
3131
- // change method deprecated
3132
- _changeDatepicker: function(target, name, value) {
3133
- this._optionDatepicker(target, name, value);
3134
- },
3135
-
3136
- /* Redraw the date picker attached to an input field or division.
3137
- * @param target element - the target input field or division or span
3138
- */
3139
- _refreshDatepicker: function(target) {
3140
- var inst = this._getInst(target);
3141
- if (inst) {
3142
- this._updateDatepicker(inst);
3143
- }
3144
- },
3145
-
3146
- /* Set the dates for a jQuery selection.
3147
- * @param target element - the target input field or division or span
3148
- * @param date Date - the new date
3149
- */
3150
- _setDateDatepicker: function(target, date) {
3151
- var inst = this._getInst(target);
3152
- if (inst) {
3153
- this._setDate(inst, date);
3154
- this._updateDatepicker(inst);
3155
- this._updateAlternate(inst);
3156
- }
3157
- },
3158
-
3159
- /* Get the date(s) for the first entry in a jQuery selection.
3160
- * @param target element - the target input field or division or span
3161
- * @param noDefault boolean - true if no default date is to be used
3162
- * @return Date - the current date
3163
- */
3164
- _getDateDatepicker: function(target, noDefault) {
3165
- var inst = this._getInst(target);
3166
- if (inst && !inst.inline) {
3167
- this._setDateFromField(inst, noDefault);
3168
- }
3169
- return (inst ? this._getDate(inst) : null);
3170
- },
3171
-
3172
- /* Handle keystrokes. */
3173
- _doKeyDown: function(event) {
3174
- var onSelect, dateStr, sel,
3175
- inst = $.datepicker._getInst(event.target),
3176
- handled = true,
3177
- isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
3178
-
3179
- inst._keyEvent = true;
3180
- if ($.datepicker._datepickerShowing) {
3181
- switch (event.keyCode) {
3182
- case 9: $.datepicker._hideDatepicker();
3183
- handled = false;
3184
- break; // hide on tab out
3185
- case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
3186
- $.datepicker._currentClass + ")", inst.dpDiv);
3187
- if (sel[0]) {
3188
- $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
3189
- }
3190
-
3191
- onSelect = $.datepicker._get(inst, "onSelect");
3192
- if (onSelect) {
3193
- dateStr = $.datepicker._formatDate(inst);
3194
-
3195
- // trigger custom callback
3196
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
3197
- } else {
3198
- $.datepicker._hideDatepicker();
3199
- }
3200
-
3201
- return false; // don't submit the form
3202
- case 27: $.datepicker._hideDatepicker();
3203
- break; // hide on escape
3204
- case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
3205
- -$.datepicker._get(inst, "stepBigMonths") :
3206
- -$.datepicker._get(inst, "stepMonths")), "M");
3207
- break; // previous month/year on page up/+ ctrl
3208
- case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
3209
- +$.datepicker._get(inst, "stepBigMonths") :
3210
- +$.datepicker._get(inst, "stepMonths")), "M");
3211
- break; // next month/year on page down/+ ctrl
3212
- case 35: if (event.ctrlKey || event.metaKey) {
3213
- $.datepicker._clearDate(event.target);
3214
- }
3215
- handled = event.ctrlKey || event.metaKey;
3216
- break; // clear on ctrl or command +end
3217
- case 36: if (event.ctrlKey || event.metaKey) {
3218
- $.datepicker._gotoToday(event.target);
3219
- }
3220
- handled = event.ctrlKey || event.metaKey;
3221
- break; // current on ctrl or command +home
3222
- case 37: if (event.ctrlKey || event.metaKey) {
3223
- $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
3224
- }
3225
- handled = event.ctrlKey || event.metaKey;
3226
- // -1 day on ctrl or command +left
3227
- if (event.originalEvent.altKey) {
3228
- $.datepicker._adjustDate(event.target, (event.ctrlKey ?
3229
- -$.datepicker._get(inst, "stepBigMonths") :
3230
- -$.datepicker._get(inst, "stepMonths")), "M");
3231
- }
3232
- // next month/year on alt +left on Mac
3233
- break;
3234
- case 38: if (event.ctrlKey || event.metaKey) {
3235
- $.datepicker._adjustDate(event.target, -7, "D");
3236
- }
3237
- handled = event.ctrlKey || event.metaKey;
3238
- break; // -1 week on ctrl or command +up
3239
- case 39: if (event.ctrlKey || event.metaKey) {
3240
- $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
3241
- }
3242
- handled = event.ctrlKey || event.metaKey;
3243
- // +1 day on ctrl or command +right
3244
- if (event.originalEvent.altKey) {
3245
- $.datepicker._adjustDate(event.target, (event.ctrlKey ?
3246
- +$.datepicker._get(inst, "stepBigMonths") :
3247
- +$.datepicker._get(inst, "stepMonths")), "M");
3248
- }
3249
- // next month/year on alt +right
3250
- break;
3251
- case 40: if (event.ctrlKey || event.metaKey) {
3252
- $.datepicker._adjustDate(event.target, +7, "D");
3253
- }
3254
- handled = event.ctrlKey || event.metaKey;
3255
- break; // +1 week on ctrl or command +down
3256
- default: handled = false;
3257
- }
3258
- } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
3259
- $.datepicker._showDatepicker(this);
3260
- } else {
3261
- handled = false;
3262
- }
3263
-
3264
- if (handled) {
3265
- event.preventDefault();
3266
- event.stopPropagation();
3267
- }
3268
- },
3269
-
3270
- /* Filter entered characters - based on date format. */
3271
- _doKeyPress: function(event) {
3272
- var chars, chr,
3273
- inst = $.datepicker._getInst(event.target);
3274
-
3275
- if ($.datepicker._get(inst, "constrainInput")) {
3276
- chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
3277
- chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
3278
- return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
3279
- }
3280
- },
3281
-
3282
- /* Synchronise manual entry and field/alternate field. */
3283
- _doKeyUp: function(event) {
3284
- var date,
3285
- inst = $.datepicker._getInst(event.target);
3286
-
3287
- if (inst.input.val() !== inst.lastVal) {
3288
- try {
3289
- date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
3290
- (inst.input ? inst.input.val() : null),
3291
- $.datepicker._getFormatConfig(inst));
3292
-
3293
- if (date) { // only if valid
3294
- $.datepicker._setDateFromField(inst);
3295
- $.datepicker._updateAlternate(inst);
3296
- $.datepicker._updateDatepicker(inst);
3297
- }
3298
- }
3299
- catch (err) {
3300
- }
3301
- }
3302
- return true;
3303
- },
3304
-
3305
- /* Pop-up the date picker for a given input field.
3306
- * If false returned from beforeShow event handler do not show.
3307
- * @param input element - the input field attached to the date picker or
3308
- * event - if triggered by focus
3309
- */
3310
- _showDatepicker: function(input) {
3311
- input = input.target || input;
3312
- if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
3313
- input = $("input", input.parentNode)[0];
3314
- }
3315
-
3316
- if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
3317
- return;
3318
- }
3319
-
3320
- var inst, beforeShow, beforeShowSettings, isFixed,
3321
- offset, showAnim, duration;
3322
-
3323
- inst = $.datepicker._getInst(input);
3324
- if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
3325
- $.datepicker._curInst.dpDiv.stop(true, true);
3326
- if ( inst && $.datepicker._datepickerShowing ) {
3327
- $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
3328
- }
3329
- }
3330
-
3331
- beforeShow = $.datepicker._get(inst, "beforeShow");
3332
- beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
3333
- if(beforeShowSettings === false){
3334
- return;
3335
- }
3336
- datepicker_extendRemove(inst.settings, beforeShowSettings);
3337
-
3338
- inst.lastVal = null;
3339
- $.datepicker._lastInput = input;
3340
- $.datepicker._setDateFromField(inst);
3341
-
3342
- if ($.datepicker._inDialog) { // hide cursor
3343
- input.value = "";
3344
- }
3345
- if (!$.datepicker._pos) { // position below input
3346
- $.datepicker._pos = $.datepicker._findPos(input);
3347
- $.datepicker._pos[1] += input.offsetHeight; // add the height
3348
- }
3349
-
3350
- isFixed = false;
3351
- $(input).parents().each(function() {
3352
- isFixed |= $(this).css("position") === "fixed";
3353
- return !isFixed;
3354
- });
3355
-
3356
- offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
3357
- $.datepicker._pos = null;
3358
- //to avoid flashes on Firefox
3359
- inst.dpDiv.empty();
3360
- // determine sizing offscreen
3361
- inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
3362
- $.datepicker._updateDatepicker(inst);
3363
- // fix width for dynamic number of date pickers
3364
- // and adjust position before showing
3365
- offset = $.datepicker._checkOffset(inst, offset, isFixed);
3366
- inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
3367
- "static" : (isFixed ? "fixed" : "absolute")), display: "none",
3368
- left: offset.left + "px", top: offset.top + "px"});
3369
-
3370
- if (!inst.inline) {
3371
- showAnim = $.datepicker._get(inst, "showAnim");
3372
- duration = $.datepicker._get(inst, "duration");
3373
- inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
3374
- $.datepicker._datepickerShowing = true;
3375
-
3376
- if ( $.effects && $.effects.effect[ showAnim ] ) {
3377
- inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
3378
- } else {
3379
- inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
3380
- }
3381
-
3382
- if ( $.datepicker._shouldFocusInput( inst ) ) {
3383
- inst.input.focus();
3384
- }
3385
-
3386
- $.datepicker._curInst = inst;
3387
- }
3388
- },
3389
-
3390
- /* Generate the date picker content. */
3391
- _updateDatepicker: function(inst) {
3392
- this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
3393
- datepicker_instActive = inst; // for delegate hover events
3394
- inst.dpDiv.empty().append(this._generateHTML(inst));
3395
- this._attachHandlers(inst);
3396
-
3397
- var origyearshtml,
3398
- numMonths = this._getNumberOfMonths(inst),
3399
- cols = numMonths[1],
3400
- width = 17,
3401
- activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
3402
-
3403
- if ( activeCell.length > 0 ) {
3404
- datepicker_handleMouseover.apply( activeCell.get( 0 ) );
3405
- }
3406
-
3407
- inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
3408
- if (cols > 1) {
3409
- inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
3410
- }
3411
- inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
3412
- "Class"]("ui-datepicker-multi");
3413
- inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
3414
- "Class"]("ui-datepicker-rtl");
3415
-
3416
- if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
3417
- inst.input.focus();
3418
- }
3419
-
3420
- // deffered render of the years select (to avoid flashes on Firefox)
3421
- if( inst.yearshtml ){
3422
- origyearshtml = inst.yearshtml;
3423
- setTimeout(function(){
3424
- //assure that inst.yearshtml didn't change.
3425
- if( origyearshtml === inst.yearshtml && inst.yearshtml ){
3426
- inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
3427
- }
3428
- origyearshtml = inst.yearshtml = null;
3429
- }, 0);
3430
- }
3431
- },
3432
-
3433
- // #6694 - don't focus the input if it's already focused
3434
- // this breaks the change event in IE
3435
- // Support: IE and jQuery <1.9
3436
- _shouldFocusInput: function( inst ) {
3437
- return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
3438
- },
3439
-
3440
- /* Check positioning to remain on screen. */
3441
- _checkOffset: function(inst, offset, isFixed) {
3442
- var dpWidth = inst.dpDiv.outerWidth(),
3443
- dpHeight = inst.dpDiv.outerHeight(),
3444
- inputWidth = inst.input ? inst.input.outerWidth() : 0,
3445
- inputHeight = inst.input ? inst.input.outerHeight() : 0,
3446
- viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
3447
- viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
3448
-
3449
- offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
3450
- offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
3451
- offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
3452
-
3453
- // now check if datepicker is showing outside window viewport - move to a better place if so.
3454
- offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
3455
- Math.abs(offset.left + dpWidth - viewWidth) : 0);
3456
- offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
3457
- Math.abs(dpHeight + inputHeight) : 0);
3458
-
3459
- return offset;
3460
- },
3461
-
3462
- /* Find an object's position on the screen. */
3463
- _findPos: function(obj) {
3464
- var position,
3465
- inst = this._getInst(obj),
3466
- isRTL = this._get(inst, "isRTL");
3467
-
3468
- while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
3469
- obj = obj[isRTL ? "previousSibling" : "nextSibling"];
3470
- }
3471
-
3472
- position = $(obj).offset();
3473
- return [position.left, position.top];
3474
- },
3475
-
3476
- /* Hide the date picker from view.
3477
- * @param input element - the input field attached to the date picker
3478
- */
3479
- _hideDatepicker: function(input) {
3480
- var showAnim, duration, postProcess, onClose,
3481
- inst = this._curInst;
3482
-
3483
- if (!inst || (input && inst !== $.data(input, "datepicker"))) {
3484
- return;
3485
- }
3486
-
3487
- if (this._datepickerShowing) {
3488
- showAnim = this._get(inst, "showAnim");
3489
- duration = this._get(inst, "duration");
3490
- postProcess = function() {
3491
- $.datepicker._tidyDialog(inst);
3492
- };
3493
-
3494
- // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
3495
- if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
3496
- inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
3497
- } else {
3498
- inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
3499
- (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
3500
- }
3501
-
3502
- if (!showAnim) {
3503
- postProcess();
3504
- }
3505
- this._datepickerShowing = false;
3506
-
3507
- onClose = this._get(inst, "onClose");
3508
- if (onClose) {
3509
- onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
3510
- }
3511
-
3512
- this._lastInput = null;
3513
- if (this._inDialog) {
3514
- this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
3515
- if ($.blockUI) {
3516
- $.unblockUI();
3517
- $("body").append(this.dpDiv);
3518
- }
3519
- }
3520
- this._inDialog = false;
3521
- }
3522
- },
3523
-
3524
- /* Tidy up after a dialog display. */
3525
- _tidyDialog: function(inst) {
3526
- inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
3527
- },
3528
-
3529
- /* Close date picker if clicked elsewhere. */
3530
- _checkExternalClick: function(event) {
3531
- if (!$.datepicker._curInst) {
3532
- return;
3533
- }
3534
-
3535
- var $target = $(event.target),
3536
- inst = $.datepicker._getInst($target[0]);
3537
-
3538
- if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
3539
- $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
3540
- !$target.hasClass($.datepicker.markerClassName) &&
3541
- !$target.closest("." + $.datepicker._triggerClass).length &&
3542
- $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
3543
- ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
3544
- $.datepicker._hideDatepicker();
3545
- }
3546
- },
3547
-
3548
- /* Adjust one of the date sub-fields. */
3549
- _adjustDate: function(id, offset, period) {
3550
- var target = $(id),
3551
- inst = this._getInst(target[0]);
3552
-
3553
- if (this._isDisabledDatepicker(target[0])) {
3554
- return;
3555
- }
3556
- this._adjustInstDate(inst, offset +
3557
- (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
3558
- period);
3559
- this._updateDatepicker(inst);
3560
- },
3561
-
3562
- /* Action for current link. */
3563
- _gotoToday: function(id) {
3564
- var date,
3565
- target = $(id),
3566
- inst = this._getInst(target[0]);
3567
-
3568
- if (this._get(inst, "gotoCurrent") && inst.currentDay) {
3569
- inst.selectedDay = inst.currentDay;
3570
- inst.drawMonth = inst.selectedMonth = inst.currentMonth;
3571
- inst.drawYear = inst.selectedYear = inst.currentYear;
3572
- } else {
3573
- date = new Date();
3574
- inst.selectedDay = date.getDate();
3575
- inst.drawMonth = inst.selectedMonth = date.getMonth();
3576
- inst.drawYear = inst.selectedYear = date.getFullYear();
3577
- }
3578
- this._notifyChange(inst);
3579
- this._adjustDate(target);
3580
- },
3581
-
3582
- /* Action for selecting a new month/year. */
3583
- _selectMonthYear: function(id, select, period) {
3584
- var target = $(id),
3585
- inst = this._getInst(target[0]);
3586
-
3587
- inst["selected" + (period === "M" ? "Month" : "Year")] =
3588
- inst["draw" + (period === "M" ? "Month" : "Year")] =
3589
- parseInt(select.options[select.selectedIndex].value,10);
3590
-
3591
- this._notifyChange(inst);
3592
- this._adjustDate(target);
3593
- },
3594
-
3595
- /* Action for selecting a day. */
3596
- _selectDay: function(id, month, year, td) {
3597
- var inst,
3598
- target = $(id);
3599
-
3600
- if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
3601
- return;
3602
- }
3603
-
3604
- inst = this._getInst(target[0]);
3605
- inst.selectedDay = inst.currentDay = $("a", td).html();
3606
- inst.selectedMonth = inst.currentMonth = month;
3607
- inst.selectedYear = inst.currentYear = year;
3608
- this._selectDate(id, this._formatDate(inst,
3609
- inst.currentDay, inst.currentMonth, inst.currentYear));
3610
- },
3611
-
3612
- /* Erase the input field and hide the date picker. */
3613
- _clearDate: function(id) {
3614
- var target = $(id);
3615
- this._selectDate(target, "");
3616
- },
3617
-
3618
- /* Update the input field with the selected date. */
3619
- _selectDate: function(id, dateStr) {
3620
- var onSelect,
3621
- target = $(id),
3622
- inst = this._getInst(target[0]);
3623
-
3624
- dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
3625
- if (inst.input) {
3626
- inst.input.val(dateStr);
3627
- }
3628
- this._updateAlternate(inst);
3629
-
3630
- onSelect = this._get(inst, "onSelect");
3631
- if (onSelect) {
3632
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
3633
- } else if (inst.input) {
3634
- inst.input.trigger("change"); // fire the change event
3635
- }
3636
-
3637
- if (inst.inline){
3638
- this._updateDatepicker(inst);
3639
- } else {
3640
- this._hideDatepicker();
3641
- this._lastInput = inst.input[0];
3642
- if (typeof(inst.input[0]) !== "object") {
3643
- inst.input.focus(); // restore focus
3644
- }
3645
- this._lastInput = null;
3646
- }
3647
- },
3648
-
3649
- /* Update any alternate field to synchronise with the main field. */
3650
- _updateAlternate: function(inst) {
3651
- var altFormat, date, dateStr,
3652
- altField = this._get(inst, "altField");
3653
-
3654
- if (altField) { // update alternate field too
3655
- altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
3656
- date = this._getDate(inst);
3657
- dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
3658
- $(altField).each(function() { $(this).val(dateStr); });
3659
- }
3660
- },
3661
-
3662
- /* Set as beforeShowDay function to prevent selection of weekends.
3663
- * @param date Date - the date to customise
3664
- * @return [boolean, string] - is this date selectable?, what is its CSS class?
3665
- */
3666
- noWeekends: function(date) {
3667
- var day = date.getDay();
3668
- return [(day > 0 && day < 6), ""];
3669
- },
3670
-
3671
- /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
3672
- * @param date Date - the date to get the week for
3673
- * @return number - the number of the week within the year that contains this date
3674
- */
3675
- iso8601Week: function(date) {
3676
- var time,
3677
- checkDate = new Date(date.getTime());
3678
-
3679
- // Find Thursday of this week starting on Monday
3680
- checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
3681
-
3682
- time = checkDate.getTime();
3683
- checkDate.setMonth(0); // Compare with Jan 1
3684
- checkDate.setDate(1);
3685
- return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
3686
- },
3687
-
3688
- /* Parse a string value into a date object.
3689
- * See formatDate below for the possible formats.
3690
- *
3691
- * @param format string - the expected format of the date
3692
- * @param value string - the date in the above format
3693
- * @param settings Object - attributes include:
3694
- * shortYearCutoff number - the cutoff year for determining the century (optional)
3695
- * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
3696
- * dayNames string[7] - names of the days from Sunday (optional)
3697
- * monthNamesShort string[12] - abbreviated names of the months (optional)
3698
- * monthNames string[12] - names of the months (optional)
3699
- * @return Date - the extracted date value or null if value is blank
3700
- */
3701
- parseDate: function (format, value, settings) {
3702
- if (format == null || value == null) {
3703
- throw "Invalid arguments";
3704
- }
3705
-
3706
- value = (typeof value === "object" ? value.toString() : value + "");
3707
- if (value === "") {
3708
- return null;
3709
- }
3710
-
3711
- var iFormat, dim, extra,
3712
- iValue = 0,
3713
- shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
3714
- shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
3715
- new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
3716
- dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
3717
- dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
3718
- monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
3719
- monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
3720
- year = -1,
3721
- month = -1,
3722
- day = -1,
3723
- doy = -1,
3724
- literal = false,
3725
- date,
3726
- // Check whether a format character is doubled
3727
- lookAhead = function(match) {
3728
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
3729
- if (matches) {
3730
- iFormat++;
3731
- }
3732
- return matches;
3733
- },
3734
- // Extract a number from the string value
3735
- getNumber = function(match) {
3736
- var isDoubled = lookAhead(match),
3737
- size = (match === "@" ? 14 : (match === "!" ? 20 :
3738
- (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
3739
- minSize = (match === "y" ? size : 1),
3740
- digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
3741
- num = value.substring(iValue).match(digits);
3742
- if (!num) {
3743
- throw "Missing number at position " + iValue;
3744
- }
3745
- iValue += num[0].length;
3746
- return parseInt(num[0], 10);
3747
- },
3748
- // Extract a name from the string value and convert to an index
3749
- getName = function(match, shortNames, longNames) {
3750
- var index = -1,
3751
- names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
3752
- return [ [k, v] ];
3753
- }).sort(function (a, b) {
3754
- return -(a[1].length - b[1].length);
3755
- });
3756
-
3757
- $.each(names, function (i, pair) {
3758
- var name = pair[1];
3759
- if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
3760
- index = pair[0];
3761
- iValue += name.length;
3762
- return false;
3763
- }
3764
- });
3765
- if (index !== -1) {
3766
- return index + 1;
3767
- } else {
3768
- throw "Unknown name at position " + iValue;
3769
- }
3770
- },
3771
- // Confirm that a literal character matches the string value
3772
- checkLiteral = function() {
3773
- if (value.charAt(iValue) !== format.charAt(iFormat)) {
3774
- throw "Unexpected literal at position " + iValue;
3775
- }
3776
- iValue++;
3777
- };
3778
-
3779
- for (iFormat = 0; iFormat < format.length; iFormat++) {
3780
- if (literal) {
3781
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
3782
- literal = false;
3783
- } else {
3784
- checkLiteral();
3785
- }
3786
- } else {
3787
- switch (format.charAt(iFormat)) {
3788
- case "d":
3789
- day = getNumber("d");
3790
- break;
3791
- case "D":
3792
- getName("D", dayNamesShort, dayNames);
3793
- break;
3794
- case "o":
3795
- doy = getNumber("o");
3796
- break;
3797
- case "m":
3798
- month = getNumber("m");
3799
- break;
3800
- case "M":
3801
- month = getName("M", monthNamesShort, monthNames);
3802
- break;
3803
- case "y":
3804
- year = getNumber("y");
3805
- break;
3806
- case "@":
3807
- date = new Date(getNumber("@"));
3808
- year = date.getFullYear();
3809
- month = date.getMonth() + 1;
3810
- day = date.getDate();
3811
- break;
3812
- case "!":
3813
- date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
3814
- year = date.getFullYear();
3815
- month = date.getMonth() + 1;
3816
- day = date.getDate();
3817
- break;
3818
- case "'":
3819
- if (lookAhead("'")){
3820
- checkLiteral();
3821
- } else {
3822
- literal = true;
3823
- }
3824
- break;
3825
- default:
3826
- checkLiteral();
3827
- }
3828
- }
3829
- }
3830
-
3831
- if (iValue < value.length){
3832
- extra = value.substr(iValue);
3833
- if (!/^\s+/.test(extra)) {
3834
- throw "Extra/unparsed characters found in date: " + extra;
3835
- }
3836
- }
3837
-
3838
- if (year === -1) {
3839
- year = new Date().getFullYear();
3840
- } else if (year < 100) {
3841
- year += new Date().getFullYear() - new Date().getFullYear() % 100 +
3842
- (year <= shortYearCutoff ? 0 : -100);
3843
- }
3844
-
3845
- if (doy > -1) {
3846
- month = 1;
3847
- day = doy;
3848
- do {
3849
- dim = this._getDaysInMonth(year, month - 1);
3850
- if (day <= dim) {
3851
- break;
3852
- }
3853
- month++;
3854
- day -= dim;
3855
- } while (true);
3856
- }
3857
-
3858
- date = this._daylightSavingAdjust(new Date(year, month - 1, day));
3859
- if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
3860
- throw "Invalid date"; // E.g. 31/02/00
3861
- }
3862
- return date;
3863
- },
3864
-
3865
- /* Standard date formats. */
3866
- ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
3867
- COOKIE: "D, dd M yy",
3868
- ISO_8601: "yy-mm-dd",
3869
- RFC_822: "D, d M y",
3870
- RFC_850: "DD, dd-M-y",
3871
- RFC_1036: "D, d M y",
3872
- RFC_1123: "D, d M yy",
3873
- RFC_2822: "D, d M yy",
3874
- RSS: "D, d M y", // RFC 822
3875
- TICKS: "!",
3876
- TIMESTAMP: "@",
3877
- W3C: "yy-mm-dd", // ISO 8601
3878
-
3879
- _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
3880
- Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
3881
-
3882
- /* Format a date object into a string value.
3883
- * The format can be combinations of the following:
3884
- * d - day of month (no leading zero)
3885
- * dd - day of month (two digit)
3886
- * o - day of year (no leading zeros)
3887
- * oo - day of year (three digit)
3888
- * D - day name short
3889
- * DD - day name long
3890
- * m - month of year (no leading zero)
3891
- * mm - month of year (two digit)
3892
- * M - month name short
3893
- * MM - month name long
3894
- * y - year (two digit)
3895
- * yy - year (four digit)
3896
- * @ - Unix timestamp (ms since 01/01/1970)
3897
- * ! - Windows ticks (100ns since 01/01/0001)
3898
- * "..." - literal text
3899
- * '' - single quote
3900
- *
3901
- * @param format string - the desired format of the date
3902
- * @param date Date - the date value to format
3903
- * @param settings Object - attributes include:
3904
- * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
3905
- * dayNames string[7] - names of the days from Sunday (optional)
3906
- * monthNamesShort string[12] - abbreviated names of the months (optional)
3907
- * monthNames string[12] - names of the months (optional)
3908
- * @return string - the date in the above format
3909
- */
3910
- formatDate: function (format, date, settings) {
3911
- if (!date) {
3912
- return "";
3913
- }
3914
-
3915
- var iFormat,
3916
- dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
3917
- dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
3918
- monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
3919
- monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
3920
- // Check whether a format character is doubled
3921
- lookAhead = function(match) {
3922
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
3923
- if (matches) {
3924
- iFormat++;
3925
- }
3926
- return matches;
3927
- },
3928
- // Format a number, with leading zero if necessary
3929
- formatNumber = function(match, value, len) {
3930
- var num = "" + value;
3931
- if (lookAhead(match)) {
3932
- while (num.length < len) {
3933
- num = "0" + num;
3934
- }
3935
- }
3936
- return num;
3937
- },
3938
- // Format a name, short or long as requested
3939
- formatName = function(match, value, shortNames, longNames) {
3940
- return (lookAhead(match) ? longNames[value] : shortNames[value]);
3941
- },
3942
- output = "",
3943
- literal = false;
3944
-
3945
- if (date) {
3946
- for (iFormat = 0; iFormat < format.length; iFormat++) {
3947
- if (literal) {
3948
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
3949
- literal = false;
3950
- } else {
3951
- output += format.charAt(iFormat);
3952
- }
3953
- } else {
3954
- switch (format.charAt(iFormat)) {
3955
- case "d":
3956
- output += formatNumber("d", date.getDate(), 2);
3957
- break;
3958
- case "D":
3959
- output += formatName("D", date.getDay(), dayNamesShort, dayNames);
3960
- break;
3961
- case "o":
3962
- output += formatNumber("o",
3963
- Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
3964
- break;
3965
- case "m":
3966
- output += formatNumber("m", date.getMonth() + 1, 2);
3967
- break;
3968
- case "M":
3969
- output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
3970
- break;
3971
- case "y":
3972
- output += (lookAhead("y") ? date.getFullYear() :
3973
- (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
3974
- break;
3975
- case "@":
3976
- output += date.getTime();
3977
- break;
3978
- case "!":
3979
- output += date.getTime() * 10000 + this._ticksTo1970;
3980
- break;
3981
- case "'":
3982
- if (lookAhead("'")) {
3983
- output += "'";
3984
- } else {
3985
- literal = true;
3986
- }
3987
- break;
3988
- default:
3989
- output += format.charAt(iFormat);
3990
- }
3991
- }
3992
- }
3993
- }
3994
- return output;
3995
- },
3996
-
3997
- /* Extract all possible characters from the date format. */
3998
- _possibleChars: function (format) {
3999
- var iFormat,
4000
- chars = "",
4001
- literal = false,
4002
- // Check whether a format character is doubled
4003
- lookAhead = function(match) {
4004
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
4005
- if (matches) {
4006
- iFormat++;
4007
- }
4008
- return matches;
4009
- };
4010
-
4011
- for (iFormat = 0; iFormat < format.length; iFormat++) {
4012
- if (literal) {
4013
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
4014
- literal = false;
4015
- } else {
4016
- chars += format.charAt(iFormat);
4017
- }
4018
- } else {
4019
- switch (format.charAt(iFormat)) {
4020
- case "d": case "m": case "y": case "@":
4021
- chars += "0123456789";
4022
- break;
4023
- case "D": case "M":
4024
- return null; // Accept anything
4025
- case "'":
4026
- if (lookAhead("'")) {
4027
- chars += "'";
4028
- } else {
4029
- literal = true;
4030
- }
4031
- break;
4032
- default:
4033
- chars += format.charAt(iFormat);
4034
- }
4035
- }
4036
- }
4037
- return chars;
4038
- },
4039
-
4040
- /* Get a setting value, defaulting if necessary. */
4041
- _get: function(inst, name) {
4042
- return inst.settings[name] !== undefined ?
4043
- inst.settings[name] : this._defaults[name];
4044
- },
4045
-
4046
- /* Parse existing date and initialise date picker. */
4047
- _setDateFromField: function(inst, noDefault) {
4048
- if (inst.input.val() === inst.lastVal) {
4049
- return;
4050
- }
4051
-
4052
- var dateFormat = this._get(inst, "dateFormat"),
4053
- dates = inst.lastVal = inst.input ? inst.input.val() : null,
4054
- defaultDate = this._getDefaultDate(inst),
4055
- date = defaultDate,
4056
- settings = this._getFormatConfig(inst);
4057
-
4058
- try {
4059
- date = this.parseDate(dateFormat, dates, settings) || defaultDate;
4060
- } catch (event) {
4061
- dates = (noDefault ? "" : dates);
4062
- }
4063
- inst.selectedDay = date.getDate();
4064
- inst.drawMonth = inst.selectedMonth = date.getMonth();
4065
- inst.drawYear = inst.selectedYear = date.getFullYear();
4066
- inst.currentDay = (dates ? date.getDate() : 0);
4067
- inst.currentMonth = (dates ? date.getMonth() : 0);
4068
- inst.currentYear = (dates ? date.getFullYear() : 0);
4069
- this._adjustInstDate(inst);
4070
- },
4071
-
4072
- /* Retrieve the default date shown on opening. */
4073
- _getDefaultDate: function(inst) {
4074
- return this._restrictMinMax(inst,
4075
- this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
4076
- },
4077
-
4078
- /* A date may be specified as an exact value or a relative one. */
4079
- _determineDate: function(inst, date, defaultDate) {
4080
- var offsetNumeric = function(offset) {
4081
- var date = new Date();
4082
- date.setDate(date.getDate() + offset);
4083
- return date;
4084
- },
4085
- offsetString = function(offset) {
4086
- try {
4087
- return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
4088
- offset, $.datepicker._getFormatConfig(inst));
4089
- }
4090
- catch (e) {
4091
- // Ignore
4092
- }
4093
-
4094
- var date = (offset.toLowerCase().match(/^c/) ?
4095
- $.datepicker._getDate(inst) : null) || new Date(),
4096
- year = date.getFullYear(),
4097
- month = date.getMonth(),
4098
- day = date.getDate(),
4099
- pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
4100
- matches = pattern.exec(offset);
4101
-
4102
- while (matches) {
4103
- switch (matches[2] || "d") {
4104
- case "d" : case "D" :
4105
- day += parseInt(matches[1],10); break;
4106
- case "w" : case "W" :
4107
- day += parseInt(matches[1],10) * 7; break;
4108
- case "m" : case "M" :
4109
- month += parseInt(matches[1],10);
4110
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
4111
- break;
4112
- case "y": case "Y" :
4113
- year += parseInt(matches[1],10);
4114
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
4115
- break;
4116
- }
4117
- matches = pattern.exec(offset);
4118
- }
4119
- return new Date(year, month, day);
4120
- },
4121
- newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
4122
- (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
4123
-
4124
- newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
4125
- if (newDate) {
4126
- newDate.setHours(0);
4127
- newDate.setMinutes(0);
4128
- newDate.setSeconds(0);
4129
- newDate.setMilliseconds(0);
4130
- }
4131
- return this._daylightSavingAdjust(newDate);
4132
- },
4133
-
4134
- /* Handle switch to/from daylight saving.
4135
- * Hours may be non-zero on daylight saving cut-over:
4136
- * > 12 when midnight changeover, but then cannot generate
4137
- * midnight datetime, so jump to 1AM, otherwise reset.
4138
- * @param date (Date) the date to check
4139
- * @return (Date) the corrected date
4140
- */
4141
- _daylightSavingAdjust: function(date) {
4142
- if (!date) {
4143
- return null;
4144
- }
4145
- date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
4146
- return date;
4147
- },
4148
-
4149
- /* Set the date(s) directly. */
4150
- _setDate: function(inst, date, noChange) {
4151
- var clear = !date,
4152
- origMonth = inst.selectedMonth,
4153
- origYear = inst.selectedYear,
4154
- newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
4155
-
4156
- inst.selectedDay = inst.currentDay = newDate.getDate();
4157
- inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
4158
- inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
4159
- if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
4160
- this._notifyChange(inst);
4161
- }
4162
- this._adjustInstDate(inst);
4163
- if (inst.input) {
4164
- inst.input.val(clear ? "" : this._formatDate(inst));
4165
- }
4166
- },
4167
-
4168
- /* Retrieve the date(s) directly. */
4169
- _getDate: function(inst) {
4170
- var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
4171
- this._daylightSavingAdjust(new Date(
4172
- inst.currentYear, inst.currentMonth, inst.currentDay)));
4173
- return startDate;
4174
- },
4175
-
4176
- /* Attach the onxxx handlers. These are declared statically so
4177
- * they work with static code transformers like Caja.
4178
- */
4179
- _attachHandlers: function(inst) {
4180
- var stepMonths = this._get(inst, "stepMonths"),
4181
- id = "#" + inst.id.replace( /\\\\/g, "\\" );
4182
- inst.dpDiv.find("[data-handler]").map(function () {
4183
- var handler = {
4184
- prev: function () {
4185
- $.datepicker._adjustDate(id, -stepMonths, "M");
4186
- },
4187
- next: function () {
4188
- $.datepicker._adjustDate(id, +stepMonths, "M");
4189
- },
4190
- hide: function () {
4191
- $.datepicker._hideDatepicker();
4192
- },
4193
- today: function () {
4194
- $.datepicker._gotoToday(id);
4195
- },
4196
- selectDay: function () {
4197
- $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
4198
- return false;
4199
- },
4200
- selectMonth: function () {
4201
- $.datepicker._selectMonthYear(id, this, "M");
4202
- return false;
4203
- },
4204
- selectYear: function () {
4205
- $.datepicker._selectMonthYear(id, this, "Y");
4206
- return false;
4207
- }
4208
- };
4209
- $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
4210
- });
4211
- },
4212
-
4213
- /* Generate the HTML for the current state of the date picker. */
4214
- _generateHTML: function(inst) {
4215
- var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
4216
- controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
4217
- monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
4218
- selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
4219
- cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
4220
- printDate, dRow, tbody, daySettings, otherMonth, unselectable,
4221
- tempDate = new Date(),
4222
- today = this._daylightSavingAdjust(
4223
- new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
4224
- isRTL = this._get(inst, "isRTL"),
4225
- showButtonPanel = this._get(inst, "showButtonPanel"),
4226
- hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
4227
- navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
4228
- numMonths = this._getNumberOfMonths(inst),
4229
- showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
4230
- stepMonths = this._get(inst, "stepMonths"),
4231
- isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
4232
- currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
4233
- new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
4234
- minDate = this._getMinMaxDate(inst, "min"),
4235
- maxDate = this._getMinMaxDate(inst, "max"),
4236
- drawMonth = inst.drawMonth - showCurrentAtPos,
4237
- drawYear = inst.drawYear;
4238
-
4239
- if (drawMonth < 0) {
4240
- drawMonth += 12;
4241
- drawYear--;
4242
- }
4243
- if (maxDate) {
4244
- maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
4245
- maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
4246
- maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
4247
- while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
4248
- drawMonth--;
4249
- if (drawMonth < 0) {
4250
- drawMonth = 11;
4251
- drawYear--;
4252
- }
4253
- }
4254
- }
4255
- inst.drawMonth = drawMonth;
4256
- inst.drawYear = drawYear;
4257
-
4258
- prevText = this._get(inst, "prevText");
4259
- prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
4260
- this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
4261
- this._getFormatConfig(inst)));
4262
-
4263
- prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
4264
- "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
4265
- " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
4266
- (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>"));
4267
-
4268
- nextText = this._get(inst, "nextText");
4269
- nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
4270
- this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
4271
- this._getFormatConfig(inst)));
4272
-
4273
- next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
4274
- "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
4275
- " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
4276
- (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>"));
4277
-
4278
- currentText = this._get(inst, "currentText");
4279
- gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
4280
- currentText = (!navigationAsDateFormat ? currentText :
4281
- this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
4282
-
4283
- 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'>" +
4284
- this._get(inst, "closeText") + "</button>" : "");
4285
-
4286
- buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
4287
- (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'" +
4288
- ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
4289
-
4290
- firstDay = parseInt(this._get(inst, "firstDay"),10);
4291
- firstDay = (isNaN(firstDay) ? 0 : firstDay);
4292
-
4293
- showWeek = this._get(inst, "showWeek");
4294
- dayNames = this._get(inst, "dayNames");
4295
- dayNamesMin = this._get(inst, "dayNamesMin");
4296
- monthNames = this._get(inst, "monthNames");
4297
- monthNamesShort = this._get(inst, "monthNamesShort");
4298
- beforeShowDay = this._get(inst, "beforeShowDay");
4299
- showOtherMonths = this._get(inst, "showOtherMonths");
4300
- selectOtherMonths = this._get(inst, "selectOtherMonths");
4301
- defaultDate = this._getDefaultDate(inst);
4302
- html = "";
4303
- dow;
4304
- for (row = 0; row < numMonths[0]; row++) {
4305
- group = "";
4306
- this.maxRows = 4;
4307
- for (col = 0; col < numMonths[1]; col++) {
4308
- selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
4309
- cornerClass = " ui-corner-all";
4310
- calender = "";
4311
- if (isMultiMonth) {
4312
- calender += "<div class='ui-datepicker-group";
4313
- if (numMonths[1] > 1) {
4314
- switch (col) {
4315
- case 0: calender += " ui-datepicker-group-first";
4316
- cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
4317
- case numMonths[1]-1: calender += " ui-datepicker-group-last";
4318
- cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
4319
- default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
4320
- }
4321
- }
4322
- calender += "'>";
4323
- }
4324
- calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
4325
- (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
4326
- (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
4327
- this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
4328
- row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
4329
- "</div><table class='ui-datepicker-calendar'><thead>" +
4330
- "<tr>";
4331
- thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
4332
- for (dow = 0; dow < 7; dow++) { // days of the week
4333
- day = (dow + firstDay) % 7;
4334
- thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
4335
- "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
4336
- }
4337
- calender += thead + "</tr></thead><tbody>";
4338
- daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
4339
- if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
4340
- inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
4341
- }
4342
- leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
4343
- curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
4344
- numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
4345
- this.maxRows = numRows;
4346
- printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
4347
- for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
4348
- calender += "<tr>";
4349
- tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
4350
- this._get(inst, "calculateWeek")(printDate) + "</td>");
4351
- for (dow = 0; dow < 7; dow++) { // create date picker days
4352
- daySettings = (beforeShowDay ?
4353
- beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
4354
- otherMonth = (printDate.getMonth() !== drawMonth);
4355
- unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
4356
- (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
4357
- tbody += "<td class='" +
4358
- ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
4359
- (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
4360
- ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
4361
- (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
4362
- // or defaultDate is current printedDate and defaultDate is selectedDate
4363
- " " + this._dayOverClass : "") + // highlight selected day
4364
- (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
4365
- (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
4366
- (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
4367
- (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
4368
- ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
4369
- (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
4370
- (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
4371
- (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
4372
- (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
4373
- (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
4374
- (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
4375
- "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
4376
- printDate.setDate(printDate.getDate() + 1);
4377
- printDate = this._daylightSavingAdjust(printDate);
4378
- }
4379
- calender += tbody + "</tr>";
4380
- }
4381
- drawMonth++;
4382
- if (drawMonth > 11) {
4383
- drawMonth = 0;
4384
- drawYear++;
4385
- }
4386
- calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
4387
- ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
4388
- group += calender;
4389
- }
4390
- html += group;
4391
- }
4392
- html += buttonPanel;
4393
- inst._keyEvent = false;
4394
- return html;
4395
- },
4396
-
4397
- /* Generate the month and year header. */
4398
- _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
4399
- secondary, monthNames, monthNamesShort) {
4400
-
4401
- var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
4402
- changeMonth = this._get(inst, "changeMonth"),
4403
- changeYear = this._get(inst, "changeYear"),
4404
- showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
4405
- html = "<div class='ui-datepicker-title'>",
4406
- monthHtml = "";
4407
-
4408
- // month selection
4409
- if (secondary || !changeMonth) {
4410
- monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
4411
- } else {
4412
- inMinYear = (minDate && minDate.getFullYear() === drawYear);
4413
- inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
4414
- monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
4415
- for ( month = 0; month < 12; month++) {
4416
- if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
4417
- monthHtml += "<option value='" + month + "'" +
4418
- (month === drawMonth ? " selected='selected'" : "") +
4419
- ">" + monthNamesShort[month] + "</option>";
4420
- }
4421
- }
4422
- monthHtml += "</select>";
4423
- }
4424
-
4425
- if (!showMonthAfterYear) {
4426
- html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
4427
- }
4428
-
4429
- // year selection
4430
- if ( !inst.yearshtml ) {
4431
- inst.yearshtml = "";
4432
- if (secondary || !changeYear) {
4433
- html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
4434
- } else {
4435
- // determine range of years to display
4436
- years = this._get(inst, "yearRange").split(":");
4437
- thisYear = new Date().getFullYear();
4438
- determineYear = function(value) {
4439
- var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
4440
- (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
4441
- parseInt(value, 10)));
4442
- return (isNaN(year) ? thisYear : year);
4443
- };
4444
- year = determineYear(years[0]);
4445
- endYear = Math.max(year, determineYear(years[1] || ""));
4446
- year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
4447
- endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
4448
- inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
4449
- for (; year <= endYear; year++) {
4450
- inst.yearshtml += "<option value='" + year + "'" +
4451
- (year === drawYear ? " selected='selected'" : "") +
4452
- ">" + year + "</option>";
4453
- }
4454
- inst.yearshtml += "</select>";
4455
-
4456
- html += inst.yearshtml;
4457
- inst.yearshtml = null;
4458
- }
4459
- }
4460
-
4461
- html += this._get(inst, "yearSuffix");
4462
- if (showMonthAfterYear) {
4463
- html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
4464
- }
4465
- html += "</div>"; // Close datepicker_header
4466
- return html;
4467
- },
4468
-
4469
- /* Adjust one of the date sub-fields. */
4470
- _adjustInstDate: function(inst, offset, period) {
4471
- var year = inst.drawYear + (period === "Y" ? offset : 0),
4472
- month = inst.drawMonth + (period === "M" ? offset : 0),
4473
- day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
4474
- date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
4475
-
4476
- inst.selectedDay = date.getDate();
4477
- inst.drawMonth = inst.selectedMonth = date.getMonth();
4478
- inst.drawYear = inst.selectedYear = date.getFullYear();
4479
- if (period === "M" || period === "Y") {
4480
- this._notifyChange(inst);
4481
- }
4482
- },
4483
-
4484
- /* Ensure a date is within any min/max bounds. */
4485
- _restrictMinMax: function(inst, date) {
4486
- var minDate = this._getMinMaxDate(inst, "min"),
4487
- maxDate = this._getMinMaxDate(inst, "max"),
4488
- newDate = (minDate && date < minDate ? minDate : date);
4489
- return (maxDate && newDate > maxDate ? maxDate : newDate);
4490
- },
4491
-
4492
- /* Notify change of month/year. */
4493
- _notifyChange: function(inst) {
4494
- var onChange = this._get(inst, "onChangeMonthYear");
4495
- if (onChange) {
4496
- onChange.apply((inst.input ? inst.input[0] : null),
4497
- [inst.selectedYear, inst.selectedMonth + 1, inst]);
4498
- }
4499
- },
4500
-
4501
- /* Determine the number of months to show. */
4502
- _getNumberOfMonths: function(inst) {
4503
- var numMonths = this._get(inst, "numberOfMonths");
4504
- return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
4505
- },
4506
-
4507
- /* Determine the current maximum date - ensure no time components are set. */
4508
- _getMinMaxDate: function(inst, minMax) {
4509
- return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
4510
- },
4511
-
4512
- /* Find the number of days in a given month. */
4513
- _getDaysInMonth: function(year, month) {
4514
- return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
4515
- },
4516
-
4517
- /* Find the day of the week of the first of a month. */
4518
- _getFirstDayOfMonth: function(year, month) {
4519
- return new Date(year, month, 1).getDay();
4520
- },
4521
-
4522
- /* Determines if we should allow a "next/prev" month display change. */
4523
- _canAdjustMonth: function(inst, offset, curYear, curMonth) {
4524
- var numMonths = this._getNumberOfMonths(inst),
4525
- date = this._daylightSavingAdjust(new Date(curYear,
4526
- curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
4527
-
4528
- if (offset < 0) {
4529
- date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
4530
- }
4531
- return this._isInRange(inst, date);
4532
- },
4533
-
4534
- /* Is the given date in the accepted range? */
4535
- _isInRange: function(inst, date) {
4536
- var yearSplit, currentYear,
4537
- minDate = this._getMinMaxDate(inst, "min"),
4538
- maxDate = this._getMinMaxDate(inst, "max"),
4539
- minYear = null,
4540
- maxYear = null,
4541
- years = this._get(inst, "yearRange");
4542
- if (years){
4543
- yearSplit = years.split(":");
4544
- currentYear = new Date().getFullYear();
4545
- minYear = parseInt(yearSplit[0], 10);
4546
- maxYear = parseInt(yearSplit[1], 10);
4547
- if ( yearSplit[0].match(/[+\-].*/) ) {
4548
- minYear += currentYear;
4549
- }
4550
- if ( yearSplit[1].match(/[+\-].*/) ) {
4551
- maxYear += currentYear;
4552
- }
4553
- }
4554
-
4555
- return ((!minDate || date.getTime() >= minDate.getTime()) &&
4556
- (!maxDate || date.getTime() <= maxDate.getTime()) &&
4557
- (!minYear || date.getFullYear() >= minYear) &&
4558
- (!maxYear || date.getFullYear() <= maxYear));
4559
- },
4560
-
4561
- /* Provide the configuration settings for formatting/parsing. */
4562
- _getFormatConfig: function(inst) {
4563
- var shortYearCutoff = this._get(inst, "shortYearCutoff");
4564
- shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
4565
- new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
4566
- return {shortYearCutoff: shortYearCutoff,
4567
- dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
4568
- monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
4569
- },
4570
-
4571
- /* Format the given date for display. */
4572
- _formatDate: function(inst, day, month, year) {
4573
- if (!day) {
4574
- inst.currentDay = inst.selectedDay;
4575
- inst.currentMonth = inst.selectedMonth;
4576
- inst.currentYear = inst.selectedYear;
4577
- }
4578
- var date = (day ? (typeof day === "object" ? day :
4579
- this._daylightSavingAdjust(new Date(year, month, day))) :
4580
- this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
4581
- return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
4582
- }
4583
- });
4584
-
4585
- /*
4586
- * Bind hover events for datepicker elements.
4587
- * Done via delegate so the binding only occurs once in the lifetime of the parent div.
4588
- * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
4589
- */
4590
- function datepicker_bindHover(dpDiv) {
4591
- var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
4592
- return dpDiv.delegate(selector, "mouseout", function() {
4593
- $(this).removeClass("ui-state-hover");
4594
- if (this.className.indexOf("ui-datepicker-prev") !== -1) {
4595
- $(this).removeClass("ui-datepicker-prev-hover");
4596
- }
4597
- if (this.className.indexOf("ui-datepicker-next") !== -1) {
4598
- $(this).removeClass("ui-datepicker-next-hover");
4599
- }
4600
- })
4601
- .delegate( selector, "mouseover", datepicker_handleMouseover );
4602
- }
4603
-
4604
- function datepicker_handleMouseover() {
4605
- if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
4606
- $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
4607
- $(this).addClass("ui-state-hover");
4608
- if (this.className.indexOf("ui-datepicker-prev") !== -1) {
4609
- $(this).addClass("ui-datepicker-prev-hover");
4610
- }
4611
- if (this.className.indexOf("ui-datepicker-next") !== -1) {
4612
- $(this).addClass("ui-datepicker-next-hover");
4613
- }
4614
- }
4615
- }
4616
-
4617
- /* jQuery extend now ignores nulls! */
4618
- function datepicker_extendRemove(target, props) {
4619
- $.extend(target, props);
4620
- for (var name in props) {
4621
- if (props[name] == null) {
4622
- target[name] = props[name];
4623
- }
4624
- }
4625
- return target;
4626
- }
4627
-
4628
- /* Invoke the datepicker functionality.
4629
- @param options string - a command, optionally followed by additional parameters or
4630
- Object - settings for attaching new datepicker functionality
4631
- @return jQuery object */
4632
- $.fn.datepicker = function(options){
4633
-
4634
- /* Verify an empty collection wasn't passed - Fixes #6976 */
4635
- if ( !this.length ) {
4636
- return this;
4637
- }
4638
-
4639
- /* Initialise the date picker. */
4640
- if (!$.datepicker.initialized) {
4641
- $(document).mousedown($.datepicker._checkExternalClick);
4642
- $.datepicker.initialized = true;
4643
- }
4644
-
4645
- /* Append datepicker main container to body if not exist. */
4646
- if ($("#"+$.datepicker._mainDivId).length === 0) {
4647
- $("body").append($.datepicker.dpDiv);
4648
- }
4649
-
4650
- var otherArgs = Array.prototype.slice.call(arguments, 1);
4651
- if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
4652
- return $.datepicker["_" + options + "Datepicker"].
4653
- apply($.datepicker, [this[0]].concat(otherArgs));
4654
- }
4655
- if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
4656
- return $.datepicker["_" + options + "Datepicker"].
4657
- apply($.datepicker, [this[0]].concat(otherArgs));
4658
- }
4659
- return this.each(function() {
4660
- typeof options === "string" ?
4661
- $.datepicker["_" + options + "Datepicker"].
4662
- apply($.datepicker, [this].concat(otherArgs)) :
4663
- $.datepicker._attachDatepicker(this, options);
4664
- });
4665
- };
4666
-
4667
- $.datepicker = new Datepicker(); // singleton instance
4668
- $.datepicker.initialized = false;
4669
- $.datepicker.uuid = new Date().getTime();
4670
- $.datepicker.version = "1.11.2";
4671
-
4672
- var datepicker = $.datepicker;
4673
-
4674
-
4675
-
4676
- }));