iqvoc 3.3.1 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/CHANGELOG.md +101 -0
  2. data/app/assets/javascripts/framework.js +1 -0
  3. data/app/assets/stylesheets/framework.css +2 -0
  4. data/app/views/layouts/application.html.erb +2 -11
  5. data/iqvoc.gemspec +2 -1
  6. data/lib/iqvoc.rb +0 -3
  7. data/lib/iqvoc/version.rb +1 -1
  8. data/public/assets/blueprint/ie-0761b92d02baf44f0b2011e3009e6aa9.css.gz +0 -0
  9. data/public/assets/blueprint/ie.css.gz +0 -0
  10. data/public/assets/iqvoc/ie_fixes-7a001f31445ddfb2e0668c419f81742f.css.gz +0 -0
  11. data/public/assets/iqvoc/ie_fixes.css.gz +0 -0
  12. data/public/assets/manifest-6f0772f7ec93cc20de428ae859353e92.js +21 -0
  13. data/public/assets/manifest-6f0772f7ec93cc20de428ae859353e92.js.gz +0 -0
  14. data/public/assets/manifest-d52be2520b68121c73695e4026876a98.css +1421 -0
  15. data/public/assets/manifest-d52be2520b68121c73695e4026876a98.css.gz +0 -0
  16. data/public/assets/manifest.css +295 -0
  17. data/public/assets/manifest.css.gz +0 -0
  18. data/public/assets/manifest.js +2 -2
  19. data/public/assets/manifest.js.gz +0 -0
  20. data/public/assets/manifest.yml +2 -5
  21. data/vendor/assets/images/ajax-loader.gif +0 -0
  22. data/vendor/assets/images/file.gif +0 -0
  23. data/vendor/assets/images/folder-closed.gif +0 -0
  24. data/vendor/assets/images/folder.gif +0 -0
  25. data/vendor/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  26. data/vendor/assets/images/jquery-ui/ui-bg_flat_55_fbec88_40x100.png +0 -0
  27. data/vendor/assets/images/jquery-ui/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  28. data/vendor/assets/images/jquery-ui/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  29. data/vendor/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  30. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  31. data/vendor/assets/images/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  32. data/vendor/assets/images/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  33. data/vendor/assets/images/jquery-ui/ui-icons_217bc0_256x240.png +0 -0
  34. data/vendor/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png +0 -0
  35. data/vendor/assets/images/jquery-ui/ui-icons_469bdd_256x240.png +0 -0
  36. data/vendor/assets/images/jquery-ui/ui-icons_6da8d5_256x240.png +0 -0
  37. data/vendor/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png +0 -0
  38. data/vendor/assets/images/jquery-ui/ui-icons_d8e7f3_256x240.png +0 -0
  39. data/vendor/assets/images/jquery-ui/ui-icons_f9bd01_256x240.png +0 -0
  40. data/vendor/assets/images/minus.gif +0 -0
  41. data/vendor/assets/images/plus.gif +0 -0
  42. data/vendor/assets/images/treeview-black-line.gif +0 -0
  43. data/vendor/assets/images/treeview-black.gif +0 -0
  44. data/vendor/assets/images/treeview-default-line.gif +0 -0
  45. data/vendor/assets/images/treeview-default.gif +0 -0
  46. data/vendor/assets/images/treeview-famfamfam-line.gif +0 -0
  47. data/vendor/assets/images/treeview-famfamfam.gif +0 -0
  48. data/vendor/assets/images/treeview-gray-line.gif +0 -0
  49. data/vendor/assets/images/treeview-gray.gif +0 -0
  50. data/vendor/assets/images/treeview-red-line.gif +0 -0
  51. data/vendor/assets/images/treeview-red.gif +0 -0
  52. data/vendor/assets/javascripts/excanvas.js +35 -0
  53. data/vendor/assets/javascripts/jit_rgraph.js +153 -0
  54. data/vendor/assets/javascripts/jquery-1.7.1.js +9266 -0
  55. data/vendor/assets/javascripts/jquery-ui-1.8.16.custom.js +3269 -0
  56. data/vendor/assets/javascripts/jquery-ui.datepicker-de.js +22 -0
  57. data/vendor/assets/javascripts/jquery.treeview.async.js +82 -0
  58. data/vendor/assets/javascripts/jquery.treeview.js +251 -0
  59. data/vendor/assets/javascripts/json2.js +485 -0
  60. data/vendor/assets/javascripts/rails.js +373 -0
  61. data/vendor/assets/javascripts/storage.js +122 -0
  62. data/vendor/assets/stylesheets/blueprint/ie.css +35 -0
  63. data/vendor/assets/stylesheets/blueprint/print.css +33 -0
  64. data/vendor/assets/stylesheets/blueprint/screen.css +262 -0
  65. data/vendor/assets/stylesheets/jquery-ui-1.8.16.custom.css +410 -0
  66. data/vendor/assets/stylesheets/jquery.treeview.css.erb +75 -0
  67. metadata +68 -17
@@ -0,0 +1,3269 @@
1
+ /*!
2
+ * jQuery UI 1.8.16
3
+ *
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI
9
+ */
10
+ (function( $, undefined ) {
11
+
12
+ // prevent duplicate loading
13
+ // this is only a problem because we proxy existing functions
14
+ // and we don't want to double proxy them
15
+ $.ui = $.ui || {};
16
+ if ( $.ui.version ) {
17
+ return;
18
+ }
19
+
20
+ $.extend( $.ui, {
21
+ version: "1.8.16",
22
+
23
+ keyCode: {
24
+ ALT: 18,
25
+ BACKSPACE: 8,
26
+ CAPS_LOCK: 20,
27
+ COMMA: 188,
28
+ COMMAND: 91,
29
+ COMMAND_LEFT: 91, // COMMAND
30
+ COMMAND_RIGHT: 93,
31
+ CONTROL: 17,
32
+ DELETE: 46,
33
+ DOWN: 40,
34
+ END: 35,
35
+ ENTER: 13,
36
+ ESCAPE: 27,
37
+ HOME: 36,
38
+ INSERT: 45,
39
+ LEFT: 37,
40
+ MENU: 93, // COMMAND_RIGHT
41
+ NUMPAD_ADD: 107,
42
+ NUMPAD_DECIMAL: 110,
43
+ NUMPAD_DIVIDE: 111,
44
+ NUMPAD_ENTER: 108,
45
+ NUMPAD_MULTIPLY: 106,
46
+ NUMPAD_SUBTRACT: 109,
47
+ PAGE_DOWN: 34,
48
+ PAGE_UP: 33,
49
+ PERIOD: 190,
50
+ RIGHT: 39,
51
+ SHIFT: 16,
52
+ SPACE: 32,
53
+ TAB: 9,
54
+ UP: 38,
55
+ WINDOWS: 91 // COMMAND
56
+ }
57
+ });
58
+
59
+ // plugins
60
+ $.fn.extend({
61
+ propAttr: $.fn.prop || $.fn.attr,
62
+
63
+ _focus: $.fn.focus,
64
+ focus: function( delay, fn ) {
65
+ return typeof delay === "number" ?
66
+ this.each(function() {
67
+ var elem = this;
68
+ setTimeout(function() {
69
+ $( elem ).focus();
70
+ if ( fn ) {
71
+ fn.call( elem );
72
+ }
73
+ }, delay );
74
+ }) :
75
+ this._focus.apply( this, arguments );
76
+ },
77
+
78
+ scrollParent: function() {
79
+ var scrollParent;
80
+ if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
81
+ scrollParent = this.parents().filter(function() {
82
+ return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
83
+ }).eq(0);
84
+ } else {
85
+ scrollParent = this.parents().filter(function() {
86
+ return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
87
+ }).eq(0);
88
+ }
89
+
90
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
91
+ },
92
+
93
+ zIndex: function( zIndex ) {
94
+ if ( zIndex !== undefined ) {
95
+ return this.css( "zIndex", zIndex );
96
+ }
97
+
98
+ if ( this.length ) {
99
+ var elem = $( this[ 0 ] ), position, value;
100
+ while ( elem.length && elem[ 0 ] !== document ) {
101
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
102
+ // This makes behavior of this function consistent across browsers
103
+ // WebKit always returns auto if the element is positioned
104
+ position = elem.css( "position" );
105
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
106
+ // IE returns 0 when zIndex is not specified
107
+ // other browsers return a string
108
+ // we ignore the case of nested elements with an explicit value of 0
109
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
110
+ value = parseInt( elem.css( "zIndex" ), 10 );
111
+ if ( !isNaN( value ) && value !== 0 ) {
112
+ return value;
113
+ }
114
+ }
115
+ elem = elem.parent();
116
+ }
117
+ }
118
+
119
+ return 0;
120
+ },
121
+
122
+ disableSelection: function() {
123
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
124
+ ".ui-disableSelection", function( event ) {
125
+ event.preventDefault();
126
+ });
127
+ },
128
+
129
+ enableSelection: function() {
130
+ return this.unbind( ".ui-disableSelection" );
131
+ }
132
+ });
133
+
134
+ $.each( [ "Width", "Height" ], function( i, name ) {
135
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
136
+ type = name.toLowerCase(),
137
+ orig = {
138
+ innerWidth: $.fn.innerWidth,
139
+ innerHeight: $.fn.innerHeight,
140
+ outerWidth: $.fn.outerWidth,
141
+ outerHeight: $.fn.outerHeight
142
+ };
143
+
144
+ function reduce( elem, size, border, margin ) {
145
+ $.each( side, function() {
146
+ size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
147
+ if ( border ) {
148
+ size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
149
+ }
150
+ if ( margin ) {
151
+ size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
152
+ }
153
+ });
154
+ return size;
155
+ }
156
+
157
+ $.fn[ "inner" + name ] = function( size ) {
158
+ if ( size === undefined ) {
159
+ return orig[ "inner" + name ].call( this );
160
+ }
161
+
162
+ return this.each(function() {
163
+ $( this ).css( type, reduce( this, size ) + "px" );
164
+ });
165
+ };
166
+
167
+ $.fn[ "outer" + name] = function( size, margin ) {
168
+ if ( typeof size !== "number" ) {
169
+ return orig[ "outer" + name ].call( this, size );
170
+ }
171
+
172
+ return this.each(function() {
173
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
174
+ });
175
+ };
176
+ });
177
+
178
+ // selectors
179
+ function focusable( element, isTabIndexNotNaN ) {
180
+ var nodeName = element.nodeName.toLowerCase();
181
+ if ( "area" === nodeName ) {
182
+ var map = element.parentNode,
183
+ mapName = map.name,
184
+ img;
185
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
186
+ return false;
187
+ }
188
+ img = $( "img[usemap=#" + mapName + "]" )[0];
189
+ return !!img && visible( img );
190
+ }
191
+ return ( /input|select|textarea|button|object/.test( nodeName )
192
+ ? !element.disabled
193
+ : "a" == nodeName
194
+ ? element.href || isTabIndexNotNaN
195
+ : isTabIndexNotNaN)
196
+ // the element and all of its ancestors must be visible
197
+ && visible( element );
198
+ }
199
+
200
+ function visible( element ) {
201
+ return !$( element ).parents().andSelf().filter(function() {
202
+ return $.curCSS( this, "visibility" ) === "hidden" ||
203
+ $.expr.filters.hidden( this );
204
+ }).length;
205
+ }
206
+
207
+ $.extend( $.expr[ ":" ], {
208
+ data: function( elem, i, match ) {
209
+ return !!$.data( elem, match[ 3 ] );
210
+ },
211
+
212
+ focusable: function( element ) {
213
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
214
+ },
215
+
216
+ tabbable: function( element ) {
217
+ var tabIndex = $.attr( element, "tabindex" ),
218
+ isTabIndexNaN = isNaN( tabIndex );
219
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
220
+ }
221
+ });
222
+
223
+ // support
224
+ $(function() {
225
+ var body = document.body,
226
+ div = body.appendChild( div = document.createElement( "div" ) );
227
+
228
+ $.extend( div.style, {
229
+ minHeight: "100px",
230
+ height: "auto",
231
+ padding: 0,
232
+ borderWidth: 0
233
+ });
234
+
235
+ $.support.minHeight = div.offsetHeight === 100;
236
+ $.support.selectstart = "onselectstart" in div;
237
+
238
+ // set display to none to avoid a layout bug in IE
239
+ // http://dev.jquery.com/ticket/4014
240
+ body.removeChild( div ).style.display = "none";
241
+ });
242
+
243
+
244
+
245
+
246
+
247
+ // deprecated
248
+ $.extend( $.ui, {
249
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
250
+ plugin: {
251
+ add: function( module, option, set ) {
252
+ var proto = $.ui[ module ].prototype;
253
+ for ( var i in set ) {
254
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
255
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
256
+ }
257
+ },
258
+ call: function( instance, name, args ) {
259
+ var set = instance.plugins[ name ];
260
+ if ( !set || !instance.element[ 0 ].parentNode ) {
261
+ return;
262
+ }
263
+
264
+ for ( var i = 0; i < set.length; i++ ) {
265
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
266
+ set[ i ][ 1 ].apply( instance.element, args );
267
+ }
268
+ }
269
+ }
270
+ },
271
+
272
+ // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
273
+ contains: function( a, b ) {
274
+ return document.compareDocumentPosition ?
275
+ a.compareDocumentPosition( b ) & 16 :
276
+ a !== b && a.contains( b );
277
+ },
278
+
279
+ // only used by resizable
280
+ hasScroll: function( el, a ) {
281
+
282
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
283
+ if ( $( el ).css( "overflow" ) === "hidden") {
284
+ return false;
285
+ }
286
+
287
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
288
+ has = false;
289
+
290
+ if ( el[ scroll ] > 0 ) {
291
+ return true;
292
+ }
293
+
294
+ // TODO: determine which cases actually cause this to happen
295
+ // if the element doesn't have the scroll set, see if it's possible to
296
+ // set the scroll
297
+ el[ scroll ] = 1;
298
+ has = ( el[ scroll ] > 0 );
299
+ el[ scroll ] = 0;
300
+ return has;
301
+ },
302
+
303
+ // these are odd functions, fix the API or move into individual plugins
304
+ isOverAxis: function( x, reference, size ) {
305
+ //Determines when x coordinate is over "b" element axis
306
+ return ( x > reference ) && ( x < ( reference + size ) );
307
+ },
308
+ isOver: function( y, x, top, left, height, width ) {
309
+ //Determines when x, y coordinates is over "b" element
310
+ return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
311
+ }
312
+ });
313
+
314
+ })( jQuery );
315
+ /*!
316
+ * jQuery UI Widget 1.8.16
317
+ *
318
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
319
+ * Dual licensed under the MIT or GPL Version 2 licenses.
320
+ * http://jquery.org/license
321
+ *
322
+ * http://docs.jquery.com/UI/Widget
323
+ */
324
+ (function( $, undefined ) {
325
+
326
+ // jQuery 1.4+
327
+ if ( $.cleanData ) {
328
+ var _cleanData = $.cleanData;
329
+ $.cleanData = function( elems ) {
330
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
331
+ try {
332
+ $( elem ).triggerHandler( "remove" );
333
+ // http://bugs.jquery.com/ticket/8235
334
+ } catch( e ) {}
335
+ }
336
+ _cleanData( elems );
337
+ };
338
+ } else {
339
+ var _remove = $.fn.remove;
340
+ $.fn.remove = function( selector, keepData ) {
341
+ return this.each(function() {
342
+ if ( !keepData ) {
343
+ if ( !selector || $.filter( selector, [ this ] ).length ) {
344
+ $( "*", this ).add( [ this ] ).each(function() {
345
+ try {
346
+ $( this ).triggerHandler( "remove" );
347
+ // http://bugs.jquery.com/ticket/8235
348
+ } catch( e ) {}
349
+ });
350
+ }
351
+ }
352
+ return _remove.call( $(this), selector, keepData );
353
+ });
354
+ };
355
+ }
356
+
357
+ $.widget = function( name, base, prototype ) {
358
+ var namespace = name.split( "." )[ 0 ],
359
+ fullName;
360
+ name = name.split( "." )[ 1 ];
361
+ fullName = namespace + "-" + name;
362
+
363
+ if ( !prototype ) {
364
+ prototype = base;
365
+ base = $.Widget;
366
+ }
367
+
368
+ // create selector for plugin
369
+ $.expr[ ":" ][ fullName ] = function( elem ) {
370
+ return !!$.data( elem, name );
371
+ };
372
+
373
+ $[ namespace ] = $[ namespace ] || {};
374
+ $[ namespace ][ name ] = function( options, element ) {
375
+ // allow instantiation without initializing for simple inheritance
376
+ if ( arguments.length ) {
377
+ this._createWidget( options, element );
378
+ }
379
+ };
380
+
381
+ var basePrototype = new base();
382
+ // we need to make the options hash a property directly on the new instance
383
+ // otherwise we'll modify the options hash on the prototype that we're
384
+ // inheriting from
385
+ // $.each( basePrototype, function( key, val ) {
386
+ // if ( $.isPlainObject(val) ) {
387
+ // basePrototype[ key ] = $.extend( {}, val );
388
+ // }
389
+ // });
390
+ basePrototype.options = $.extend( true, {}, basePrototype.options );
391
+ $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
392
+ namespace: namespace,
393
+ widgetName: name,
394
+ widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
395
+ widgetBaseClass: fullName
396
+ }, prototype );
397
+
398
+ $.widget.bridge( name, $[ namespace ][ name ] );
399
+ };
400
+
401
+ $.widget.bridge = function( name, object ) {
402
+ $.fn[ name ] = function( options ) {
403
+ var isMethodCall = typeof options === "string",
404
+ args = Array.prototype.slice.call( arguments, 1 ),
405
+ returnValue = this;
406
+
407
+ // allow multiple hashes to be passed on init
408
+ options = !isMethodCall && args.length ?
409
+ $.extend.apply( null, [ true, options ].concat(args) ) :
410
+ options;
411
+
412
+ // prevent calls to internal methods
413
+ if ( isMethodCall && options.charAt( 0 ) === "_" ) {
414
+ return returnValue;
415
+ }
416
+
417
+ if ( isMethodCall ) {
418
+ this.each(function() {
419
+ var instance = $.data( this, name ),
420
+ methodValue = instance && $.isFunction( instance[options] ) ?
421
+ instance[ options ].apply( instance, args ) :
422
+ instance;
423
+ // TODO: add this back in 1.9 and use $.error() (see #5972)
424
+ // if ( !instance ) {
425
+ // throw "cannot call methods on " + name + " prior to initialization; " +
426
+ // "attempted to call method '" + options + "'";
427
+ // }
428
+ // if ( !$.isFunction( instance[options] ) ) {
429
+ // throw "no such method '" + options + "' for " + name + " widget instance";
430
+ // }
431
+ // var methodValue = instance[ options ].apply( instance, args );
432
+ if ( methodValue !== instance && methodValue !== undefined ) {
433
+ returnValue = methodValue;
434
+ return false;
435
+ }
436
+ });
437
+ } else {
438
+ this.each(function() {
439
+ var instance = $.data( this, name );
440
+ if ( instance ) {
441
+ instance.option( options || {} )._init();
442
+ } else {
443
+ $.data( this, name, new object( options, this ) );
444
+ }
445
+ });
446
+ }
447
+
448
+ return returnValue;
449
+ };
450
+ };
451
+
452
+ $.Widget = function( options, element ) {
453
+ // allow instantiation without initializing for simple inheritance
454
+ if ( arguments.length ) {
455
+ this._createWidget( options, element );
456
+ }
457
+ };
458
+
459
+ $.Widget.prototype = {
460
+ widgetName: "widget",
461
+ widgetEventPrefix: "",
462
+ options: {
463
+ disabled: false
464
+ },
465
+ _createWidget: function( options, element ) {
466
+ // $.widget.bridge stores the plugin instance, but we do it anyway
467
+ // so that it's stored even before the _create function runs
468
+ $.data( element, this.widgetName, this );
469
+ this.element = $( element );
470
+ this.options = $.extend( true, {},
471
+ this.options,
472
+ this._getCreateOptions(),
473
+ options );
474
+
475
+ var self = this;
476
+ this.element.bind( "remove." + this.widgetName, function() {
477
+ self.destroy();
478
+ });
479
+
480
+ this._create();
481
+ this._trigger( "create" );
482
+ this._init();
483
+ },
484
+ _getCreateOptions: function() {
485
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
486
+ },
487
+ _create: function() {},
488
+ _init: function() {},
489
+
490
+ destroy: function() {
491
+ this.element
492
+ .unbind( "." + this.widgetName )
493
+ .removeData( this.widgetName );
494
+ this.widget()
495
+ .unbind( "." + this.widgetName )
496
+ .removeAttr( "aria-disabled" )
497
+ .removeClass(
498
+ this.widgetBaseClass + "-disabled " +
499
+ "ui-state-disabled" );
500
+ },
501
+
502
+ widget: function() {
503
+ return this.element;
504
+ },
505
+
506
+ option: function( key, value ) {
507
+ var options = key;
508
+
509
+ if ( arguments.length === 0 ) {
510
+ // don't return a reference to the internal hash
511
+ return $.extend( {}, this.options );
512
+ }
513
+
514
+ if (typeof key === "string" ) {
515
+ if ( value === undefined ) {
516
+ return this.options[ key ];
517
+ }
518
+ options = {};
519
+ options[ key ] = value;
520
+ }
521
+
522
+ this._setOptions( options );
523
+
524
+ return this;
525
+ },
526
+ _setOptions: function( options ) {
527
+ var self = this;
528
+ $.each( options, function( key, value ) {
529
+ self._setOption( key, value );
530
+ });
531
+
532
+ return this;
533
+ },
534
+ _setOption: function( key, value ) {
535
+ this.options[ key ] = value;
536
+
537
+ if ( key === "disabled" ) {
538
+ this.widget()
539
+ [ value ? "addClass" : "removeClass"](
540
+ this.widgetBaseClass + "-disabled" + " " +
541
+ "ui-state-disabled" )
542
+ .attr( "aria-disabled", value );
543
+ }
544
+
545
+ return this;
546
+ },
547
+
548
+ enable: function() {
549
+ return this._setOption( "disabled", false );
550
+ },
551
+ disable: function() {
552
+ return this._setOption( "disabled", true );
553
+ },
554
+
555
+ _trigger: function( type, event, data ) {
556
+ var callback = this.options[ type ];
557
+
558
+ event = $.Event( event );
559
+ event.type = ( type === this.widgetEventPrefix ?
560
+ type :
561
+ this.widgetEventPrefix + type ).toLowerCase();
562
+ data = data || {};
563
+
564
+ // copy original event properties over to the new event
565
+ // this would happen if we could call $.event.fix instead of $.Event
566
+ // but we don't have a way to force an event to be fixed multiple times
567
+ if ( event.originalEvent ) {
568
+ for ( var i = $.event.props.length, prop; i; ) {
569
+ prop = $.event.props[ --i ];
570
+ event[ prop ] = event.originalEvent[ prop ];
571
+ }
572
+ }
573
+
574
+ this.element.trigger( event, data );
575
+
576
+ return !( $.isFunction(callback) &&
577
+ callback.call( this.element[0], event, data ) === false ||
578
+ event.isDefaultPrevented() );
579
+ }
580
+ };
581
+
582
+ })( jQuery );
583
+ /*
584
+ * jQuery UI Position 1.8.16
585
+ *
586
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
587
+ * Dual licensed under the MIT or GPL Version 2 licenses.
588
+ * http://jquery.org/license
589
+ *
590
+ * http://docs.jquery.com/UI/Position
591
+ */
592
+ (function( $, undefined ) {
593
+
594
+ $.ui = $.ui || {};
595
+
596
+ var horizontalPositions = /left|center|right/,
597
+ verticalPositions = /top|center|bottom/,
598
+ center = "center",
599
+ _position = $.fn.position,
600
+ _offset = $.fn.offset;
601
+
602
+ $.fn.position = function( options ) {
603
+ if ( !options || !options.of ) {
604
+ return _position.apply( this, arguments );
605
+ }
606
+
607
+ // make a copy, we don't want to modify arguments
608
+ options = $.extend( {}, options );
609
+
610
+ var target = $( options.of ),
611
+ targetElem = target[0],
612
+ collision = ( options.collision || "flip" ).split( " " ),
613
+ offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
614
+ targetWidth,
615
+ targetHeight,
616
+ basePosition;
617
+
618
+ if ( targetElem.nodeType === 9 ) {
619
+ targetWidth = target.width();
620
+ targetHeight = target.height();
621
+ basePosition = { top: 0, left: 0 };
622
+ // TODO: use $.isWindow() in 1.9
623
+ } else if ( targetElem.setTimeout ) {
624
+ targetWidth = target.width();
625
+ targetHeight = target.height();
626
+ basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
627
+ } else if ( targetElem.preventDefault ) {
628
+ // force left top to allow flipping
629
+ options.at = "left top";
630
+ targetWidth = targetHeight = 0;
631
+ basePosition = { top: options.of.pageY, left: options.of.pageX };
632
+ } else {
633
+ targetWidth = target.outerWidth();
634
+ targetHeight = target.outerHeight();
635
+ basePosition = target.offset();
636
+ }
637
+
638
+ // force my and at to have valid horizontal and veritcal positions
639
+ // if a value is missing or invalid, it will be converted to center
640
+ $.each( [ "my", "at" ], function() {
641
+ var pos = ( options[this] || "" ).split( " " );
642
+ if ( pos.length === 1) {
643
+ pos = horizontalPositions.test( pos[0] ) ?
644
+ pos.concat( [center] ) :
645
+ verticalPositions.test( pos[0] ) ?
646
+ [ center ].concat( pos ) :
647
+ [ center, center ];
648
+ }
649
+ pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
650
+ pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
651
+ options[ this ] = pos;
652
+ });
653
+
654
+ // normalize collision option
655
+ if ( collision.length === 1 ) {
656
+ collision[ 1 ] = collision[ 0 ];
657
+ }
658
+
659
+ // normalize offset option
660
+ offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
661
+ if ( offset.length === 1 ) {
662
+ offset[ 1 ] = offset[ 0 ];
663
+ }
664
+ offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
665
+
666
+ if ( options.at[0] === "right" ) {
667
+ basePosition.left += targetWidth;
668
+ } else if ( options.at[0] === center ) {
669
+ basePosition.left += targetWidth / 2;
670
+ }
671
+
672
+ if ( options.at[1] === "bottom" ) {
673
+ basePosition.top += targetHeight;
674
+ } else if ( options.at[1] === center ) {
675
+ basePosition.top += targetHeight / 2;
676
+ }
677
+
678
+ basePosition.left += offset[ 0 ];
679
+ basePosition.top += offset[ 1 ];
680
+
681
+ return this.each(function() {
682
+ var elem = $( this ),
683
+ elemWidth = elem.outerWidth(),
684
+ elemHeight = elem.outerHeight(),
685
+ marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
686
+ marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
687
+ collisionWidth = elemWidth + marginLeft +
688
+ ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
689
+ collisionHeight = elemHeight + marginTop +
690
+ ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
691
+ position = $.extend( {}, basePosition ),
692
+ collisionPosition;
693
+
694
+ if ( options.my[0] === "right" ) {
695
+ position.left -= elemWidth;
696
+ } else if ( options.my[0] === center ) {
697
+ position.left -= elemWidth / 2;
698
+ }
699
+
700
+ if ( options.my[1] === "bottom" ) {
701
+ position.top -= elemHeight;
702
+ } else if ( options.my[1] === center ) {
703
+ position.top -= elemHeight / 2;
704
+ }
705
+
706
+ // prevent fractions (see #5280)
707
+ position.left = Math.round( position.left );
708
+ position.top = Math.round( position.top );
709
+
710
+ collisionPosition = {
711
+ left: position.left - marginLeft,
712
+ top: position.top - marginTop
713
+ };
714
+
715
+ $.each( [ "left", "top" ], function( i, dir ) {
716
+ if ( $.ui.position[ collision[i] ] ) {
717
+ $.ui.position[ collision[i] ][ dir ]( position, {
718
+ targetWidth: targetWidth,
719
+ targetHeight: targetHeight,
720
+ elemWidth: elemWidth,
721
+ elemHeight: elemHeight,
722
+ collisionPosition: collisionPosition,
723
+ collisionWidth: collisionWidth,
724
+ collisionHeight: collisionHeight,
725
+ offset: offset,
726
+ my: options.my,
727
+ at: options.at
728
+ });
729
+ }
730
+ });
731
+
732
+ if ( $.fn.bgiframe ) {
733
+ elem.bgiframe();
734
+ }
735
+ elem.offset( $.extend( position, { using: options.using } ) );
736
+ });
737
+ };
738
+
739
+ $.ui.position = {
740
+ fit: {
741
+ left: function( position, data ) {
742
+ var win = $( window ),
743
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
744
+ position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
745
+ },
746
+ top: function( position, data ) {
747
+ var win = $( window ),
748
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
749
+ position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
750
+ }
751
+ },
752
+
753
+ flip: {
754
+ left: function( position, data ) {
755
+ if ( data.at[0] === center ) {
756
+ return;
757
+ }
758
+ var win = $( window ),
759
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
760
+ myOffset = data.my[ 0 ] === "left" ?
761
+ -data.elemWidth :
762
+ data.my[ 0 ] === "right" ?
763
+ data.elemWidth :
764
+ 0,
765
+ atOffset = data.at[ 0 ] === "left" ?
766
+ data.targetWidth :
767
+ -data.targetWidth,
768
+ offset = -2 * data.offset[ 0 ];
769
+ position.left += data.collisionPosition.left < 0 ?
770
+ myOffset + atOffset + offset :
771
+ over > 0 ?
772
+ myOffset + atOffset + offset :
773
+ 0;
774
+ },
775
+ top: function( position, data ) {
776
+ if ( data.at[1] === center ) {
777
+ return;
778
+ }
779
+ var win = $( window ),
780
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
781
+ myOffset = data.my[ 1 ] === "top" ?
782
+ -data.elemHeight :
783
+ data.my[ 1 ] === "bottom" ?
784
+ data.elemHeight :
785
+ 0,
786
+ atOffset = data.at[ 1 ] === "top" ?
787
+ data.targetHeight :
788
+ -data.targetHeight,
789
+ offset = -2 * data.offset[ 1 ];
790
+ position.top += data.collisionPosition.top < 0 ?
791
+ myOffset + atOffset + offset :
792
+ over > 0 ?
793
+ myOffset + atOffset + offset :
794
+ 0;
795
+ }
796
+ }
797
+ };
798
+
799
+ // offset setter from jQuery 1.4
800
+ if ( !$.offset.setOffset ) {
801
+ $.offset.setOffset = function( elem, options ) {
802
+ // set position first, in-case top/left are set even on static elem
803
+ if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
804
+ elem.style.position = "relative";
805
+ }
806
+ var curElem = $( elem ),
807
+ curOffset = curElem.offset(),
808
+ curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
809
+ curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
810
+ props = {
811
+ top: (options.top - curOffset.top) + curTop,
812
+ left: (options.left - curOffset.left) + curLeft
813
+ };
814
+
815
+ if ( 'using' in options ) {
816
+ options.using.call( elem, props );
817
+ } else {
818
+ curElem.css( props );
819
+ }
820
+ };
821
+
822
+ $.fn.offset = function( options ) {
823
+ var elem = this[ 0 ];
824
+ if ( !elem || !elem.ownerDocument ) { return null; }
825
+ if ( options ) {
826
+ return this.each(function() {
827
+ $.offset.setOffset( this, options );
828
+ });
829
+ }
830
+ return _offset.call( this );
831
+ };
832
+ }
833
+
834
+ }( jQuery ));
835
+ /*
836
+ * jQuery UI Autocomplete 1.8.16
837
+ *
838
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
839
+ * Dual licensed under the MIT or GPL Version 2 licenses.
840
+ * http://jquery.org/license
841
+ *
842
+ * http://docs.jquery.com/UI/Autocomplete
843
+ *
844
+ * Depends:
845
+ * jquery.ui.core.js
846
+ * jquery.ui.widget.js
847
+ * jquery.ui.position.js
848
+ */
849
+ (function( $, undefined ) {
850
+
851
+ // used to prevent race conditions with remote data sources
852
+ var requestIndex = 0;
853
+
854
+ $.widget( "ui.autocomplete", {
855
+ options: {
856
+ appendTo: "body",
857
+ autoFocus: false,
858
+ delay: 300,
859
+ minLength: 1,
860
+ position: {
861
+ my: "left top",
862
+ at: "left bottom",
863
+ collision: "none"
864
+ },
865
+ source: null
866
+ },
867
+
868
+ pending: 0,
869
+
870
+ _create: function() {
871
+ var self = this,
872
+ doc = this.element[ 0 ].ownerDocument,
873
+ suppressKeyPress;
874
+
875
+ this.element
876
+ .addClass( "ui-autocomplete-input" )
877
+ .attr( "autocomplete", "off" )
878
+ // TODO verify these actually work as intended
879
+ .attr({
880
+ role: "textbox",
881
+ "aria-autocomplete": "list",
882
+ "aria-haspopup": "true"
883
+ })
884
+ .bind( "keydown.autocomplete", function( event ) {
885
+ if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
886
+ return;
887
+ }
888
+
889
+ suppressKeyPress = false;
890
+ var keyCode = $.ui.keyCode;
891
+ switch( event.keyCode ) {
892
+ case keyCode.PAGE_UP:
893
+ self._move( "previousPage", event );
894
+ break;
895
+ case keyCode.PAGE_DOWN:
896
+ self._move( "nextPage", event );
897
+ break;
898
+ case keyCode.UP:
899
+ self._move( "previous", event );
900
+ // prevent moving cursor to beginning of text field in some browsers
901
+ event.preventDefault();
902
+ break;
903
+ case keyCode.DOWN:
904
+ self._move( "next", event );
905
+ // prevent moving cursor to end of text field in some browsers
906
+ event.preventDefault();
907
+ break;
908
+ case keyCode.ENTER:
909
+ case keyCode.NUMPAD_ENTER:
910
+ // when menu is open and has focus
911
+ if ( self.menu.active ) {
912
+ // #6055 - Opera still allows the keypress to occur
913
+ // which causes forms to submit
914
+ suppressKeyPress = true;
915
+ event.preventDefault();
916
+ }
917
+ //passthrough - ENTER and TAB both select the current element
918
+ case keyCode.TAB:
919
+ if ( !self.menu.active ) {
920
+ return;
921
+ }
922
+ self.menu.select( event );
923
+ break;
924
+ case keyCode.ESCAPE:
925
+ self.element.val( self.term );
926
+ self.close( event );
927
+ break;
928
+ default:
929
+ // keypress is triggered before the input value is changed
930
+ clearTimeout( self.searching );
931
+ self.searching = setTimeout(function() {
932
+ // only search if the value has changed
933
+ if ( self.term != self.element.val() ) {
934
+ self.selectedItem = null;
935
+ self.search( null, event );
936
+ }
937
+ }, self.options.delay );
938
+ break;
939
+ }
940
+ })
941
+ .bind( "keypress.autocomplete", function( event ) {
942
+ if ( suppressKeyPress ) {
943
+ suppressKeyPress = false;
944
+ event.preventDefault();
945
+ }
946
+ })
947
+ .bind( "focus.autocomplete", function() {
948
+ if ( self.options.disabled ) {
949
+ return;
950
+ }
951
+
952
+ self.selectedItem = null;
953
+ self.previous = self.element.val();
954
+ })
955
+ .bind( "blur.autocomplete", function( event ) {
956
+ if ( self.options.disabled ) {
957
+ return;
958
+ }
959
+
960
+ clearTimeout( self.searching );
961
+ // clicks on the menu (or a button to trigger a search) will cause a blur event
962
+ self.closing = setTimeout(function() {
963
+ self.close( event );
964
+ self._change( event );
965
+ }, 150 );
966
+ });
967
+ this._initSource();
968
+ this.response = function() {
969
+ return self._response.apply( self, arguments );
970
+ };
971
+ this.menu = $( "<ul></ul>" )
972
+ .addClass( "ui-autocomplete" )
973
+ .appendTo( $( this.options.appendTo || "body", doc )[0] )
974
+ // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
975
+ .mousedown(function( event ) {
976
+ // clicking on the scrollbar causes focus to shift to the body
977
+ // but we can't detect a mouseup or a click immediately afterward
978
+ // so we have to track the next mousedown and close the menu if
979
+ // the user clicks somewhere outside of the autocomplete
980
+ var menuElement = self.menu.element[ 0 ];
981
+ if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
982
+ setTimeout(function() {
983
+ $( document ).one( 'mousedown', function( event ) {
984
+ if ( event.target !== self.element[ 0 ] &&
985
+ event.target !== menuElement &&
986
+ !$.ui.contains( menuElement, event.target ) ) {
987
+ self.close();
988
+ }
989
+ });
990
+ }, 1 );
991
+ }
992
+
993
+ // use another timeout to make sure the blur-event-handler on the input was already triggered
994
+ setTimeout(function() {
995
+ clearTimeout( self.closing );
996
+ }, 13);
997
+ })
998
+ .menu({
999
+ focus: function( event, ui ) {
1000
+ var item = ui.item.data( "item.autocomplete" );
1001
+ if ( false !== self._trigger( "focus", event, { item: item } ) ) {
1002
+ // use value to match what will end up in the input, if it was a key event
1003
+ if ( /^key/.test(event.originalEvent.type) ) {
1004
+ self.element.val( item.value );
1005
+ }
1006
+ }
1007
+ },
1008
+ selected: function( event, ui ) {
1009
+ var item = ui.item.data( "item.autocomplete" ),
1010
+ previous = self.previous;
1011
+
1012
+ // only trigger when focus was lost (click on menu)
1013
+ if ( self.element[0] !== doc.activeElement ) {
1014
+ self.element.focus();
1015
+ self.previous = previous;
1016
+ // #6109 - IE triggers two focus events and the second
1017
+ // is asynchronous, so we need to reset the previous
1018
+ // term synchronously and asynchronously :-(
1019
+ setTimeout(function() {
1020
+ self.previous = previous;
1021
+ self.selectedItem = item;
1022
+ }, 1);
1023
+ }
1024
+
1025
+ if ( false !== self._trigger( "select", event, { item: item } ) ) {
1026
+ self.element.val( item.value );
1027
+ }
1028
+ // reset the term after the select event
1029
+ // this allows custom select handling to work properly
1030
+ self.term = self.element.val();
1031
+
1032
+ self.close( event );
1033
+ self.selectedItem = item;
1034
+ },
1035
+ blur: function( event, ui ) {
1036
+ // don't set the value of the text field if it's already correct
1037
+ // this prevents moving the cursor unnecessarily
1038
+ if ( self.menu.element.is(":visible") &&
1039
+ ( self.element.val() !== self.term ) ) {
1040
+ self.element.val( self.term );
1041
+ }
1042
+ }
1043
+ })
1044
+ .zIndex( this.element.zIndex() + 1 )
1045
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
1046
+ .css({ top: 0, left: 0 })
1047
+ .hide()
1048
+ .data( "menu" );
1049
+ if ( $.fn.bgiframe ) {
1050
+ this.menu.element.bgiframe();
1051
+ }
1052
+ },
1053
+
1054
+ destroy: function() {
1055
+ this.element
1056
+ .removeClass( "ui-autocomplete-input" )
1057
+ .removeAttr( "autocomplete" )
1058
+ .removeAttr( "role" )
1059
+ .removeAttr( "aria-autocomplete" )
1060
+ .removeAttr( "aria-haspopup" );
1061
+ this.menu.element.remove();
1062
+ $.Widget.prototype.destroy.call( this );
1063
+ },
1064
+
1065
+ _setOption: function( key, value ) {
1066
+ $.Widget.prototype._setOption.apply( this, arguments );
1067
+ if ( key === "source" ) {
1068
+ this._initSource();
1069
+ }
1070
+ if ( key === "appendTo" ) {
1071
+ this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
1072
+ }
1073
+ if ( key === "disabled" && value && this.xhr ) {
1074
+ this.xhr.abort();
1075
+ }
1076
+ },
1077
+
1078
+ _initSource: function() {
1079
+ var self = this,
1080
+ array,
1081
+ url;
1082
+ if ( $.isArray(this.options.source) ) {
1083
+ array = this.options.source;
1084
+ this.source = function( request, response ) {
1085
+ response( $.ui.autocomplete.filter(array, request.term) );
1086
+ };
1087
+ } else if ( typeof this.options.source === "string" ) {
1088
+ url = this.options.source;
1089
+ this.source = function( request, response ) {
1090
+ if ( self.xhr ) {
1091
+ self.xhr.abort();
1092
+ }
1093
+ self.xhr = $.ajax({
1094
+ url: url,
1095
+ data: request,
1096
+ dataType: "json",
1097
+ autocompleteRequest: ++requestIndex,
1098
+ success: function( data, status ) {
1099
+ if ( this.autocompleteRequest === requestIndex ) {
1100
+ response( data );
1101
+ }
1102
+ },
1103
+ error: function() {
1104
+ if ( this.autocompleteRequest === requestIndex ) {
1105
+ response( [] );
1106
+ }
1107
+ }
1108
+ });
1109
+ };
1110
+ } else {
1111
+ this.source = this.options.source;
1112
+ }
1113
+ },
1114
+
1115
+ search: function( value, event ) {
1116
+ value = value != null ? value : this.element.val();
1117
+
1118
+ // always save the actual value, not the one passed as an argument
1119
+ this.term = this.element.val();
1120
+
1121
+ if ( value.length < this.options.minLength ) {
1122
+ return this.close( event );
1123
+ }
1124
+
1125
+ clearTimeout( this.closing );
1126
+ if ( this._trigger( "search", event ) === false ) {
1127
+ return;
1128
+ }
1129
+
1130
+ return this._search( value );
1131
+ },
1132
+
1133
+ _search: function( value ) {
1134
+ this.pending++;
1135
+ this.element.addClass( "ui-autocomplete-loading" );
1136
+
1137
+ this.source( { term: value }, this.response );
1138
+ },
1139
+
1140
+ _response: function( content ) {
1141
+ if ( !this.options.disabled && content && content.length ) {
1142
+ content = this._normalize( content );
1143
+ this._suggest( content );
1144
+ this._trigger( "open" );
1145
+ } else {
1146
+ this.close();
1147
+ }
1148
+ this.pending--;
1149
+ if ( !this.pending ) {
1150
+ this.element.removeClass( "ui-autocomplete-loading" );
1151
+ }
1152
+ },
1153
+
1154
+ close: function( event ) {
1155
+ clearTimeout( this.closing );
1156
+ if ( this.menu.element.is(":visible") ) {
1157
+ this.menu.element.hide();
1158
+ this.menu.deactivate();
1159
+ this._trigger( "close", event );
1160
+ }
1161
+ },
1162
+
1163
+ _change: function( event ) {
1164
+ if ( this.previous !== this.element.val() ) {
1165
+ this._trigger( "change", event, { item: this.selectedItem } );
1166
+ }
1167
+ },
1168
+
1169
+ _normalize: function( items ) {
1170
+ // assume all items have the right format when the first item is complete
1171
+ if ( items.length && items[0].label && items[0].value ) {
1172
+ return items;
1173
+ }
1174
+ return $.map( items, function(item) {
1175
+ if ( typeof item === "string" ) {
1176
+ return {
1177
+ label: item,
1178
+ value: item
1179
+ };
1180
+ }
1181
+ return $.extend({
1182
+ label: item.label || item.value,
1183
+ value: item.value || item.label
1184
+ }, item );
1185
+ });
1186
+ },
1187
+
1188
+ _suggest: function( items ) {
1189
+ var ul = this.menu.element
1190
+ .empty()
1191
+ .zIndex( this.element.zIndex() + 1 );
1192
+ this._renderMenu( ul, items );
1193
+ // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
1194
+ this.menu.deactivate();
1195
+ this.menu.refresh();
1196
+
1197
+ // size and position menu
1198
+ ul.show();
1199
+ this._resizeMenu();
1200
+ ul.position( $.extend({
1201
+ of: this.element
1202
+ }, this.options.position ));
1203
+
1204
+ if ( this.options.autoFocus ) {
1205
+ this.menu.next( new $.Event("mouseover") );
1206
+ }
1207
+ },
1208
+
1209
+ _resizeMenu: function() {
1210
+ var ul = this.menu.element;
1211
+ ul.outerWidth( Math.max(
1212
+ ul.width( "" ).outerWidth(),
1213
+ this.element.outerWidth()
1214
+ ) );
1215
+ },
1216
+
1217
+ _renderMenu: function( ul, items ) {
1218
+ var self = this;
1219
+ $.each( items, function( index, item ) {
1220
+ self._renderItem( ul, item );
1221
+ });
1222
+ },
1223
+
1224
+ _renderItem: function( ul, item) {
1225
+ return $( "<li></li>" )
1226
+ .data( "item.autocomplete", item )
1227
+ .append( $( "<a></a>" ).text( item.label ) )
1228
+ .appendTo( ul );
1229
+ },
1230
+
1231
+ _move: function( direction, event ) {
1232
+ if ( !this.menu.element.is(":visible") ) {
1233
+ this.search( null, event );
1234
+ return;
1235
+ }
1236
+ if ( this.menu.first() && /^previous/.test(direction) ||
1237
+ this.menu.last() && /^next/.test(direction) ) {
1238
+ this.element.val( this.term );
1239
+ this.menu.deactivate();
1240
+ return;
1241
+ }
1242
+ this.menu[ direction ]( event );
1243
+ },
1244
+
1245
+ widget: function() {
1246
+ return this.menu.element;
1247
+ }
1248
+ });
1249
+
1250
+ $.extend( $.ui.autocomplete, {
1251
+ escapeRegex: function( value ) {
1252
+ return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
1253
+ },
1254
+ filter: function(array, term) {
1255
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
1256
+ return $.grep( array, function(value) {
1257
+ return matcher.test( value.label || value.value || value );
1258
+ });
1259
+ }
1260
+ });
1261
+
1262
+ }( jQuery ));
1263
+
1264
+ /*
1265
+ * jQuery UI Menu (not officially released)
1266
+ *
1267
+ * This widget isn't yet finished and the API is subject to change. We plan to finish
1268
+ * it for the next release. You're welcome to give it a try anyway and give us feedback,
1269
+ * as long as you're okay with migrating your code later on. We can help with that, too.
1270
+ *
1271
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1272
+ * Dual licensed under the MIT or GPL Version 2 licenses.
1273
+ * http://jquery.org/license
1274
+ *
1275
+ * http://docs.jquery.com/UI/Menu
1276
+ *
1277
+ * Depends:
1278
+ * jquery.ui.core.js
1279
+ * jquery.ui.widget.js
1280
+ */
1281
+ (function($) {
1282
+
1283
+ $.widget("ui.menu", {
1284
+ _create: function() {
1285
+ var self = this;
1286
+ this.element
1287
+ .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
1288
+ .attr({
1289
+ role: "listbox",
1290
+ "aria-activedescendant": "ui-active-menuitem"
1291
+ })
1292
+ .click(function( event ) {
1293
+ if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
1294
+ return;
1295
+ }
1296
+ // temporary
1297
+ event.preventDefault();
1298
+ self.select( event );
1299
+ });
1300
+ this.refresh();
1301
+ },
1302
+
1303
+ refresh: function() {
1304
+ var self = this;
1305
+
1306
+ // don't refresh list items that are already adapted
1307
+ var items = this.element.children("li:not(.ui-menu-item):has(a)")
1308
+ .addClass("ui-menu-item")
1309
+ .attr("role", "menuitem");
1310
+
1311
+ items.children("a")
1312
+ .addClass("ui-corner-all")
1313
+ .attr("tabindex", -1)
1314
+ // mouseenter doesn't work with event delegation
1315
+ .mouseenter(function( event ) {
1316
+ self.activate( event, $(this).parent() );
1317
+ })
1318
+ .mouseleave(function() {
1319
+ self.deactivate();
1320
+ });
1321
+ },
1322
+
1323
+ activate: function( event, item ) {
1324
+ this.deactivate();
1325
+ if (this.hasScroll()) {
1326
+ var offset = item.offset().top - this.element.offset().top,
1327
+ scroll = this.element.scrollTop(),
1328
+ elementHeight = this.element.height();
1329
+ if (offset < 0) {
1330
+ this.element.scrollTop( scroll + offset);
1331
+ } else if (offset >= elementHeight) {
1332
+ this.element.scrollTop( scroll + offset - elementHeight + item.height());
1333
+ }
1334
+ }
1335
+ this.active = item.eq(0)
1336
+ .children("a")
1337
+ .addClass("ui-state-hover")
1338
+ .attr("id", "ui-active-menuitem")
1339
+ .end();
1340
+ this._trigger("focus", event, { item: item });
1341
+ },
1342
+
1343
+ deactivate: function() {
1344
+ if (!this.active) { return; }
1345
+
1346
+ this.active.children("a")
1347
+ .removeClass("ui-state-hover")
1348
+ .removeAttr("id");
1349
+ this._trigger("blur");
1350
+ this.active = null;
1351
+ },
1352
+
1353
+ next: function(event) {
1354
+ this.move("next", ".ui-menu-item:first", event);
1355
+ },
1356
+
1357
+ previous: function(event) {
1358
+ this.move("prev", ".ui-menu-item:last", event);
1359
+ },
1360
+
1361
+ first: function() {
1362
+ return this.active && !this.active.prevAll(".ui-menu-item").length;
1363
+ },
1364
+
1365
+ last: function() {
1366
+ return this.active && !this.active.nextAll(".ui-menu-item").length;
1367
+ },
1368
+
1369
+ move: function(direction, edge, event) {
1370
+ if (!this.active) {
1371
+ this.activate(event, this.element.children(edge));
1372
+ return;
1373
+ }
1374
+ var next = this.active[direction + "All"](".ui-menu-item").eq(0);
1375
+ if (next.length) {
1376
+ this.activate(event, next);
1377
+ } else {
1378
+ this.activate(event, this.element.children(edge));
1379
+ }
1380
+ },
1381
+
1382
+ // TODO merge with previousPage
1383
+ nextPage: function(event) {
1384
+ if (this.hasScroll()) {
1385
+ // TODO merge with no-scroll-else
1386
+ if (!this.active || this.last()) {
1387
+ this.activate(event, this.element.children(".ui-menu-item:first"));
1388
+ return;
1389
+ }
1390
+ var base = this.active.offset().top,
1391
+ height = this.element.height(),
1392
+ result = this.element.children(".ui-menu-item").filter(function() {
1393
+ var close = $(this).offset().top - base - height + $(this).height();
1394
+ // TODO improve approximation
1395
+ return close < 10 && close > -10;
1396
+ });
1397
+
1398
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
1399
+ if (!result.length) {
1400
+ result = this.element.children(".ui-menu-item:last");
1401
+ }
1402
+ this.activate(event, result);
1403
+ } else {
1404
+ this.activate(event, this.element.children(".ui-menu-item")
1405
+ .filter(!this.active || this.last() ? ":first" : ":last"));
1406
+ }
1407
+ },
1408
+
1409
+ // TODO merge with nextPage
1410
+ previousPage: function(event) {
1411
+ if (this.hasScroll()) {
1412
+ // TODO merge with no-scroll-else
1413
+ if (!this.active || this.first()) {
1414
+ this.activate(event, this.element.children(".ui-menu-item:last"));
1415
+ return;
1416
+ }
1417
+
1418
+ var base = this.active.offset().top,
1419
+ height = this.element.height();
1420
+ result = this.element.children(".ui-menu-item").filter(function() {
1421
+ var close = $(this).offset().top - base + height - $(this).height();
1422
+ // TODO improve approximation
1423
+ return close < 10 && close > -10;
1424
+ });
1425
+
1426
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
1427
+ if (!result.length) {
1428
+ result = this.element.children(".ui-menu-item:first");
1429
+ }
1430
+ this.activate(event, result);
1431
+ } else {
1432
+ this.activate(event, this.element.children(".ui-menu-item")
1433
+ .filter(!this.active || this.first() ? ":last" : ":first"));
1434
+ }
1435
+ },
1436
+
1437
+ hasScroll: function() {
1438
+ return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
1439
+ },
1440
+
1441
+ select: function( event ) {
1442
+ this._trigger("selected", event, { item: this.active });
1443
+ }
1444
+ });
1445
+
1446
+ }(jQuery));
1447
+ /*
1448
+ * jQuery UI Datepicker 1.8.16
1449
+ *
1450
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1451
+ * Dual licensed under the MIT or GPL Version 2 licenses.
1452
+ * http://jquery.org/license
1453
+ *
1454
+ * http://docs.jquery.com/UI/Datepicker
1455
+ *
1456
+ * Depends:
1457
+ * jquery.ui.core.js
1458
+ */
1459
+ (function( $, undefined ) {
1460
+
1461
+ $.extend($.ui, { datepicker: { version: "1.8.16" } });
1462
+
1463
+ var PROP_NAME = 'datepicker';
1464
+ var dpuuid = new Date().getTime();
1465
+ var instActive;
1466
+
1467
+ /* Date picker manager.
1468
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
1469
+ Settings for (groups of) date pickers are maintained in an instance object,
1470
+ allowing multiple different settings on the same page. */
1471
+
1472
+ function Datepicker() {
1473
+ this.debug = false; // Change this to true to start debugging
1474
+ this._curInst = null; // The current instance in use
1475
+ this._keyEvent = false; // If the last event was a key event
1476
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
1477
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
1478
+ this._inDialog = false; // True if showing within a "dialog", false if not
1479
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
1480
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
1481
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
1482
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
1483
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
1484
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
1485
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
1486
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
1487
+ this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
1488
+ this.regional = []; // Available regional settings, indexed by language code
1489
+ this.regional[''] = { // Default regional settings
1490
+ closeText: 'Done', // Display text for close link
1491
+ prevText: 'Prev', // Display text for previous month link
1492
+ nextText: 'Next', // Display text for next month link
1493
+ currentText: 'Today', // Display text for current month link
1494
+ monthNames: ['January','February','March','April','May','June',
1495
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
1496
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
1497
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
1498
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
1499
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
1500
+ weekHeader: 'Wk', // Column header for week of the year
1501
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
1502
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
1503
+ isRTL: false, // True if right-to-left language, false if left-to-right
1504
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
1505
+ yearSuffix: '' // Additional text to append to the year in the month headers
1506
+ };
1507
+ this._defaults = { // Global defaults for all the date picker instances
1508
+ showOn: 'focus', // 'focus' for popup on focus,
1509
+ // 'button' for trigger button, or 'both' for either
1510
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
1511
+ showOptions: {}, // Options for enhanced animations
1512
+ defaultDate: null, // Used when field is blank: actual date,
1513
+ // +/-number for offset from today, null for today
1514
+ appendText: '', // Display text following the input box, e.g. showing the format
1515
+ buttonText: '...', // Text for trigger button
1516
+ buttonImage: '', // URL for trigger button image
1517
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
1518
+ hideIfNoPrevNext: false, // True to hide next/previous month links
1519
+ // if not applicable, false to just disable them
1520
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
1521
+ gotoCurrent: false, // True if today link goes back to current selection instead
1522
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
1523
+ changeYear: false, // True if year can be selected directly, false if only prev/next
1524
+ yearRange: 'c-10:c+10', // Range of years to display in drop-down,
1525
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
1526
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
1527
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
1528
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
1529
+ showWeek: false, // True to show week of the year, false to not show it
1530
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
1531
+ // takes a Date and returns the number of the week for it
1532
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
1533
+ // > this are in the previous century,
1534
+ // string value starting with '+' for current year + value
1535
+ minDate: null, // The earliest selectable date, or null for no limit
1536
+ maxDate: null, // The latest selectable date, or null for no limit
1537
+ duration: 'fast', // Duration of display/closure
1538
+ beforeShowDay: null, // Function that takes a date and returns an array with
1539
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
1540
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
1541
+ beforeShow: null, // Function that takes an input field and
1542
+ // returns a set of custom settings for the date picker
1543
+ onSelect: null, // Define a callback function when a date is selected
1544
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
1545
+ onClose: null, // Define a callback function when the datepicker is closed
1546
+ numberOfMonths: 1, // Number of months to show at a time
1547
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
1548
+ stepMonths: 1, // Number of months to step back/forward
1549
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
1550
+ altField: '', // Selector for an alternate field to store selected dates into
1551
+ altFormat: '', // The date format to use for the alternate field
1552
+ constrainInput: true, // The input is constrained by the current date format
1553
+ showButtonPanel: false, // True to show button panel, false to not show it
1554
+ autoSize: false, // True to size the input for the date format, false to leave as is
1555
+ disabled: false // The initial disabled state
1556
+ };
1557
+ $.extend(this._defaults, this.regional['']);
1558
+ this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
1559
+ }
1560
+
1561
+ $.extend(Datepicker.prototype, {
1562
+ /* Class name added to elements to indicate already configured with a date picker. */
1563
+ markerClassName: 'hasDatepicker',
1564
+
1565
+ //Keep track of the maximum number of rows displayed (see #7043)
1566
+ maxRows: 4,
1567
+
1568
+ /* Debug logging (if enabled). */
1569
+ log: function () {
1570
+ if (this.debug)
1571
+ console.log.apply('', arguments);
1572
+ },
1573
+
1574
+ // TODO rename to "widget" when switching to widget factory
1575
+ _widgetDatepicker: function() {
1576
+ return this.dpDiv;
1577
+ },
1578
+
1579
+ /* Override the default settings for all instances of the date picker.
1580
+ @param settings object - the new settings to use as defaults (anonymous object)
1581
+ @return the manager object */
1582
+ setDefaults: function(settings) {
1583
+ extendRemove(this._defaults, settings || {});
1584
+ return this;
1585
+ },
1586
+
1587
+ /* Attach the date picker to a jQuery selection.
1588
+ @param target element - the target input field or division or span
1589
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
1590
+ _attachDatepicker: function(target, settings) {
1591
+ // check for settings on the control itself - in namespace 'date:'
1592
+ var inlineSettings = null;
1593
+ for (var attrName in this._defaults) {
1594
+ var attrValue = target.getAttribute('date:' + attrName);
1595
+ if (attrValue) {
1596
+ inlineSettings = inlineSettings || {};
1597
+ try {
1598
+ inlineSettings[attrName] = eval(attrValue);
1599
+ } catch (err) {
1600
+ inlineSettings[attrName] = attrValue;
1601
+ }
1602
+ }
1603
+ }
1604
+ var nodeName = target.nodeName.toLowerCase();
1605
+ var inline = (nodeName == 'div' || nodeName == 'span');
1606
+ if (!target.id) {
1607
+ this.uuid += 1;
1608
+ target.id = 'dp' + this.uuid;
1609
+ }
1610
+ var inst = this._newInst($(target), inline);
1611
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
1612
+ if (nodeName == 'input') {
1613
+ this._connectDatepicker(target, inst);
1614
+ } else if (inline) {
1615
+ this._inlineDatepicker(target, inst);
1616
+ }
1617
+ },
1618
+
1619
+ /* Create a new instance object. */
1620
+ _newInst: function(target, inline) {
1621
+ var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
1622
+ return {id: id, input: target, // associated target
1623
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
1624
+ drawMonth: 0, drawYear: 0, // month being drawn
1625
+ inline: inline, // is datepicker inline or not
1626
+ dpDiv: (!inline ? this.dpDiv : // presentation div
1627
+ bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
1628
+ },
1629
+
1630
+ /* Attach the date picker to an input field. */
1631
+ _connectDatepicker: function(target, inst) {
1632
+ var input = $(target);
1633
+ inst.append = $([]);
1634
+ inst.trigger = $([]);
1635
+ if (input.hasClass(this.markerClassName))
1636
+ return;
1637
+ this._attachments(input, inst);
1638
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
1639
+ keypress(this._doKeyPress).keyup(this._doKeyUp).
1640
+ bind("setData.datepicker", function(event, key, value) {
1641
+ inst.settings[key] = value;
1642
+ }).bind("getData.datepicker", function(event, key) {
1643
+ return this._get(inst, key);
1644
+ });
1645
+ this._autoSize(inst);
1646
+ $.data(target, PROP_NAME, inst);
1647
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
1648
+ if( inst.settings.disabled ) {
1649
+ this._disableDatepicker( target );
1650
+ }
1651
+ },
1652
+
1653
+ /* Make attachments based on settings. */
1654
+ _attachments: function(input, inst) {
1655
+ var appendText = this._get(inst, 'appendText');
1656
+ var isRTL = this._get(inst, 'isRTL');
1657
+ if (inst.append)
1658
+ inst.append.remove();
1659
+ if (appendText) {
1660
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
1661
+ input[isRTL ? 'before' : 'after'](inst.append);
1662
+ }
1663
+ input.unbind('focus', this._showDatepicker);
1664
+ if (inst.trigger)
1665
+ inst.trigger.remove();
1666
+ var showOn = this._get(inst, 'showOn');
1667
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
1668
+ input.focus(this._showDatepicker);
1669
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
1670
+ var buttonText = this._get(inst, 'buttonText');
1671
+ var buttonImage = this._get(inst, 'buttonImage');
1672
+ inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
1673
+ $('<img/>').addClass(this._triggerClass).
1674
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
1675
+ $('<button type="button"></button>').addClass(this._triggerClass).
1676
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
1677
+ { src:buttonImage, alt:buttonText, title:buttonText })));
1678
+ input[isRTL ? 'before' : 'after'](inst.trigger);
1679
+ inst.trigger.click(function() {
1680
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
1681
+ $.datepicker._hideDatepicker();
1682
+ else
1683
+ $.datepicker._showDatepicker(input[0]);
1684
+ return false;
1685
+ });
1686
+ }
1687
+ },
1688
+
1689
+ /* Apply the maximum length for the date format. */
1690
+ _autoSize: function(inst) {
1691
+ if (this._get(inst, 'autoSize') && !inst.inline) {
1692
+ var date = new Date(2009, 12 - 1, 20); // Ensure double digits
1693
+ var dateFormat = this._get(inst, 'dateFormat');
1694
+ if (dateFormat.match(/[DM]/)) {
1695
+ var findMax = function(names) {
1696
+ var max = 0;
1697
+ var maxI = 0;
1698
+ for (var i = 0; i < names.length; i++) {
1699
+ if (names[i].length > max) {
1700
+ max = names[i].length;
1701
+ maxI = i;
1702
+ }
1703
+ }
1704
+ return maxI;
1705
+ };
1706
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
1707
+ 'monthNames' : 'monthNamesShort'))));
1708
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
1709
+ 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
1710
+ }
1711
+ inst.input.attr('size', this._formatDate(inst, date).length);
1712
+ }
1713
+ },
1714
+
1715
+ /* Attach an inline date picker to a div. */
1716
+ _inlineDatepicker: function(target, inst) {
1717
+ var divSpan = $(target);
1718
+ if (divSpan.hasClass(this.markerClassName))
1719
+ return;
1720
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
1721
+ bind("setData.datepicker", function(event, key, value){
1722
+ inst.settings[key] = value;
1723
+ }).bind("getData.datepicker", function(event, key){
1724
+ return this._get(inst, key);
1725
+ });
1726
+ $.data(target, PROP_NAME, inst);
1727
+ this._setDate(inst, this._getDefaultDate(inst), true);
1728
+ this._updateDatepicker(inst);
1729
+ this._updateAlternate(inst);
1730
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
1731
+ if( inst.settings.disabled ) {
1732
+ this._disableDatepicker( target );
1733
+ }
1734
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
1735
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
1736
+ inst.dpDiv.css( "display", "block" );
1737
+ },
1738
+
1739
+ /* Pop-up the date picker in a "dialog" box.
1740
+ @param input element - ignored
1741
+ @param date string or Date - the initial date to display
1742
+ @param onSelect function - the function to call when a date is selected
1743
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
1744
+ @param pos int[2] - coordinates for the dialog's position within the screen or
1745
+ event - with x/y coordinates or
1746
+ leave empty for default (screen centre)
1747
+ @return the manager object */
1748
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
1749
+ var inst = this._dialogInst; // internal instance
1750
+ if (!inst) {
1751
+ this.uuid += 1;
1752
+ var id = 'dp' + this.uuid;
1753
+ this._dialogInput = $('<input type="text" id="' + id +
1754
+ '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
1755
+ this._dialogInput.keydown(this._doKeyDown);
1756
+ $('body').append(this._dialogInput);
1757
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
1758
+ inst.settings = {};
1759
+ $.data(this._dialogInput[0], PROP_NAME, inst);
1760
+ }
1761
+ extendRemove(inst.settings, settings || {});
1762
+ date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
1763
+ this._dialogInput.val(date);
1764
+
1765
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
1766
+ if (!this._pos) {
1767
+ var browserWidth = document.documentElement.clientWidth;
1768
+ var browserHeight = document.documentElement.clientHeight;
1769
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
1770
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
1771
+ this._pos = // should use actual width/height below
1772
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
1773
+ }
1774
+
1775
+ // move input on screen for focus, but hidden behind dialog
1776
+ this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
1777
+ inst.settings.onSelect = onSelect;
1778
+ this._inDialog = true;
1779
+ this.dpDiv.addClass(this._dialogClass);
1780
+ this._showDatepicker(this._dialogInput[0]);
1781
+ if ($.blockUI)
1782
+ $.blockUI(this.dpDiv);
1783
+ $.data(this._dialogInput[0], PROP_NAME, inst);
1784
+ return this;
1785
+ },
1786
+
1787
+ /* Detach a datepicker from its control.
1788
+ @param target element - the target input field or division or span */
1789
+ _destroyDatepicker: function(target) {
1790
+ var $target = $(target);
1791
+ var inst = $.data(target, PROP_NAME);
1792
+ if (!$target.hasClass(this.markerClassName)) {
1793
+ return;
1794
+ }
1795
+ var nodeName = target.nodeName.toLowerCase();
1796
+ $.removeData(target, PROP_NAME);
1797
+ if (nodeName == 'input') {
1798
+ inst.append.remove();
1799
+ inst.trigger.remove();
1800
+ $target.removeClass(this.markerClassName).
1801
+ unbind('focus', this._showDatepicker).
1802
+ unbind('keydown', this._doKeyDown).
1803
+ unbind('keypress', this._doKeyPress).
1804
+ unbind('keyup', this._doKeyUp);
1805
+ } else if (nodeName == 'div' || nodeName == 'span')
1806
+ $target.removeClass(this.markerClassName).empty();
1807
+ },
1808
+
1809
+ /* Enable the date picker to a jQuery selection.
1810
+ @param target element - the target input field or division or span */
1811
+ _enableDatepicker: function(target) {
1812
+ var $target = $(target);
1813
+ var inst = $.data(target, PROP_NAME);
1814
+ if (!$target.hasClass(this.markerClassName)) {
1815
+ return;
1816
+ }
1817
+ var nodeName = target.nodeName.toLowerCase();
1818
+ if (nodeName == 'input') {
1819
+ target.disabled = false;
1820
+ inst.trigger.filter('button').
1821
+ each(function() { this.disabled = false; }).end().
1822
+ filter('img').css({opacity: '1.0', cursor: ''});
1823
+ }
1824
+ else if (nodeName == 'div' || nodeName == 'span') {
1825
+ var inline = $target.children('.' + this._inlineClass);
1826
+ inline.children().removeClass('ui-state-disabled');
1827
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
1828
+ removeAttr("disabled");
1829
+ }
1830
+ this._disabledInputs = $.map(this._disabledInputs,
1831
+ function(value) { return (value == target ? null : value); }); // delete entry
1832
+ },
1833
+
1834
+ /* Disable the date picker to a jQuery selection.
1835
+ @param target element - the target input field or division or span */
1836
+ _disableDatepicker: function(target) {
1837
+ var $target = $(target);
1838
+ var inst = $.data(target, PROP_NAME);
1839
+ if (!$target.hasClass(this.markerClassName)) {
1840
+ return;
1841
+ }
1842
+ var nodeName = target.nodeName.toLowerCase();
1843
+ if (nodeName == 'input') {
1844
+ target.disabled = true;
1845
+ inst.trigger.filter('button').
1846
+ each(function() { this.disabled = true; }).end().
1847
+ filter('img').css({opacity: '0.5', cursor: 'default'});
1848
+ }
1849
+ else if (nodeName == 'div' || nodeName == 'span') {
1850
+ var inline = $target.children('.' + this._inlineClass);
1851
+ inline.children().addClass('ui-state-disabled');
1852
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
1853
+ attr("disabled", "disabled");
1854
+ }
1855
+ this._disabledInputs = $.map(this._disabledInputs,
1856
+ function(value) { return (value == target ? null : value); }); // delete entry
1857
+ this._disabledInputs[this._disabledInputs.length] = target;
1858
+ },
1859
+
1860
+ /* Is the first field in a jQuery collection disabled as a datepicker?
1861
+ @param target element - the target input field or division or span
1862
+ @return boolean - true if disabled, false if enabled */
1863
+ _isDisabledDatepicker: function(target) {
1864
+ if (!target) {
1865
+ return false;
1866
+ }
1867
+ for (var i = 0; i < this._disabledInputs.length; i++) {
1868
+ if (this._disabledInputs[i] == target)
1869
+ return true;
1870
+ }
1871
+ return false;
1872
+ },
1873
+
1874
+ /* Retrieve the instance data for the target control.
1875
+ @param target element - the target input field or division or span
1876
+ @return object - the associated instance data
1877
+ @throws error if a jQuery problem getting data */
1878
+ _getInst: function(target) {
1879
+ try {
1880
+ return $.data(target, PROP_NAME);
1881
+ }
1882
+ catch (err) {
1883
+ throw 'Missing instance data for this datepicker';
1884
+ }
1885
+ },
1886
+
1887
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
1888
+ @param target element - the target input field or division or span
1889
+ @param name object - the new settings to update or
1890
+ string - the name of the setting to change or retrieve,
1891
+ when retrieving also 'all' for all instance settings or
1892
+ 'defaults' for all global defaults
1893
+ @param value any - the new value for the setting
1894
+ (omit if above is an object or to retrieve a value) */
1895
+ _optionDatepicker: function(target, name, value) {
1896
+ var inst = this._getInst(target);
1897
+ if (arguments.length == 2 && typeof name == 'string') {
1898
+ return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
1899
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
1900
+ this._get(inst, name)) : null));
1901
+ }
1902
+ var settings = name || {};
1903
+ if (typeof name == 'string') {
1904
+ settings = {};
1905
+ settings[name] = value;
1906
+ }
1907
+ if (inst) {
1908
+ if (this._curInst == inst) {
1909
+ this._hideDatepicker();
1910
+ }
1911
+ var date = this._getDateDatepicker(target, true);
1912
+ var minDate = this._getMinMaxDate(inst, 'min');
1913
+ var maxDate = this._getMinMaxDate(inst, 'max');
1914
+ extendRemove(inst.settings, settings);
1915
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
1916
+ if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
1917
+ inst.settings.minDate = this._formatDate(inst, minDate);
1918
+ if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
1919
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
1920
+ this._attachments($(target), inst);
1921
+ this._autoSize(inst);
1922
+ this._setDate(inst, date);
1923
+ this._updateAlternate(inst);
1924
+ this._updateDatepicker(inst);
1925
+ }
1926
+ },
1927
+
1928
+ // change method deprecated
1929
+ _changeDatepicker: function(target, name, value) {
1930
+ this._optionDatepicker(target, name, value);
1931
+ },
1932
+
1933
+ /* Redraw the date picker attached to an input field or division.
1934
+ @param target element - the target input field or division or span */
1935
+ _refreshDatepicker: function(target) {
1936
+ var inst = this._getInst(target);
1937
+ if (inst) {
1938
+ this._updateDatepicker(inst);
1939
+ }
1940
+ },
1941
+
1942
+ /* Set the dates for a jQuery selection.
1943
+ @param target element - the target input field or division or span
1944
+ @param date Date - the new date */
1945
+ _setDateDatepicker: function(target, date) {
1946
+ var inst = this._getInst(target);
1947
+ if (inst) {
1948
+ this._setDate(inst, date);
1949
+ this._updateDatepicker(inst);
1950
+ this._updateAlternate(inst);
1951
+ }
1952
+ },
1953
+
1954
+ /* Get the date(s) for the first entry in a jQuery selection.
1955
+ @param target element - the target input field or division or span
1956
+ @param noDefault boolean - true if no default date is to be used
1957
+ @return Date - the current date */
1958
+ _getDateDatepicker: function(target, noDefault) {
1959
+ var inst = this._getInst(target);
1960
+ if (inst && !inst.inline)
1961
+ this._setDateFromField(inst, noDefault);
1962
+ return (inst ? this._getDate(inst) : null);
1963
+ },
1964
+
1965
+ /* Handle keystrokes. */
1966
+ _doKeyDown: function(event) {
1967
+ var inst = $.datepicker._getInst(event.target);
1968
+ var handled = true;
1969
+ var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
1970
+ inst._keyEvent = true;
1971
+ if ($.datepicker._datepickerShowing)
1972
+ switch (event.keyCode) {
1973
+ case 9: $.datepicker._hideDatepicker();
1974
+ handled = false;
1975
+ break; // hide on tab out
1976
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
1977
+ $.datepicker._currentClass + ')', inst.dpDiv);
1978
+ if (sel[0])
1979
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
1980
+ var onSelect = $.datepicker._get(inst, 'onSelect');
1981
+ if (onSelect) {
1982
+ var dateStr = $.datepicker._formatDate(inst);
1983
+
1984
+ // trigger custom callback
1985
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
1986
+ }
1987
+ else
1988
+ $.datepicker._hideDatepicker();
1989
+ return false; // don't submit the form
1990
+ break; // select the value on enter
1991
+ case 27: $.datepicker._hideDatepicker();
1992
+ break; // hide on escape
1993
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
1994
+ -$.datepicker._get(inst, 'stepBigMonths') :
1995
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
1996
+ break; // previous month/year on page up/+ ctrl
1997
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
1998
+ +$.datepicker._get(inst, 'stepBigMonths') :
1999
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
2000
+ break; // next month/year on page down/+ ctrl
2001
+ case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
2002
+ handled = event.ctrlKey || event.metaKey;
2003
+ break; // clear on ctrl or command +end
2004
+ case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
2005
+ handled = event.ctrlKey || event.metaKey;
2006
+ break; // current on ctrl or command +home
2007
+ case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
2008
+ handled = event.ctrlKey || event.metaKey;
2009
+ // -1 day on ctrl or command +left
2010
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
2011
+ -$.datepicker._get(inst, 'stepBigMonths') :
2012
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
2013
+ // next month/year on alt +left on Mac
2014
+ break;
2015
+ case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
2016
+ handled = event.ctrlKey || event.metaKey;
2017
+ break; // -1 week on ctrl or command +up
2018
+ case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
2019
+ handled = event.ctrlKey || event.metaKey;
2020
+ // +1 day on ctrl or command +right
2021
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
2022
+ +$.datepicker._get(inst, 'stepBigMonths') :
2023
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
2024
+ // next month/year on alt +right
2025
+ break;
2026
+ case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
2027
+ handled = event.ctrlKey || event.metaKey;
2028
+ break; // +1 week on ctrl or command +down
2029
+ default: handled = false;
2030
+ }
2031
+ else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
2032
+ $.datepicker._showDatepicker(this);
2033
+ else {
2034
+ handled = false;
2035
+ }
2036
+ if (handled) {
2037
+ event.preventDefault();
2038
+ event.stopPropagation();
2039
+ }
2040
+ },
2041
+
2042
+ /* Filter entered characters - based on date format. */
2043
+ _doKeyPress: function(event) {
2044
+ var inst = $.datepicker._getInst(event.target);
2045
+ if ($.datepicker._get(inst, 'constrainInput')) {
2046
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
2047
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
2048
+ return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
2049
+ }
2050
+ },
2051
+
2052
+ /* Synchronise manual entry and field/alternate field. */
2053
+ _doKeyUp: function(event) {
2054
+ var inst = $.datepicker._getInst(event.target);
2055
+ if (inst.input.val() != inst.lastVal) {
2056
+ try {
2057
+ var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
2058
+ (inst.input ? inst.input.val() : null),
2059
+ $.datepicker._getFormatConfig(inst));
2060
+ if (date) { // only if valid
2061
+ $.datepicker._setDateFromField(inst);
2062
+ $.datepicker._updateAlternate(inst);
2063
+ $.datepicker._updateDatepicker(inst);
2064
+ }
2065
+ }
2066
+ catch (event) {
2067
+ $.datepicker.log(event);
2068
+ }
2069
+ }
2070
+ return true;
2071
+ },
2072
+
2073
+ /* Pop-up the date picker for a given input field.
2074
+ If false returned from beforeShow event handler do not show.
2075
+ @param input element - the input field attached to the date picker or
2076
+ event - if triggered by focus */
2077
+ _showDatepicker: function(input) {
2078
+ input = input.target || input;
2079
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
2080
+ input = $('input', input.parentNode)[0];
2081
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
2082
+ return;
2083
+ var inst = $.datepicker._getInst(input);
2084
+ if ($.datepicker._curInst && $.datepicker._curInst != inst) {
2085
+ if ( $.datepicker._datepickerShowing ) {
2086
+ $.datepicker._triggerOnClose($.datepicker._curInst);
2087
+ }
2088
+ $.datepicker._curInst.dpDiv.stop(true, true);
2089
+ }
2090
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
2091
+ var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
2092
+ if(beforeShowSettings === false){
2093
+ //false
2094
+ return;
2095
+ }
2096
+ extendRemove(inst.settings, beforeShowSettings);
2097
+ inst.lastVal = null;
2098
+ $.datepicker._lastInput = input;
2099
+ $.datepicker._setDateFromField(inst);
2100
+ if ($.datepicker._inDialog) // hide cursor
2101
+ input.value = '';
2102
+ if (!$.datepicker._pos) { // position below input
2103
+ $.datepicker._pos = $.datepicker._findPos(input);
2104
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
2105
+ }
2106
+ var isFixed = false;
2107
+ $(input).parents().each(function() {
2108
+ isFixed |= $(this).css('position') == 'fixed';
2109
+ return !isFixed;
2110
+ });
2111
+ if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
2112
+ $.datepicker._pos[0] -= document.documentElement.scrollLeft;
2113
+ $.datepicker._pos[1] -= document.documentElement.scrollTop;
2114
+ }
2115
+ var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
2116
+ $.datepicker._pos = null;
2117
+ //to avoid flashes on Firefox
2118
+ inst.dpDiv.empty();
2119
+ // determine sizing offscreen
2120
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
2121
+ $.datepicker._updateDatepicker(inst);
2122
+ // fix width for dynamic number of date pickers
2123
+ // and adjust position before showing
2124
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
2125
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
2126
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
2127
+ left: offset.left + 'px', top: offset.top + 'px'});
2128
+ if (!inst.inline) {
2129
+ var showAnim = $.datepicker._get(inst, 'showAnim');
2130
+ var duration = $.datepicker._get(inst, 'duration');
2131
+ var postProcess = function() {
2132
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
2133
+ if( !! cover.length ){
2134
+ var borders = $.datepicker._getBorders(inst.dpDiv);
2135
+ cover.css({left: -borders[0], top: -borders[1],
2136
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
2137
+ }
2138
+ };
2139
+ inst.dpDiv.zIndex($(input).zIndex()+1);
2140
+ $.datepicker._datepickerShowing = true;
2141
+ if ($.effects && $.effects[showAnim])
2142
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
2143
+ else
2144
+ inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
2145
+ if (!showAnim || !duration)
2146
+ postProcess();
2147
+ if (inst.input.is(':visible') && !inst.input.is(':disabled'))
2148
+ inst.input.focus();
2149
+ $.datepicker._curInst = inst;
2150
+ }
2151
+ },
2152
+
2153
+ /* Generate the date picker content. */
2154
+ _updateDatepicker: function(inst) {
2155
+ var self = this;
2156
+ self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
2157
+ var borders = $.datepicker._getBorders(inst.dpDiv);
2158
+ instActive = inst; // for delegate hover events
2159
+ inst.dpDiv.empty().append(this._generateHTML(inst));
2160
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
2161
+ if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
2162
+ cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
2163
+ }
2164
+ inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
2165
+ var numMonths = this._getNumberOfMonths(inst);
2166
+ var cols = numMonths[1];
2167
+ var width = 17;
2168
+ inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
2169
+ if (cols > 1)
2170
+ inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
2171
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
2172
+ 'Class']('ui-datepicker-multi');
2173
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
2174
+ 'Class']('ui-datepicker-rtl');
2175
+ if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
2176
+ // #6694 - don't focus the input if it's already focused
2177
+ // this breaks the change event in IE
2178
+ inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
2179
+ inst.input.focus();
2180
+ // deffered render of the years select (to avoid flashes on Firefox)
2181
+ if( inst.yearshtml ){
2182
+ var origyearshtml = inst.yearshtml;
2183
+ setTimeout(function(){
2184
+ //assure that inst.yearshtml didn't change.
2185
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
2186
+ inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
2187
+ }
2188
+ origyearshtml = inst.yearshtml = null;
2189
+ }, 0);
2190
+ }
2191
+ },
2192
+
2193
+ /* Retrieve the size of left and top borders for an element.
2194
+ @param elem (jQuery object) the element of interest
2195
+ @return (number[2]) the left and top borders */
2196
+ _getBorders: function(elem) {
2197
+ var convert = function(value) {
2198
+ return {thin: 1, medium: 2, thick: 3}[value] || value;
2199
+ };
2200
+ return [parseFloat(convert(elem.css('border-left-width'))),
2201
+ parseFloat(convert(elem.css('border-top-width')))];
2202
+ },
2203
+
2204
+ /* Check positioning to remain on screen. */
2205
+ _checkOffset: function(inst, offset, isFixed) {
2206
+ var dpWidth = inst.dpDiv.outerWidth();
2207
+ var dpHeight = inst.dpDiv.outerHeight();
2208
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
2209
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
2210
+ var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
2211
+ var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
2212
+
2213
+ offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
2214
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
2215
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
2216
+
2217
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
2218
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
2219
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
2220
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
2221
+ Math.abs(dpHeight + inputHeight) : 0);
2222
+
2223
+ return offset;
2224
+ },
2225
+
2226
+ /* Find an object's position on the screen. */
2227
+ _findPos: function(obj) {
2228
+ var inst = this._getInst(obj);
2229
+ var isRTL = this._get(inst, 'isRTL');
2230
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
2231
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
2232
+ }
2233
+ var position = $(obj).offset();
2234
+ return [position.left, position.top];
2235
+ },
2236
+
2237
+ /* Trigger custom callback of onClose. */
2238
+ _triggerOnClose: function(inst) {
2239
+ var onClose = this._get(inst, 'onClose');
2240
+ if (onClose)
2241
+ onClose.apply((inst.input ? inst.input[0] : null),
2242
+ [(inst.input ? inst.input.val() : ''), inst]);
2243
+ },
2244
+
2245
+ /* Hide the date picker from view.
2246
+ @param input element - the input field attached to the date picker */
2247
+ _hideDatepicker: function(input) {
2248
+ var inst = this._curInst;
2249
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
2250
+ return;
2251
+ if (this._datepickerShowing) {
2252
+ var showAnim = this._get(inst, 'showAnim');
2253
+ var duration = this._get(inst, 'duration');
2254
+ var postProcess = function() {
2255
+ $.datepicker._tidyDialog(inst);
2256
+ this._curInst = null;
2257
+ };
2258
+ if ($.effects && $.effects[showAnim])
2259
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
2260
+ else
2261
+ inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
2262
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
2263
+ if (!showAnim)
2264
+ postProcess();
2265
+ $.datepicker._triggerOnClose(inst);
2266
+ this._datepickerShowing = false;
2267
+ this._lastInput = null;
2268
+ if (this._inDialog) {
2269
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
2270
+ if ($.blockUI) {
2271
+ $.unblockUI();
2272
+ $('body').append(this.dpDiv);
2273
+ }
2274
+ }
2275
+ this._inDialog = false;
2276
+ }
2277
+ },
2278
+
2279
+ /* Tidy up after a dialog display. */
2280
+ _tidyDialog: function(inst) {
2281
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
2282
+ },
2283
+
2284
+ /* Close date picker if clicked elsewhere. */
2285
+ _checkExternalClick: function(event) {
2286
+ if (!$.datepicker._curInst)
2287
+ return;
2288
+ var $target = $(event.target);
2289
+ if ($target[0].id != $.datepicker._mainDivId &&
2290
+ $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
2291
+ !$target.hasClass($.datepicker.markerClassName) &&
2292
+ !$target.hasClass($.datepicker._triggerClass) &&
2293
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
2294
+ $.datepicker._hideDatepicker();
2295
+ },
2296
+
2297
+ /* Adjust one of the date sub-fields. */
2298
+ _adjustDate: function(id, offset, period) {
2299
+ var target = $(id);
2300
+ var inst = this._getInst(target[0]);
2301
+ if (this._isDisabledDatepicker(target[0])) {
2302
+ return;
2303
+ }
2304
+ this._adjustInstDate(inst, offset +
2305
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
2306
+ period);
2307
+ this._updateDatepicker(inst);
2308
+ },
2309
+
2310
+ /* Action for current link. */
2311
+ _gotoToday: function(id) {
2312
+ var target = $(id);
2313
+ var inst = this._getInst(target[0]);
2314
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
2315
+ inst.selectedDay = inst.currentDay;
2316
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
2317
+ inst.drawYear = inst.selectedYear = inst.currentYear;
2318
+ }
2319
+ else {
2320
+ var date = new Date();
2321
+ inst.selectedDay = date.getDate();
2322
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
2323
+ inst.drawYear = inst.selectedYear = date.getFullYear();
2324
+ }
2325
+ this._notifyChange(inst);
2326
+ this._adjustDate(target);
2327
+ },
2328
+
2329
+ /* Action for selecting a new month/year. */
2330
+ _selectMonthYear: function(id, select, period) {
2331
+ var target = $(id);
2332
+ var inst = this._getInst(target[0]);
2333
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
2334
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
2335
+ parseInt(select.options[select.selectedIndex].value,10);
2336
+ this._notifyChange(inst);
2337
+ this._adjustDate(target);
2338
+ },
2339
+
2340
+ /* Action for selecting a day. */
2341
+ _selectDay: function(id, month, year, td) {
2342
+ var target = $(id);
2343
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
2344
+ return;
2345
+ }
2346
+ var inst = this._getInst(target[0]);
2347
+ inst.selectedDay = inst.currentDay = $('a', td).html();
2348
+ inst.selectedMonth = inst.currentMonth = month;
2349
+ inst.selectedYear = inst.currentYear = year;
2350
+ this._selectDate(id, this._formatDate(inst,
2351
+ inst.currentDay, inst.currentMonth, inst.currentYear));
2352
+ },
2353
+
2354
+ /* Erase the input field and hide the date picker. */
2355
+ _clearDate: function(id) {
2356
+ var target = $(id);
2357
+ var inst = this._getInst(target[0]);
2358
+ this._selectDate(target, '');
2359
+ },
2360
+
2361
+ /* Update the input field with the selected date. */
2362
+ _selectDate: function(id, dateStr) {
2363
+ var target = $(id);
2364
+ var inst = this._getInst(target[0]);
2365
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
2366
+ if (inst.input)
2367
+ inst.input.val(dateStr);
2368
+ this._updateAlternate(inst);
2369
+ var onSelect = this._get(inst, 'onSelect');
2370
+ if (onSelect)
2371
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
2372
+ else if (inst.input)
2373
+ inst.input.trigger('change'); // fire the change event
2374
+ if (inst.inline)
2375
+ this._updateDatepicker(inst);
2376
+ else {
2377
+ this._hideDatepicker();
2378
+ this._lastInput = inst.input[0];
2379
+ if (typeof(inst.input[0]) != 'object')
2380
+ inst.input.focus(); // restore focus
2381
+ this._lastInput = null;
2382
+ }
2383
+ },
2384
+
2385
+ /* Update any alternate field to synchronise with the main field. */
2386
+ _updateAlternate: function(inst) {
2387
+ var altField = this._get(inst, 'altField');
2388
+ if (altField) { // update alternate field too
2389
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
2390
+ var date = this._getDate(inst);
2391
+ var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
2392
+ $(altField).each(function() { $(this).val(dateStr); });
2393
+ }
2394
+ },
2395
+
2396
+ /* Set as beforeShowDay function to prevent selection of weekends.
2397
+ @param date Date - the date to customise
2398
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
2399
+ noWeekends: function(date) {
2400
+ var day = date.getDay();
2401
+ return [(day > 0 && day < 6), ''];
2402
+ },
2403
+
2404
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
2405
+ @param date Date - the date to get the week for
2406
+ @return number - the number of the week within the year that contains this date */
2407
+ iso8601Week: function(date) {
2408
+ var checkDate = new Date(date.getTime());
2409
+ // Find Thursday of this week starting on Monday
2410
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
2411
+ var time = checkDate.getTime();
2412
+ checkDate.setMonth(0); // Compare with Jan 1
2413
+ checkDate.setDate(1);
2414
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
2415
+ },
2416
+
2417
+ /* Parse a string value into a date object.
2418
+ See formatDate below for the possible formats.
2419
+
2420
+ @param format string - the expected format of the date
2421
+ @param value string - the date in the above format
2422
+ @param settings Object - attributes include:
2423
+ shortYearCutoff number - the cutoff year for determining the century (optional)
2424
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
2425
+ dayNames string[7] - names of the days from Sunday (optional)
2426
+ monthNamesShort string[12] - abbreviated names of the months (optional)
2427
+ monthNames string[12] - names of the months (optional)
2428
+ @return Date - the extracted date value or null if value is blank */
2429
+ parseDate: function (format, value, settings) {
2430
+ if (format == null || value == null)
2431
+ throw 'Invalid arguments';
2432
+ value = (typeof value == 'object' ? value.toString() : value + '');
2433
+ if (value == '')
2434
+ return null;
2435
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
2436
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
2437
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
2438
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
2439
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
2440
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
2441
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
2442
+ var year = -1;
2443
+ var month = -1;
2444
+ var day = -1;
2445
+ var doy = -1;
2446
+ var literal = false;
2447
+ // Check whether a format character is doubled
2448
+ var lookAhead = function(match) {
2449
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2450
+ if (matches)
2451
+ iFormat++;
2452
+ return matches;
2453
+ };
2454
+ // Extract a number from the string value
2455
+ var getNumber = function(match) {
2456
+ var isDoubled = lookAhead(match);
2457
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
2458
+ (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
2459
+ var digits = new RegExp('^\\d{1,' + size + '}');
2460
+ var num = value.substring(iValue).match(digits);
2461
+ if (!num)
2462
+ throw 'Missing number at position ' + iValue;
2463
+ iValue += num[0].length;
2464
+ return parseInt(num[0], 10);
2465
+ };
2466
+ // Extract a name from the string value and convert to an index
2467
+ var getName = function(match, shortNames, longNames) {
2468
+ var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
2469
+ return [ [k, v] ];
2470
+ }).sort(function (a, b) {
2471
+ return -(a[1].length - b[1].length);
2472
+ });
2473
+ var index = -1;
2474
+ $.each(names, function (i, pair) {
2475
+ var name = pair[1];
2476
+ if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
2477
+ index = pair[0];
2478
+ iValue += name.length;
2479
+ return false;
2480
+ }
2481
+ });
2482
+ if (index != -1)
2483
+ return index + 1;
2484
+ else
2485
+ throw 'Unknown name at position ' + iValue;
2486
+ };
2487
+ // Confirm that a literal character matches the string value
2488
+ var checkLiteral = function() {
2489
+ if (value.charAt(iValue) != format.charAt(iFormat))
2490
+ throw 'Unexpected literal at position ' + iValue;
2491
+ iValue++;
2492
+ };
2493
+ var iValue = 0;
2494
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
2495
+ if (literal)
2496
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2497
+ literal = false;
2498
+ else
2499
+ checkLiteral();
2500
+ else
2501
+ switch (format.charAt(iFormat)) {
2502
+ case 'd':
2503
+ day = getNumber('d');
2504
+ break;
2505
+ case 'D':
2506
+ getName('D', dayNamesShort, dayNames);
2507
+ break;
2508
+ case 'o':
2509
+ doy = getNumber('o');
2510
+ break;
2511
+ case 'm':
2512
+ month = getNumber('m');
2513
+ break;
2514
+ case 'M':
2515
+ month = getName('M', monthNamesShort, monthNames);
2516
+ break;
2517
+ case 'y':
2518
+ year = getNumber('y');
2519
+ break;
2520
+ case '@':
2521
+ var date = new Date(getNumber('@'));
2522
+ year = date.getFullYear();
2523
+ month = date.getMonth() + 1;
2524
+ day = date.getDate();
2525
+ break;
2526
+ case '!':
2527
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
2528
+ year = date.getFullYear();
2529
+ month = date.getMonth() + 1;
2530
+ day = date.getDate();
2531
+ break;
2532
+ case "'":
2533
+ if (lookAhead("'"))
2534
+ checkLiteral();
2535
+ else
2536
+ literal = true;
2537
+ break;
2538
+ default:
2539
+ checkLiteral();
2540
+ }
2541
+ }
2542
+ if (iValue < value.length){
2543
+ throw "Extra/unparsed characters found in date: " + value.substring(iValue);
2544
+ }
2545
+ if (year == -1)
2546
+ year = new Date().getFullYear();
2547
+ else if (year < 100)
2548
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
2549
+ (year <= shortYearCutoff ? 0 : -100);
2550
+ if (doy > -1) {
2551
+ month = 1;
2552
+ day = doy;
2553
+ do {
2554
+ var dim = this._getDaysInMonth(year, month - 1);
2555
+ if (day <= dim)
2556
+ break;
2557
+ month++;
2558
+ day -= dim;
2559
+ } while (true);
2560
+ }
2561
+ var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
2562
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
2563
+ throw 'Invalid date'; // E.g. 31/02/00
2564
+ return date;
2565
+ },
2566
+
2567
+ /* Standard date formats. */
2568
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
2569
+ COOKIE: 'D, dd M yy',
2570
+ ISO_8601: 'yy-mm-dd',
2571
+ RFC_822: 'D, d M y',
2572
+ RFC_850: 'DD, dd-M-y',
2573
+ RFC_1036: 'D, d M y',
2574
+ RFC_1123: 'D, d M yy',
2575
+ RFC_2822: 'D, d M yy',
2576
+ RSS: 'D, d M y', // RFC 822
2577
+ TICKS: '!',
2578
+ TIMESTAMP: '@',
2579
+ W3C: 'yy-mm-dd', // ISO 8601
2580
+
2581
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
2582
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
2583
+
2584
+ /* Format a date object into a string value.
2585
+ The format can be combinations of the following:
2586
+ d - day of month (no leading zero)
2587
+ dd - day of month (two digit)
2588
+ o - day of year (no leading zeros)
2589
+ oo - day of year (three digit)
2590
+ D - day name short
2591
+ DD - day name long
2592
+ m - month of year (no leading zero)
2593
+ mm - month of year (two digit)
2594
+ M - month name short
2595
+ MM - month name long
2596
+ y - year (two digit)
2597
+ yy - year (four digit)
2598
+ @ - Unix timestamp (ms since 01/01/1970)
2599
+ ! - Windows ticks (100ns since 01/01/0001)
2600
+ '...' - literal text
2601
+ '' - single quote
2602
+
2603
+ @param format string - the desired format of the date
2604
+ @param date Date - the date value to format
2605
+ @param settings Object - attributes include:
2606
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
2607
+ dayNames string[7] - names of the days from Sunday (optional)
2608
+ monthNamesShort string[12] - abbreviated names of the months (optional)
2609
+ monthNames string[12] - names of the months (optional)
2610
+ @return string - the date in the above format */
2611
+ formatDate: function (format, date, settings) {
2612
+ if (!date)
2613
+ return '';
2614
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
2615
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
2616
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
2617
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
2618
+ // Check whether a format character is doubled
2619
+ var lookAhead = function(match) {
2620
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2621
+ if (matches)
2622
+ iFormat++;
2623
+ return matches;
2624
+ };
2625
+ // Format a number, with leading zero if necessary
2626
+ var formatNumber = function(match, value, len) {
2627
+ var num = '' + value;
2628
+ if (lookAhead(match))
2629
+ while (num.length < len)
2630
+ num = '0' + num;
2631
+ return num;
2632
+ };
2633
+ // Format a name, short or long as requested
2634
+ var formatName = function(match, value, shortNames, longNames) {
2635
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
2636
+ };
2637
+ var output = '';
2638
+ var literal = false;
2639
+ if (date)
2640
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
2641
+ if (literal)
2642
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2643
+ literal = false;
2644
+ else
2645
+ output += format.charAt(iFormat);
2646
+ else
2647
+ switch (format.charAt(iFormat)) {
2648
+ case 'd':
2649
+ output += formatNumber('d', date.getDate(), 2);
2650
+ break;
2651
+ case 'D':
2652
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
2653
+ break;
2654
+ case 'o':
2655
+ output += formatNumber('o',
2656
+ Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
2657
+ break;
2658
+ case 'm':
2659
+ output += formatNumber('m', date.getMonth() + 1, 2);
2660
+ break;
2661
+ case 'M':
2662
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
2663
+ break;
2664
+ case 'y':
2665
+ output += (lookAhead('y') ? date.getFullYear() :
2666
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
2667
+ break;
2668
+ case '@':
2669
+ output += date.getTime();
2670
+ break;
2671
+ case '!':
2672
+ output += date.getTime() * 10000 + this._ticksTo1970;
2673
+ break;
2674
+ case "'":
2675
+ if (lookAhead("'"))
2676
+ output += "'";
2677
+ else
2678
+ literal = true;
2679
+ break;
2680
+ default:
2681
+ output += format.charAt(iFormat);
2682
+ }
2683
+ }
2684
+ return output;
2685
+ },
2686
+
2687
+ /* Extract all possible characters from the date format. */
2688
+ _possibleChars: function (format) {
2689
+ var chars = '';
2690
+ var literal = false;
2691
+ // Check whether a format character is doubled
2692
+ var lookAhead = function(match) {
2693
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2694
+ if (matches)
2695
+ iFormat++;
2696
+ return matches;
2697
+ };
2698
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
2699
+ if (literal)
2700
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2701
+ literal = false;
2702
+ else
2703
+ chars += format.charAt(iFormat);
2704
+ else
2705
+ switch (format.charAt(iFormat)) {
2706
+ case 'd': case 'm': case 'y': case '@':
2707
+ chars += '0123456789';
2708
+ break;
2709
+ case 'D': case 'M':
2710
+ return null; // Accept anything
2711
+ case "'":
2712
+ if (lookAhead("'"))
2713
+ chars += "'";
2714
+ else
2715
+ literal = true;
2716
+ break;
2717
+ default:
2718
+ chars += format.charAt(iFormat);
2719
+ }
2720
+ return chars;
2721
+ },
2722
+
2723
+ /* Get a setting value, defaulting if necessary. */
2724
+ _get: function(inst, name) {
2725
+ return inst.settings[name] !== undefined ?
2726
+ inst.settings[name] : this._defaults[name];
2727
+ },
2728
+
2729
+ /* Parse existing date and initialise date picker. */
2730
+ _setDateFromField: function(inst, noDefault) {
2731
+ if (inst.input.val() == inst.lastVal) {
2732
+ return;
2733
+ }
2734
+ var dateFormat = this._get(inst, 'dateFormat');
2735
+ var dates = inst.lastVal = inst.input ? inst.input.val() : null;
2736
+ var date, defaultDate;
2737
+ date = defaultDate = this._getDefaultDate(inst);
2738
+ var settings = this._getFormatConfig(inst);
2739
+ try {
2740
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
2741
+ } catch (event) {
2742
+ this.log(event);
2743
+ dates = (noDefault ? '' : dates);
2744
+ }
2745
+ inst.selectedDay = date.getDate();
2746
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
2747
+ inst.drawYear = inst.selectedYear = date.getFullYear();
2748
+ inst.currentDay = (dates ? date.getDate() : 0);
2749
+ inst.currentMonth = (dates ? date.getMonth() : 0);
2750
+ inst.currentYear = (dates ? date.getFullYear() : 0);
2751
+ this._adjustInstDate(inst);
2752
+ },
2753
+
2754
+ /* Retrieve the default date shown on opening. */
2755
+ _getDefaultDate: function(inst) {
2756
+ return this._restrictMinMax(inst,
2757
+ this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
2758
+ },
2759
+
2760
+ /* A date may be specified as an exact value or a relative one. */
2761
+ _determineDate: function(inst, date, defaultDate) {
2762
+ var offsetNumeric = function(offset) {
2763
+ var date = new Date();
2764
+ date.setDate(date.getDate() + offset);
2765
+ return date;
2766
+ };
2767
+ var offsetString = function(offset) {
2768
+ try {
2769
+ return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
2770
+ offset, $.datepicker._getFormatConfig(inst));
2771
+ }
2772
+ catch (e) {
2773
+ // Ignore
2774
+ }
2775
+ var date = (offset.toLowerCase().match(/^c/) ?
2776
+ $.datepicker._getDate(inst) : null) || new Date();
2777
+ var year = date.getFullYear();
2778
+ var month = date.getMonth();
2779
+ var day = date.getDate();
2780
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
2781
+ var matches = pattern.exec(offset);
2782
+ while (matches) {
2783
+ switch (matches[2] || 'd') {
2784
+ case 'd' : case 'D' :
2785
+ day += parseInt(matches[1],10); break;
2786
+ case 'w' : case 'W' :
2787
+ day += parseInt(matches[1],10) * 7; break;
2788
+ case 'm' : case 'M' :
2789
+ month += parseInt(matches[1],10);
2790
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
2791
+ break;
2792
+ case 'y': case 'Y' :
2793
+ year += parseInt(matches[1],10);
2794
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
2795
+ break;
2796
+ }
2797
+ matches = pattern.exec(offset);
2798
+ }
2799
+ return new Date(year, month, day);
2800
+ };
2801
+ var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
2802
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
2803
+ newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
2804
+ if (newDate) {
2805
+ newDate.setHours(0);
2806
+ newDate.setMinutes(0);
2807
+ newDate.setSeconds(0);
2808
+ newDate.setMilliseconds(0);
2809
+ }
2810
+ return this._daylightSavingAdjust(newDate);
2811
+ },
2812
+
2813
+ /* Handle switch to/from daylight saving.
2814
+ Hours may be non-zero on daylight saving cut-over:
2815
+ > 12 when midnight changeover, but then cannot generate
2816
+ midnight datetime, so jump to 1AM, otherwise reset.
2817
+ @param date (Date) the date to check
2818
+ @return (Date) the corrected date */
2819
+ _daylightSavingAdjust: function(date) {
2820
+ if (!date) return null;
2821
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
2822
+ return date;
2823
+ },
2824
+
2825
+ /* Set the date(s) directly. */
2826
+ _setDate: function(inst, date, noChange) {
2827
+ var clear = !date;
2828
+ var origMonth = inst.selectedMonth;
2829
+ var origYear = inst.selectedYear;
2830
+ var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
2831
+ inst.selectedDay = inst.currentDay = newDate.getDate();
2832
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
2833
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
2834
+ if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
2835
+ this._notifyChange(inst);
2836
+ this._adjustInstDate(inst);
2837
+ if (inst.input) {
2838
+ inst.input.val(clear ? '' : this._formatDate(inst));
2839
+ }
2840
+ },
2841
+
2842
+ /* Retrieve the date(s) directly. */
2843
+ _getDate: function(inst) {
2844
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
2845
+ this._daylightSavingAdjust(new Date(
2846
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
2847
+ return startDate;
2848
+ },
2849
+
2850
+ /* Generate the HTML for the current state of the date picker. */
2851
+ _generateHTML: function(inst) {
2852
+ var today = new Date();
2853
+ today = this._daylightSavingAdjust(
2854
+ new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
2855
+ var isRTL = this._get(inst, 'isRTL');
2856
+ var showButtonPanel = this._get(inst, 'showButtonPanel');
2857
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
2858
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
2859
+ var numMonths = this._getNumberOfMonths(inst);
2860
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
2861
+ var stepMonths = this._get(inst, 'stepMonths');
2862
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
2863
+ var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
2864
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
2865
+ var minDate = this._getMinMaxDate(inst, 'min');
2866
+ var maxDate = this._getMinMaxDate(inst, 'max');
2867
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
2868
+ var drawYear = inst.drawYear;
2869
+ if (drawMonth < 0) {
2870
+ drawMonth += 12;
2871
+ drawYear--;
2872
+ }
2873
+ if (maxDate) {
2874
+ var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
2875
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
2876
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
2877
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
2878
+ drawMonth--;
2879
+ if (drawMonth < 0) {
2880
+ drawMonth = 11;
2881
+ drawYear--;
2882
+ }
2883
+ }
2884
+ }
2885
+ inst.drawMonth = drawMonth;
2886
+ inst.drawYear = drawYear;
2887
+ var prevText = this._get(inst, 'prevText');
2888
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
2889
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
2890
+ this._getFormatConfig(inst)));
2891
+ var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
2892
+ '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2893
+ '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
2894
+ ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
2895
+ (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>'));
2896
+ var nextText = this._get(inst, 'nextText');
2897
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
2898
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
2899
+ this._getFormatConfig(inst)));
2900
+ var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
2901
+ '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2902
+ '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
2903
+ ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
2904
+ (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>'));
2905
+ var currentText = this._get(inst, 'currentText');
2906
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
2907
+ currentText = (!navigationAsDateFormat ? currentText :
2908
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
2909
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2910
+ '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
2911
+ var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
2912
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2913
+ '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
2914
+ '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
2915
+ var firstDay = parseInt(this._get(inst, 'firstDay'),10);
2916
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
2917
+ var showWeek = this._get(inst, 'showWeek');
2918
+ var dayNames = this._get(inst, 'dayNames');
2919
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
2920
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
2921
+ var monthNames = this._get(inst, 'monthNames');
2922
+ var monthNamesShort = this._get(inst, 'monthNamesShort');
2923
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
2924
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
2925
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
2926
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
2927
+ var defaultDate = this._getDefaultDate(inst);
2928
+ var html = '';
2929
+ for (var row = 0; row < numMonths[0]; row++) {
2930
+ var group = '';
2931
+ this.maxRows = 4;
2932
+ for (var col = 0; col < numMonths[1]; col++) {
2933
+ var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
2934
+ var cornerClass = ' ui-corner-all';
2935
+ var calender = '';
2936
+ if (isMultiMonth) {
2937
+ calender += '<div class="ui-datepicker-group';
2938
+ if (numMonths[1] > 1)
2939
+ switch (col) {
2940
+ case 0: calender += ' ui-datepicker-group-first';
2941
+ cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
2942
+ case numMonths[1]-1: calender += ' ui-datepicker-group-last';
2943
+ cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
2944
+ default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
2945
+ }
2946
+ calender += '">';
2947
+ }
2948
+ calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
2949
+ (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
2950
+ (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
2951
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
2952
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
2953
+ '</div><table class="ui-datepicker-calendar"><thead>' +
2954
+ '<tr>';
2955
+ var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
2956
+ for (var dow = 0; dow < 7; dow++) { // days of the week
2957
+ var day = (dow + firstDay) % 7;
2958
+ thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
2959
+ '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
2960
+ }
2961
+ calender += thead + '</tr></thead><tbody>';
2962
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
2963
+ if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
2964
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
2965
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
2966
+ var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
2967
+ var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
2968
+ this.maxRows = numRows;
2969
+ var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
2970
+ for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
2971
+ calender += '<tr>';
2972
+ var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
2973
+ this._get(inst, 'calculateWeek')(printDate) + '</td>');
2974
+ for (var dow = 0; dow < 7; dow++) { // create date picker days
2975
+ var daySettings = (beforeShowDay ?
2976
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
2977
+ var otherMonth = (printDate.getMonth() != drawMonth);
2978
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
2979
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
2980
+ tbody += '<td class="' +
2981
+ ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
2982
+ (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
2983
+ ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
2984
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
2985
+ // or defaultDate is current printedDate and defaultDate is selectedDate
2986
+ ' ' + this._dayOverClass : '') + // highlight selected day
2987
+ (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
2988
+ (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
2989
+ (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
2990
+ (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
2991
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
2992
+ (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
2993
+ inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
2994
+ (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
2995
+ (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
2996
+ (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
2997
+ (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
2998
+ (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
2999
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
3000
+ printDate.setDate(printDate.getDate() + 1);
3001
+ printDate = this._daylightSavingAdjust(printDate);
3002
+ }
3003
+ calender += tbody + '</tr>';
3004
+ }
3005
+ drawMonth++;
3006
+ if (drawMonth > 11) {
3007
+ drawMonth = 0;
3008
+ drawYear++;
3009
+ }
3010
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
3011
+ ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
3012
+ group += calender;
3013
+ }
3014
+ html += group;
3015
+ }
3016
+ html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
3017
+ '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
3018
+ inst._keyEvent = false;
3019
+ return html;
3020
+ },
3021
+
3022
+ /* Generate the month and year header. */
3023
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
3024
+ secondary, monthNames, monthNamesShort) {
3025
+ var changeMonth = this._get(inst, 'changeMonth');
3026
+ var changeYear = this._get(inst, 'changeYear');
3027
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
3028
+ var html = '<div class="ui-datepicker-title">';
3029
+ var monthHtml = '';
3030
+ // month selection
3031
+ if (secondary || !changeMonth)
3032
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
3033
+ else {
3034
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
3035
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
3036
+ monthHtml += '<select class="ui-datepicker-month" ' +
3037
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
3038
+ '>';
3039
+ for (var month = 0; month < 12; month++) {
3040
+ if ((!inMinYear || month >= minDate.getMonth()) &&
3041
+ (!inMaxYear || month <= maxDate.getMonth()))
3042
+ monthHtml += '<option value="' + month + '"' +
3043
+ (month == drawMonth ? ' selected="selected"' : '') +
3044
+ '>' + monthNamesShort[month] + '</option>';
3045
+ }
3046
+ monthHtml += '</select>';
3047
+ }
3048
+ if (!showMonthAfterYear)
3049
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
3050
+ // year selection
3051
+ if ( !inst.yearshtml ) {
3052
+ inst.yearshtml = '';
3053
+ if (secondary || !changeYear)
3054
+ html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
3055
+ else {
3056
+ // determine range of years to display
3057
+ var years = this._get(inst, 'yearRange').split(':');
3058
+ var thisYear = new Date().getFullYear();
3059
+ var determineYear = function(value) {
3060
+ var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
3061
+ (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
3062
+ parseInt(value, 10)));
3063
+ return (isNaN(year) ? thisYear : year);
3064
+ };
3065
+ var year = determineYear(years[0]);
3066
+ var endYear = Math.max(year, determineYear(years[1] || ''));
3067
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
3068
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
3069
+ inst.yearshtml += '<select class="ui-datepicker-year" ' +
3070
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
3071
+ '>';
3072
+ for (; year <= endYear; year++) {
3073
+ inst.yearshtml += '<option value="' + year + '"' +
3074
+ (year == drawYear ? ' selected="selected"' : '') +
3075
+ '>' + year + '</option>';
3076
+ }
3077
+ inst.yearshtml += '</select>';
3078
+
3079
+ html += inst.yearshtml;
3080
+ inst.yearshtml = null;
3081
+ }
3082
+ }
3083
+ html += this._get(inst, 'yearSuffix');
3084
+ if (showMonthAfterYear)
3085
+ html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
3086
+ html += '</div>'; // Close datepicker_header
3087
+ return html;
3088
+ },
3089
+
3090
+ /* Adjust one of the date sub-fields. */
3091
+ _adjustInstDate: function(inst, offset, period) {
3092
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
3093
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
3094
+ var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
3095
+ (period == 'D' ? offset : 0);
3096
+ var date = this._restrictMinMax(inst,
3097
+ this._daylightSavingAdjust(new Date(year, month, day)));
3098
+ inst.selectedDay = date.getDate();
3099
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
3100
+ inst.drawYear = inst.selectedYear = date.getFullYear();
3101
+ if (period == 'M' || period == 'Y')
3102
+ this._notifyChange(inst);
3103
+ },
3104
+
3105
+ /* Ensure a date is within any min/max bounds. */
3106
+ _restrictMinMax: function(inst, date) {
3107
+ var minDate = this._getMinMaxDate(inst, 'min');
3108
+ var maxDate = this._getMinMaxDate(inst, 'max');
3109
+ var newDate = (minDate && date < minDate ? minDate : date);
3110
+ newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
3111
+ return newDate;
3112
+ },
3113
+
3114
+ /* Notify change of month/year. */
3115
+ _notifyChange: function(inst) {
3116
+ var onChange = this._get(inst, 'onChangeMonthYear');
3117
+ if (onChange)
3118
+ onChange.apply((inst.input ? inst.input[0] : null),
3119
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
3120
+ },
3121
+
3122
+ /* Determine the number of months to show. */
3123
+ _getNumberOfMonths: function(inst) {
3124
+ var numMonths = this._get(inst, 'numberOfMonths');
3125
+ return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
3126
+ },
3127
+
3128
+ /* Determine the current maximum date - ensure no time components are set. */
3129
+ _getMinMaxDate: function(inst, minMax) {
3130
+ return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
3131
+ },
3132
+
3133
+ /* Find the number of days in a given month. */
3134
+ _getDaysInMonth: function(year, month) {
3135
+ return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
3136
+ },
3137
+
3138
+ /* Find the day of the week of the first of a month. */
3139
+ _getFirstDayOfMonth: function(year, month) {
3140
+ return new Date(year, month, 1).getDay();
3141
+ },
3142
+
3143
+ /* Determines if we should allow a "next/prev" month display change. */
3144
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
3145
+ var numMonths = this._getNumberOfMonths(inst);
3146
+ var date = this._daylightSavingAdjust(new Date(curYear,
3147
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
3148
+ if (offset < 0)
3149
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
3150
+ return this._isInRange(inst, date);
3151
+ },
3152
+
3153
+ /* Is the given date in the accepted range? */
3154
+ _isInRange: function(inst, date) {
3155
+ var minDate = this._getMinMaxDate(inst, 'min');
3156
+ var maxDate = this._getMinMaxDate(inst, 'max');
3157
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
3158
+ (!maxDate || date.getTime() <= maxDate.getTime()));
3159
+ },
3160
+
3161
+ /* Provide the configuration settings for formatting/parsing. */
3162
+ _getFormatConfig: function(inst) {
3163
+ var shortYearCutoff = this._get(inst, 'shortYearCutoff');
3164
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
3165
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
3166
+ return {shortYearCutoff: shortYearCutoff,
3167
+ dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
3168
+ monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
3169
+ },
3170
+
3171
+ /* Format the given date for display. */
3172
+ _formatDate: function(inst, day, month, year) {
3173
+ if (!day) {
3174
+ inst.currentDay = inst.selectedDay;
3175
+ inst.currentMonth = inst.selectedMonth;
3176
+ inst.currentYear = inst.selectedYear;
3177
+ }
3178
+ var date = (day ? (typeof day == 'object' ? day :
3179
+ this._daylightSavingAdjust(new Date(year, month, day))) :
3180
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
3181
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
3182
+ }
3183
+ });
3184
+
3185
+ /*
3186
+ * Bind hover events for datepicker elements.
3187
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
3188
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
3189
+ */
3190
+ function bindHover(dpDiv) {
3191
+ var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
3192
+ return dpDiv.bind('mouseout', function(event) {
3193
+ var elem = $( event.target ).closest( selector );
3194
+ if ( !elem.length ) {
3195
+ return;
3196
+ }
3197
+ elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
3198
+ })
3199
+ .bind('mouseover', function(event) {
3200
+ var elem = $( event.target ).closest( selector );
3201
+ if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
3202
+ !elem.length ) {
3203
+ return;
3204
+ }
3205
+ elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
3206
+ elem.addClass('ui-state-hover');
3207
+ if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
3208
+ if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
3209
+ });
3210
+ }
3211
+
3212
+ /* jQuery extend now ignores nulls! */
3213
+ function extendRemove(target, props) {
3214
+ $.extend(target, props);
3215
+ for (var name in props)
3216
+ if (props[name] == null || props[name] == undefined)
3217
+ target[name] = props[name];
3218
+ return target;
3219
+ };
3220
+
3221
+ /* Determine whether an object is an array. */
3222
+ function isArray(a) {
3223
+ return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
3224
+ (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
3225
+ };
3226
+
3227
+ /* Invoke the datepicker functionality.
3228
+ @param options string - a command, optionally followed by additional parameters or
3229
+ Object - settings for attaching new datepicker functionality
3230
+ @return jQuery object */
3231
+ $.fn.datepicker = function(options){
3232
+
3233
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
3234
+ if ( !this.length ) {
3235
+ return this;
3236
+ }
3237
+
3238
+ /* Initialise the date picker. */
3239
+ if (!$.datepicker.initialized) {
3240
+ $(document).mousedown($.datepicker._checkExternalClick).
3241
+ find('body').append($.datepicker.dpDiv);
3242
+ $.datepicker.initialized = true;
3243
+ }
3244
+
3245
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
3246
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
3247
+ return $.datepicker['_' + options + 'Datepicker'].
3248
+ apply($.datepicker, [this[0]].concat(otherArgs));
3249
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
3250
+ return $.datepicker['_' + options + 'Datepicker'].
3251
+ apply($.datepicker, [this[0]].concat(otherArgs));
3252
+ return this.each(function() {
3253
+ typeof options == 'string' ?
3254
+ $.datepicker['_' + options + 'Datepicker'].
3255
+ apply($.datepicker, [this].concat(otherArgs)) :
3256
+ $.datepicker._attachDatepicker(this, options);
3257
+ });
3258
+ };
3259
+
3260
+ $.datepicker = new Datepicker(); // singleton instance
3261
+ $.datepicker.initialized = false;
3262
+ $.datepicker.uuid = new Date().getTime();
3263
+ $.datepicker.version = "1.8.16";
3264
+
3265
+ // Workaround for #4055
3266
+ // Add another global to avoid noConflict issues with inline event handlers
3267
+ window['DP_jQuery_' + dpuuid] = $;
3268
+
3269
+ })(jQuery);