dashstrap 0.2.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +0 -9
  4. data/Rakefile +0 -5
  5. data/app/assets/javascripts/dashstrap/application.js +5 -1
  6. data/app/assets/javascripts/dashstrap/modules/list-view.js +13 -3
  7. data/app/assets/javascripts/dashstrap/modules/modules.js +2 -2
  8. data/app/assets/stylesheets/dashstrap/dashboard/ltr/application.css +5 -1
  9. data/app/assets/stylesheets/dashstrap/dashboard/rtl/application.css +5 -1
  10. data/app/assets/stylesheets/dashstrap/dashboard/share.scss +1 -1
  11. data/app/assets/stylesheets/dashstrap/ltr/application.css +3 -3
  12. data/app/assets/stylesheets/dashstrap/rtl/application.css +4 -3
  13. data/app/assets/stylesheets/dashstrap/share.scss +39 -1
  14. data/app/assets/stylesheets/dashstrap/variables.scss +5 -0
  15. data/app/views/angular/auth/groups/index.html.slim +1 -3
  16. data/app/views/angular/auth/groups/new.html.slim +12 -0
  17. data/app/views/angular/auth/users/index.html.slim +2 -0
  18. data/app/views/angular/list-view/index.html +12 -11
  19. data/app/views/dashstrap/shared/_content_header.html.slim +14 -0
  20. data/app/views/dashstrap/shared/_header.html.erb +273 -0
  21. data/app/views/dashstrap/shared/_sidebar.html.erb +62 -0
  22. data/app/views/faalis/dashboard/index.html.erb +0 -44
  23. data/app/views/faalis/dashboard/not_found.html.slim +9 -0
  24. data/app/views/faalis/dashboard/not_found.js.erb +1 -0
  25. data/app/views/layouts/faalis/dashboard.html.erb +48 -24
  26. data/config/initializers/assets.rb +1 -0
  27. data/dashstrap.gemspec +4 -5
  28. data/lib/dashstrap/engine.rb +3 -17
  29. data/lib/dashstrap/version.rb +1 -1
  30. data/lib/generators/templates/js/list_view/index.html.erb +1 -1
  31. data/lib/generators/templates/js/list_view/partials/index_controller.js.erb +9 -5
  32. data/vendor/assets/fonts/Lato-Bold.woff +0 -0
  33. data/vendor/assets/fonts/Lato-Bold.woff2 +0 -0
  34. data/vendor/assets/fonts/Lato-Light.woff +0 -0
  35. data/vendor/assets/fonts/Lato-Light.woff2 +0 -0
  36. data/vendor/assets/fonts/Lato-Regular.woff +0 -0
  37. data/vendor/assets/fonts/Lato-Regular.woff2 +0 -0
  38. data/vendor/assets/images/avatar.jpg +0 -0
  39. data/vendor/assets/javascripts/AdminLTE/app.js +929 -593
  40. data/vendor/assets/javascripts/AdminLTE/dashboard.js +11 -12
  41. data/vendor/assets/javascripts/bootstrap-datepicker.js +2286 -0
  42. data/vendor/assets/javascripts/rtl/bootstrap-datepicker.fa.js +245 -0
  43. data/vendor/assets/stylesheets/AdminLTE.css +3 -5
  44. data/vendor/assets/stylesheets/daterangepicker.css +337 -0
  45. data/vendor/assets/stylesheets/fonts.css.erb +20 -0
  46. metadata +33 -30
  47. data/app/views/angular/auth/users/index.html +0 -6
  48. data/vendor/assets/javascripts/ui-bootstrap.js +0 -3799
@@ -28,7 +28,7 @@ $(function() {
28
28
 
29
29
  //bootstrap WYSIHTML5 - text editor
30
30
  //$(".textarea").wysihtml5();
31
- /*
31
+
32
32
  $('.daterange').daterangepicker(
33
33
  {
34
34
  ranges: {
@@ -45,12 +45,11 @@ $(function() {
45
45
  function(start, end) {
46
46
  alert("You chose: " + start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
47
47
  });
48
- */
49
48
 
50
49
  /* jQueryKnob */
51
- //$(".knob").knob();
50
+ $(".knob").knob();
52
51
 
53
- //jvectormap data
52
+ /*jvectormap data
54
53
  var visitorsData = {
55
54
  "US": 398, //USA
56
55
  "SA": 400, //Saudi Arabia
@@ -65,7 +64,7 @@ $(function() {
65
64
  "RU": 3000 //Russia
66
65
  };
67
66
  //World map by jvectormap
68
- /*$('#world-map').vectorMap({
67
+ $('#world-map').vectorMap({
69
68
  map: 'world_mill_en',
70
69
  backgroundColor: "transparent",
71
70
  regionStyle: {
@@ -88,10 +87,10 @@ $(function() {
88
87
  if (typeof visitorsData[code] != "undefined")
89
88
  el.html(el.html() + ': ' + visitorsData[code] + ' new visitors');
90
89
  }
91
- });*/
92
-
90
+ });
91
+ */
93
92
  //Sparkline charts
94
- /*var myvalues = [1000, 1200, 920, 927, 931, 1027, 819, 930, 1021];
93
+ var myvalues = [1000, 1200, 920, 927, 931, 1027, 819, 930, 1021];
95
94
  $('#sparkline-1').sparkline(myvalues, {
96
95
  type: 'line',
97
96
  lineColor: '#92c1dc',
@@ -114,7 +113,7 @@ $(function() {
114
113
  fillColor: "#ebf4f9",
115
114
  height: '50',
116
115
  width: '80'
117
- });*/
116
+ });
118
117
 
119
118
  //The Calender
120
119
  $("#calendar").datepicker();
@@ -124,9 +123,9 @@ $(function() {
124
123
  height: '250px'
125
124
  });
126
125
 
127
- /* Morris.js Charts */
126
+ /* Morris.js Charts
128
127
  // Sales chart
129
- /*var area = new Morris.Area({
128
+ var area = new Morris.Area({
130
129
  element: 'revenue-chart',
131
130
  resize: true,
132
131
  data: [
@@ -208,12 +207,12 @@ $(function() {
208
207
  labels: ['CPU', 'DISK'],
209
208
  hideHover: 'auto'
210
209
  });
211
-
212
210
  //Fix for charts under tabs
213
211
  $('.box ul.nav a').on('shown.bs.tab', function(e) {
214
212
  area.redraw();
215
213
  donut.redraw();
216
214
  });
215
+
217
216
  */
218
217
 
219
218
  /* BOX REFRESH PLUGIN EXAMPLE (usage with morris charts) */
@@ -0,0 +1,2286 @@
1
+ /*! jQuery UI - v1.9.1 - 2012-10-29
2
+ * http://jqueryui.com
3
+ * Includes: jquery.ui.core.js, jquery.ui.datepicker.js
4
+ * Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT
5
+ *
6
+ * Edited By Rahman Mousavian
7
+ * Special Thanks to
8
+ * Mahdi Hasheminezhad. email: hasheminezhad at gmail dot com (http://hasheminezhad.com)
9
+ */
10
+
11
+ (function( $, undefined ) {
12
+
13
+ var uuid = 0,
14
+ runiqueId = /^ui-id-\d+$/;
15
+
16
+ // prevent duplicate loading
17
+ // this is only a problem because we proxy existing functions
18
+ // and we don't want to double proxy them
19
+ $.ui = $.ui || {};
20
+ if ( $.ui.version ) {
21
+ return;
22
+ }
23
+
24
+ $.extend( $.ui, {
25
+ version: "1.9.1",
26
+
27
+ keyCode: {
28
+ BACKSPACE: 8,
29
+ COMMA: 188,
30
+ DELETE: 46,
31
+ DOWN: 40,
32
+ END: 35,
33
+ ENTER: 13,
34
+ ESCAPE: 27,
35
+ HOME: 36,
36
+ LEFT: 37,
37
+ NUMPAD_ADD: 107,
38
+ NUMPAD_DECIMAL: 110,
39
+ NUMPAD_DIVIDE: 111,
40
+ NUMPAD_ENTER: 108,
41
+ NUMPAD_MULTIPLY: 106,
42
+ NUMPAD_SUBTRACT: 109,
43
+ PAGE_DOWN: 34,
44
+ PAGE_UP: 33,
45
+ PERIOD: 190,
46
+ RIGHT: 39,
47
+ SPACE: 32,
48
+ TAB: 9,
49
+ UP: 38
50
+ }
51
+ });
52
+
53
+ // plugins
54
+ $.fn.extend({
55
+ _focus: $.fn.focus,
56
+ focus: function( delay, fn ) {
57
+ return typeof delay === "number" ?
58
+ this.each(function() {
59
+ var elem = this;
60
+ setTimeout(function() {
61
+ $( elem ).focus();
62
+ if ( fn ) {
63
+ fn.call( elem );
64
+ }
65
+ }, delay );
66
+ }) :
67
+ this._focus.apply( this, arguments );
68
+ },
69
+
70
+ scrollParent: function() {
71
+ var scrollParent;
72
+ if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
73
+ scrollParent = this.parents().filter(function() {
74
+ return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
75
+ }).eq(0);
76
+ } else {
77
+ scrollParent = this.parents().filter(function() {
78
+ return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
79
+ }).eq(0);
80
+ }
81
+
82
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
83
+ },
84
+
85
+ zIndex: function( zIndex ) {
86
+ if ( zIndex !== undefined ) {
87
+ return this.css( "zIndex", zIndex );
88
+ }
89
+
90
+ if ( this.length ) {
91
+ var elem = $( this[ 0 ] ), position, value;
92
+ while ( elem.length && elem[ 0 ] !== document ) {
93
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
94
+ // This makes behavior of this function consistent across browsers
95
+ // WebKit always returns auto if the element is positioned
96
+ position = elem.css( "position" );
97
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
98
+ // IE returns 0 when zIndex is not specified
99
+ // other browsers return a string
100
+ // we ignore the case of nested elements with an explicit value of 0
101
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
102
+ value = parseInt( elem.css( "zIndex" ), 10 );
103
+ if ( !isNaN( value ) && value !== 0 ) {
104
+ return value;
105
+ }
106
+ }
107
+ elem = elem.parent();
108
+ }
109
+ }
110
+
111
+ return 0;
112
+ },
113
+
114
+ uniqueId: function() {
115
+ return this.each(function() {
116
+ if ( !this.id ) {
117
+ this.id = "ui-id-" + (++uuid);
118
+ }
119
+ });
120
+ },
121
+
122
+ removeUniqueId: function() {
123
+ return this.each(function() {
124
+ if ( runiqueId.test( this.id ) ) {
125
+ $( this ).removeAttr( "id" );
126
+ }
127
+ });
128
+ }
129
+ });
130
+
131
+ // support: jQuery <1.8
132
+ if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
133
+ $.each( [ "Width", "Height" ], function( i, name ) {
134
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
135
+ type = name.toLowerCase(),
136
+ orig = {
137
+ innerWidth: $.fn.innerWidth,
138
+ innerHeight: $.fn.innerHeight,
139
+ outerWidth: $.fn.outerWidth,
140
+ outerHeight: $.fn.outerHeight
141
+ };
142
+
143
+ function reduce( elem, size, border, margin ) {
144
+ $.each( side, function() {
145
+ size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
146
+ if ( border ) {
147
+ size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
148
+ }
149
+ if ( margin ) {
150
+ size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
151
+ }
152
+ });
153
+ return size;
154
+ }
155
+
156
+ $.fn[ "inner" + name ] = function( size ) {
157
+ if ( size === undefined ) {
158
+ return orig[ "inner" + name ].call( this );
159
+ }
160
+
161
+ return this.each(function() {
162
+ $( this ).css( type, reduce( this, size ) + "px" );
163
+ });
164
+ };
165
+
166
+ $.fn[ "outer" + name] = function( size, margin ) {
167
+ if ( typeof size !== "number" ) {
168
+ return orig[ "outer" + name ].call( this, size );
169
+ }
170
+
171
+ return this.each(function() {
172
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
173
+ });
174
+ };
175
+ });
176
+ }
177
+
178
+ // selectors
179
+ function focusable( element, isTabIndexNotNaN ) {
180
+ var map, mapName, img,
181
+ nodeName = element.nodeName.toLowerCase();
182
+ if ( "area" === nodeName ) {
183
+ map = element.parentNode;
184
+ mapName = map.name;
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 $.expr.filters.visible( element ) &&
202
+ !$( element ).parents().andSelf().filter(function() {
203
+ return $.css( this, "visibility" ) === "hidden";
204
+ }).length;
205
+ }
206
+
207
+ $.extend( $.expr[ ":" ], {
208
+ data: $.expr.createPseudo ?
209
+ $.expr.createPseudo(function( dataName ) {
210
+ return function( elem ) {
211
+ return !!$.data( elem, dataName );
212
+ };
213
+ }) :
214
+ // support: jQuery <1.8
215
+ function( elem, i, match ) {
216
+ return !!$.data( elem, match[ 3 ] );
217
+ },
218
+
219
+ focusable: function( element ) {
220
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
221
+ },
222
+
223
+ tabbable: function( element ) {
224
+ var tabIndex = $.attr( element, "tabindex" ),
225
+ isTabIndexNaN = isNaN( tabIndex );
226
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
227
+ }
228
+ });
229
+
230
+ // support
231
+ $(function() {
232
+ var body = document.body,
233
+ div = body.appendChild( div = document.createElement( "div" ) );
234
+
235
+ // access offsetHeight before setting the style to prevent a layout bug
236
+ // in IE 9 which causes the element to continue to take up space even
237
+ // after it is removed from the DOM (#8026)
238
+ div.offsetHeight;
239
+
240
+ $.extend( div.style, {
241
+ minHeight: "100px",
242
+ height: "auto",
243
+ padding: 0,
244
+ borderWidth: 0
245
+ });
246
+
247
+ $.support.minHeight = div.offsetHeight === 100;
248
+ $.support.selectstart = "onselectstart" in div;
249
+
250
+ // set display to none to avoid a layout bug in IE
251
+ // http://dev.jquery.com/ticket/4014
252
+ body.removeChild( div ).style.display = "none";
253
+ });
254
+
255
+
256
+
257
+
258
+
259
+ // deprecated
260
+
261
+ (function() {
262
+ var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || [];
263
+ $.ui.ie = uaMatch.length ? true : false;
264
+ $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6;
265
+ })();
266
+
267
+ $.fn.extend({
268
+ disableSelection: function() {
269
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
270
+ ".ui-disableSelection", function( event ) {
271
+ event.preventDefault();
272
+ });
273
+ },
274
+
275
+ enableSelection: function() {
276
+ return this.unbind( ".ui-disableSelection" );
277
+ }
278
+ });
279
+
280
+ $.extend( $.ui, {
281
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
282
+ plugin: {
283
+ add: function( module, option, set ) {
284
+ var i,
285
+ proto = $.ui[ module ].prototype;
286
+ for ( i in set ) {
287
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
288
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
289
+ }
290
+ },
291
+ call: function( instance, name, args ) {
292
+ var i,
293
+ set = instance.plugins[ name ];
294
+ if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
295
+ return;
296
+ }
297
+
298
+ for ( i = 0; i < set.length; i++ ) {
299
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
300
+ set[ i ][ 1 ].apply( instance.element, args );
301
+ }
302
+ }
303
+ }
304
+ },
305
+
306
+ contains: $.contains,
307
+
308
+ // only used by resizable
309
+ hasScroll: function( el, a ) {
310
+
311
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
312
+ if ( $( el ).css( "overflow" ) === "hidden") {
313
+ return false;
314
+ }
315
+
316
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
317
+ has = false;
318
+
319
+ if ( el[ scroll ] > 0 ) {
320
+ return true;
321
+ }
322
+
323
+ // TODO: determine which cases actually cause this to happen
324
+ // if the element doesn't have the scroll set, see if it's possible to
325
+ // set the scroll
326
+ el[ scroll ] = 1;
327
+ has = ( el[ scroll ] > 0 );
328
+ el[ scroll ] = 0;
329
+ return has;
330
+ },
331
+
332
+ // these are odd functions, fix the API or move into individual plugins
333
+ isOverAxis: function( x, reference, size ) {
334
+ //Determines when x coordinate is over "b" element axis
335
+ return ( x > reference ) && ( x < ( reference + size ) );
336
+ },
337
+ isOver: function( y, x, top, left, height, width ) {
338
+ //Determines when x, y coordinates is over "b" element
339
+ return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
340
+ }
341
+ });
342
+
343
+ })( jQuery );
344
+ (function( $, undefined ) {
345
+
346
+ $.extend($.ui, {
347
+ datepicker: {
348
+ version: "1.9.1"
349
+ }
350
+ });
351
+
352
+ var PROP_NAME = 'datepicker';
353
+ var dpuuid = new Date().getTime();
354
+ var instActive;
355
+
356
+ /* Date picker manager.
357
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
358
+ Settings for (groups of) date pickers are maintained in an instance object,
359
+ allowing multiple different settings on the same page. */
360
+
361
+ function Datepicker() {
362
+ this.debug = false; // Change this to true to start debugging
363
+ this._curInst = null; // The current instance in use
364
+ this._keyEvent = false; // If the last event was a key event
365
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
366
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
367
+ this._inDialog = false; // True if showing within a "dialog", false if not
368
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
369
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
370
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
371
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
372
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
373
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
374
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
375
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
376
+ this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
377
+ this.regional = []; // Available regional settings, indexed by language code
378
+ this.regional[''] = { // Default regional settings
379
+ calendar: Date, //[CC]
380
+ closeText: 'Done', // Display text for close link
381
+ prevText: 'Prev', // Display text for previous month link
382
+ nextText: 'Next', // Display text for next month link
383
+ currentText: 'Today', // Display text for current month link
384
+ monthNames: ['January','February','March','April','May','June',
385
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
386
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
387
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
388
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
389
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
390
+ weekHeader: 'Wk', // Column header for week of the year
391
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
392
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
393
+ isRTL: false, // True if right-to-left language, false if left-to-right
394
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
395
+ yearSuffix: '' // Additional text to append to the year in the month headers
396
+ };
397
+ this._defaults = { // Global defaults for all the date picker instances
398
+ showOn: 'focus', // 'focus' for popup on focus,
399
+ // 'button' for trigger button, or 'both' for either
400
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
401
+ showOptions: {}, // Options for enhanced animations
402
+ defaultDate: null, // Used when field is blank: actual date,
403
+ // +/-number for offset from today, null for today
404
+ appendText: '', // Display text following the input box, e.g. showing the format
405
+ buttonText: '...', // Text for trigger button
406
+ buttonImage: '', // URL for trigger button image
407
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
408
+ hideIfNoPrevNext: false, // True to hide next/previous month links
409
+ // if not applicable, false to just disable them
410
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
411
+ gotoCurrent: false, // True if today link goes back to current selection instead
412
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
413
+ changeYear: false, // True if year can be selected directly, false if only prev/next
414
+ yearRange: 'c-10:c+10', // Range of years to display in drop-down,
415
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
416
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
417
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
418
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
419
+ showWeek: false, // True to show week of the year, false to not show it
420
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
421
+ // takes a Date and returns the number of the week for it
422
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
423
+ // > this are in the previous century,
424
+ // string value starting with '+' for current year + value
425
+ minDate: null, // The earliest selectable date, or null for no limit
426
+ maxDate: null, // The latest selectable date, or null for no limit
427
+ duration: 'fast', // Duration of display/closure
428
+ beforeShowDay: null, // Function that takes a date and returns an array with
429
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
430
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
431
+ beforeShow: null, // Function that takes an input field and
432
+ // returns a set of custom settings for the date picker
433
+ onSelect: null, // Define a callback function when a date is selected
434
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
435
+ onClose: null, // Define a callback function when the datepicker is closed
436
+ numberOfMonths: 1, // Number of months to show at a time
437
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
438
+ stepMonths: 1, // Number of months to step back/forward
439
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
440
+ altField: '', // Selector for an alternate field to store selected dates into
441
+ altFormat: '', // The date format to use for the alternate field
442
+ constrainInput: true, // The input is constrained by the current date format
443
+ showButtonPanel: false, // True to show button panel, false to not show it
444
+ autoSize: false, // True to size the input for the date format, false to leave as is
445
+ disabled: false // The initial disabled state
446
+ };
447
+ $.extend(this._defaults, this.regional['']);
448
+ this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
449
+ }
450
+
451
+ $.extend(Datepicker.prototype, {
452
+ /* Class name added to elements to indicate already configured with a date picker. */
453
+ markerClassName: 'hasDatepicker',
454
+
455
+ //Keep track of the maximum number of rows displayed (see #7043)
456
+ maxRows: 4,
457
+
458
+ /* Debug logging (if enabled). */
459
+ log: function () {
460
+ if (this.debug)
461
+ console.log.apply('', arguments);
462
+ },
463
+
464
+ // TODO rename to "widget" when switching to widget factory
465
+ _widgetDatepicker: function() {
466
+ return this.dpDiv;
467
+ },
468
+
469
+ /* Override the default settings for all instances of the date picker.
470
+ @param settings object - the new settings to use as defaults (anonymous object)
471
+ @return the manager object */
472
+ setDefaults: function(settings) {
473
+ extendRemove(this._defaults, settings || {});
474
+ return this;
475
+ },
476
+
477
+ /* Attach the date picker to a jQuery selection.
478
+ @param target element - the target input field or division or span
479
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
480
+ _attachDatepicker: function(target, settings) {
481
+ // check for settings on the control itself - in namespace 'date:'
482
+ var inlineSettings = null;
483
+ for (var attrName in this._defaults) {
484
+ var attrValue = target.getAttribute('date:' + attrName);
485
+ if (attrValue) {
486
+ inlineSettings = inlineSettings || {};
487
+ try {
488
+ inlineSettings[attrName] = eval(attrValue);
489
+ } catch (err) {
490
+ inlineSettings[attrName] = attrValue;
491
+ }
492
+ }
493
+ }
494
+ var nodeName = target.nodeName.toLowerCase();
495
+ var inline = (nodeName == 'div' || nodeName == 'span');
496
+ if (!target.id) {
497
+ this.uuid += 1;
498
+ target.id = 'dp' + this.uuid;
499
+ }
500
+ var inst = this._newInst($(target), inline);
501
+ var regional = $.extend({}, settings && this.regional[settings['regional']] || {});//[CC]
502
+ inst.settings = $.extend(regional, settings || {}, inlineSettings || {});//[CC]
503
+ if (nodeName == 'input') {
504
+ this._connectDatepicker(target, inst);
505
+ } else if (inline) {
506
+ this._inlineDatepicker(target, inst);
507
+ }
508
+ },
509
+
510
+ /* Create a new instance object. */
511
+ _newInst: function(target, inline) {
512
+ var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
513
+ return {
514
+ id: id,
515
+ input: target, // associated target
516
+ selectedDay: 0,
517
+ selectedMonth: 0,
518
+ selectedYear: 0, // current selection
519
+ drawMonth: 0,
520
+ drawYear: 0, // month being drawn
521
+ inline: inline, // is datepicker inline or not
522
+ dpDiv: (!inline ? this.dpDiv : // presentation div
523
+ bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))
524
+ };
525
+ },
526
+
527
+ /* Attach the date picker to an input field. */
528
+ _connectDatepicker: function(target, inst) {
529
+ var input = $(target);
530
+ inst.append = $([]);
531
+ inst.trigger = $([]);
532
+ if (input.hasClass(this.markerClassName))
533
+ return;
534
+ this._attachments(input, inst);
535
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
536
+ keypress(this._doKeyPress).keyup(this._doKeyUp).
537
+ bind("setData.datepicker", function(event, key, value) {
538
+ inst.settings[key] = value;
539
+ }).bind("getData.datepicker", function(event, key) {
540
+ return this._get(inst, key);
541
+ });
542
+ this._autoSize(inst);
543
+ $.data(target, PROP_NAME, inst);
544
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
545
+ if( inst.settings.disabled ) {
546
+ this._disableDatepicker( target );
547
+ }
548
+ },
549
+
550
+ /* Make attachments based on settings. */
551
+ _attachments: function(input, inst) {
552
+ var appendText = this._get(inst, 'appendText');
553
+ var isRTL = false; //[CC] old code was: this._get(inst, 'isRTL');
554
+ if (inst.append)
555
+ inst.append.remove();
556
+ if (appendText) {
557
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
558
+ input[isRTL ? 'before' : 'after'](inst.append);
559
+ }
560
+ input.unbind('focus', this._showDatepicker);
561
+ if (inst.trigger)
562
+ inst.trigger.remove();
563
+ var showOn = this._get(inst, 'showOn');
564
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
565
+ input.focus(this._showDatepicker);
566
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
567
+ var buttonText = this._get(inst, 'buttonText');
568
+ var buttonImage = this._get(inst, 'buttonImage');
569
+ inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
570
+ $('<img/>').addClass(this._triggerClass).
571
+ attr({
572
+ src: buttonImage,
573
+ alt: buttonText,
574
+ title: buttonText
575
+ }) :
576
+ $('<button type="button"></button>').addClass(this._triggerClass).
577
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
578
+ {
579
+ src:buttonImage,
580
+ alt:buttonText,
581
+ title:buttonText
582
+ })));
583
+ input[isRTL ? 'before' : 'after'](inst.trigger);
584
+ inst.trigger.click(function() {
585
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
586
+ $.datepicker._hideDatepicker();
587
+ else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
588
+ $.datepicker._hideDatepicker();
589
+ $.datepicker._showDatepicker(input[0]);
590
+ } else
591
+ $.datepicker._showDatepicker(input[0]);
592
+ return false;
593
+ });
594
+ }
595
+ },
596
+
597
+ /* Apply the maximum length for the date format. */
598
+ _autoSize: function(inst) {
599
+ if (this._get(inst, 'autoSize') && !inst.inline) {
600
+ var date = new Date(2009, 12 - 1, 20); // Ensure double digits
601
+ var dateFormat = this._get(inst, 'dateFormat');
602
+ if (dateFormat.match(/[DM]/)) {
603
+ var findMax = function(names) {
604
+ var max = 0;
605
+ var maxI = 0;
606
+ for (var i = 0; i < names.length; i++) {
607
+ if (names[i].length > max) {
608
+ max = names[i].length;
609
+ maxI = i;
610
+ }
611
+ }
612
+ return maxI;
613
+ };
614
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
615
+ 'monthNames' : 'monthNamesShort'))));
616
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
617
+ 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
618
+ }
619
+ inst.input.attr('size', this._formatDate(inst, date).length);
620
+ }
621
+ },
622
+
623
+ /* Attach an inline date picker to a div. */
624
+ _inlineDatepicker: function(target, inst) {
625
+ var divSpan = $(target);
626
+ if (divSpan.hasClass(this.markerClassName))
627
+ return;
628
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
629
+ bind("setData.datepicker", function(event, key, value){
630
+ inst.settings[key] = value;
631
+ }).bind("getData.datepicker", function(event, key){
632
+ return this._get(inst, key);
633
+ });
634
+ $.data(target, PROP_NAME, inst);
635
+ this._setDate(inst, this._getDefaultDate(inst), true);
636
+ this._updateDatepicker(inst);
637
+ this._updateAlternate(inst);
638
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
639
+ if( inst.settings.disabled ) {
640
+ this._disableDatepicker( target );
641
+ }
642
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
643
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
644
+ inst.dpDiv.css( "display", "block" );
645
+ },
646
+
647
+ /* Pop-up the date picker in a "dialog" box.
648
+ @param input element - ignored
649
+ @param date string or Date - the initial date to display
650
+ @param onSelect function - the function to call when a date is selected
651
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
652
+ @param pos int[2] - coordinates for the dialog's position within the screen or
653
+ event - with x/y coordinates or
654
+ leave empty for default (screen centre)
655
+ @return the manager object */
656
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
657
+ var inst = this._dialogInst; // internal instance
658
+ if (!inst) {
659
+ this.uuid += 1;
660
+ var id = 'dp' + this.uuid;
661
+ this._dialogInput = $('<input type="text" id="' + id +
662
+ '" style="position: absolute; top: -100px; width: 0px;"/>');
663
+ this._dialogInput.keydown(this._doKeyDown);
664
+ $('body').append(this._dialogInput);
665
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
666
+ inst.settings = {};
667
+ $.data(this._dialogInput[0], PROP_NAME, inst);
668
+ }
669
+ extendRemove(inst.settings, settings || {});
670
+ date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
671
+ this._dialogInput.val(date);
672
+
673
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
674
+ if (!this._pos) {
675
+ var browserWidth = document.documentElement.clientWidth;
676
+ var browserHeight = document.documentElement.clientHeight;
677
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
678
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
679
+ this._pos = // should use actual width/height below
680
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
681
+ }
682
+
683
+ // move input on screen for focus, but hidden behind dialog
684
+ this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
685
+ inst.settings.onSelect = onSelect;
686
+ this._inDialog = true;
687
+ this.dpDiv.addClass(this._dialogClass);
688
+ this._showDatepicker(this._dialogInput[0]);
689
+ if ($.blockUI)
690
+ $.blockUI(this.dpDiv);
691
+ $.data(this._dialogInput[0], PROP_NAME, inst);
692
+ return this;
693
+ },
694
+
695
+ /* Detach a datepicker from its control.
696
+ @param target element - the target input field or division or span */
697
+ _destroyDatepicker: function(target) {
698
+ var $target = $(target);
699
+ var inst = $.data(target, PROP_NAME);
700
+ if (!$target.hasClass(this.markerClassName)) {
701
+ return;
702
+ }
703
+ var nodeName = target.nodeName.toLowerCase();
704
+ $.removeData(target, PROP_NAME);
705
+ if (nodeName == 'input') {
706
+ inst.append.remove();
707
+ inst.trigger.remove();
708
+ $target.removeClass(this.markerClassName).
709
+ unbind('focus', this._showDatepicker).
710
+ unbind('keydown', this._doKeyDown).
711
+ unbind('keypress', this._doKeyPress).
712
+ unbind('keyup', this._doKeyUp);
713
+ } else if (nodeName == 'div' || nodeName == 'span')
714
+ $target.removeClass(this.markerClassName).empty();
715
+ },
716
+
717
+ /* Enable the date picker to a jQuery selection.
718
+ @param target element - the target input field or division or span */
719
+ _enableDatepicker: function(target) {
720
+ var $target = $(target);
721
+ var inst = $.data(target, PROP_NAME);
722
+ if (!$target.hasClass(this.markerClassName)) {
723
+ return;
724
+ }
725
+ var nodeName = target.nodeName.toLowerCase();
726
+ if (nodeName == 'input') {
727
+ target.disabled = false;
728
+ inst.trigger.filter('button').
729
+ each(function() {
730
+ this.disabled = false;
731
+ }).end().
732
+ filter('img').css({
733
+ opacity: '1.0',
734
+ cursor: ''
735
+ });
736
+ }
737
+ else if (nodeName == 'div' || nodeName == 'span') {
738
+ var inline = $target.children('.' + this._inlineClass);
739
+ inline.children().removeClass('ui-state-disabled');
740
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
741
+ prop("disabled", false);
742
+ }
743
+ this._disabledInputs = $.map(this._disabledInputs,
744
+ function(value) {
745
+ return (value == target ? null : value);
746
+ }); // delete entry
747
+ },
748
+
749
+ /* Disable the date picker to a jQuery selection.
750
+ @param target element - the target input field or division or span */
751
+ _disableDatepicker: function(target) {
752
+ var $target = $(target);
753
+ var inst = $.data(target, PROP_NAME);
754
+ if (!$target.hasClass(this.markerClassName)) {
755
+ return;
756
+ }
757
+ var nodeName = target.nodeName.toLowerCase();
758
+ if (nodeName == 'input') {
759
+ target.disabled = true;
760
+ inst.trigger.filter('button').
761
+ each(function() {
762
+ this.disabled = true;
763
+ }).end().
764
+ filter('img').css({
765
+ opacity: '0.5',
766
+ cursor: 'default'
767
+ });
768
+ }
769
+ else if (nodeName == 'div' || nodeName == 'span') {
770
+ var inline = $target.children('.' + this._inlineClass);
771
+ inline.children().addClass('ui-state-disabled');
772
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
773
+ prop("disabled", true);
774
+ }
775
+ this._disabledInputs = $.map(this._disabledInputs,
776
+ function(value) {
777
+ return (value == target ? null : value);
778
+ }); // delete entry
779
+ this._disabledInputs[this._disabledInputs.length] = target;
780
+ },
781
+
782
+ /* Is the first field in a jQuery collection disabled as a datepicker?
783
+ @param target element - the target input field or division or span
784
+ @return boolean - true if disabled, false if enabled */
785
+ _isDisabledDatepicker: function(target) {
786
+ if (!target) {
787
+ return false;
788
+ }
789
+ for (var i = 0; i < this._disabledInputs.length; i++) {
790
+ if (this._disabledInputs[i] == target)
791
+ return true;
792
+ }
793
+ return false;
794
+ },
795
+
796
+ /* Retrieve the instance data for the target control.
797
+ @param target element - the target input field or division or span
798
+ @return object - the associated instance data
799
+ @throws error if a jQuery problem getting data */
800
+ _getInst: function(target) {
801
+ try {
802
+ return $.data(target, PROP_NAME);
803
+ }
804
+ catch (err) {
805
+ throw 'Missing instance data for this datepicker';
806
+ }
807
+ },
808
+
809
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
810
+ @param target element - the target input field or division or span
811
+ @param name object - the new settings to update or
812
+ string - the name of the setting to change or retrieve,
813
+ when retrieving also 'all' for all instance settings or
814
+ 'defaults' for all global defaults
815
+ @param value any - the new value for the setting
816
+ (omit if above is an object or to retrieve a value) */
817
+ _optionDatepicker: function(target, name, value) {
818
+ var inst = this._getInst(target);
819
+ if (arguments.length == 2 && typeof name == 'string') {
820
+ return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
821
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
822
+ this._get(inst, name)) : null));
823
+ }
824
+ var settings = name || {};
825
+ if (typeof name == 'string') {
826
+ settings = {};
827
+ settings[name] = value;
828
+ }
829
+ if (inst) {
830
+ if (this._curInst == inst) {
831
+ this._hideDatepicker();
832
+ }
833
+ var date = this._getDateDatepicker(target, true);
834
+ var minDate = this._getMinMaxDate(inst, 'min');
835
+ var maxDate = this._getMinMaxDate(inst, 'max');
836
+ extendRemove(inst.settings, settings);
837
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
838
+ if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
839
+ inst.settings.minDate = this._formatDate(inst, minDate);
840
+ if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
841
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
842
+ this._attachments($(target), inst);
843
+ this._autoSize(inst);
844
+ this._setDate(inst, date);
845
+ this._updateAlternate(inst);
846
+ this._updateDatepicker(inst);
847
+ }
848
+ },
849
+
850
+ // change method deprecated
851
+ _changeDatepicker: function(target, name, value) {
852
+ this._optionDatepicker(target, name, value);
853
+ },
854
+
855
+ /* Redraw the date picker attached to an input field or division.
856
+ @param target element - the target input field or division or span */
857
+ _refreshDatepicker: function(target) {
858
+ var inst = this._getInst(target);
859
+ if (inst) {
860
+ this._updateDatepicker(inst);
861
+ }
862
+ },
863
+
864
+ /* Set the dates for a jQuery selection.
865
+ @param target element - the target input field or division or span
866
+ @param date Date - the new date */
867
+ _setDateDatepicker: function(target, date) {
868
+ var inst = this._getInst(target);
869
+ if (inst) {
870
+ this._setDate(inst, date);
871
+ this._updateDatepicker(inst);
872
+ this._updateAlternate(inst);
873
+ }
874
+ },
875
+
876
+ /* Get the date(s) for the first entry in a jQuery selection.
877
+ @param target element - the target input field or division or span
878
+ @param noDefault boolean - true if no default date is to be used
879
+ @return Date - the current date */
880
+ _getDateDatepicker: function(target, noDefault) {
881
+ var inst = this._getInst(target);
882
+ if (inst && !inst.inline)
883
+ this._setDateFromField(inst, noDefault);
884
+ return (inst ? this._getDate(inst) : null);
885
+ },
886
+
887
+ /* Handle keystrokes. */
888
+ _doKeyDown: function(event) {
889
+ var inst = $.datepicker._getInst(event.target);
890
+ var handled = true;
891
+ var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
892
+ inst._keyEvent = true;
893
+ if ($.datepicker._datepickerShowing)
894
+ switch (event.keyCode) {
895
+ case 9:
896
+ $.datepicker._hideDatepicker();
897
+ handled = false;
898
+ break; // hide on tab out
899
+ case 13:
900
+ var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
901
+ $.datepicker._currentClass + ')', inst.dpDiv);
902
+ if (sel[0])
903
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
904
+ var onSelect = $.datepicker._get(inst, 'onSelect');
905
+ if (onSelect) {
906
+ var dateStr = $.datepicker._formatDate(inst);
907
+
908
+ // trigger custom callback
909
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
910
+ }
911
+ else
912
+ $.datepicker._hideDatepicker();
913
+ return false; // don't submit the form
914
+ break; // select the value on enter
915
+ case 27:
916
+ $.datepicker._hideDatepicker();
917
+ break; // hide on escape
918
+ case 33:
919
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
920
+ -$.datepicker._get(inst, 'stepBigMonths') :
921
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
922
+ break; // previous month/year on page up/+ ctrl
923
+ case 34:
924
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
925
+ +$.datepicker._get(inst, 'stepBigMonths') :
926
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
927
+ break; // next month/year on page down/+ ctrl
928
+ case 35:
929
+ if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
930
+ handled = event.ctrlKey || event.metaKey;
931
+ break; // clear on ctrl or command +end
932
+ case 36:
933
+ if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
934
+ handled = event.ctrlKey || event.metaKey;
935
+ break; // current on ctrl or command +home
936
+ case 37:
937
+ if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
938
+ handled = event.ctrlKey || event.metaKey;
939
+ // -1 day on ctrl or command +left
940
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
941
+ -$.datepicker._get(inst, 'stepBigMonths') :
942
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
943
+ // next month/year on alt +left on Mac
944
+ break;
945
+ case 38:
946
+ if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
947
+ handled = event.ctrlKey || event.metaKey;
948
+ break; // -1 week on ctrl or command +up
949
+ case 39:
950
+ if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
951
+ handled = event.ctrlKey || event.metaKey;
952
+ // +1 day on ctrl or command +right
953
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
954
+ +$.datepicker._get(inst, 'stepBigMonths') :
955
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
956
+ // next month/year on alt +right
957
+ break;
958
+ case 40:
959
+ if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
960
+ handled = event.ctrlKey || event.metaKey;
961
+ break; // +1 week on ctrl or command +down
962
+ default:
963
+ handled = false;
964
+ }
965
+ else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
966
+ $.datepicker._showDatepicker(this);
967
+ else {
968
+ handled = false;
969
+ }
970
+ if (handled) {
971
+ event.preventDefault();
972
+ event.stopPropagation();
973
+ }
974
+ },
975
+
976
+ /* Filter entered characters - based on date format. */
977
+ _doKeyPress: function(event) {
978
+ var inst = $.datepicker._getInst(event.target);
979
+ if ($.datepicker._get(inst, 'constrainInput')) {
980
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
981
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
982
+ return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
983
+ }
984
+ },
985
+
986
+ /* Synchronise manual entry and field/alternate field. */
987
+ _doKeyUp: function(event) {
988
+ var inst = $.datepicker._getInst(event.target);
989
+ if (inst.input.val() != inst.lastVal) {
990
+ try {
991
+ var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
992
+ (inst.input ? inst.input.val() : null),
993
+ $.datepicker._getFormatConfig(inst));
994
+ if (date) { // only if valid
995
+ $.datepicker._setDateFromField(inst);
996
+ $.datepicker._updateAlternate(inst);
997
+ $.datepicker._updateDatepicker(inst);
998
+ }
999
+ }
1000
+ catch (err) {
1001
+ $.datepicker.log(err);
1002
+ }
1003
+ }
1004
+ return true;
1005
+ },
1006
+
1007
+ /* Pop-up the date picker for a given input field.
1008
+ If false returned from beforeShow event handler do not show.
1009
+ @param input element - the input field attached to the date picker or
1010
+ event - if triggered by focus */
1011
+ _showDatepicker: function(input) {
1012
+ input = input.target || input;
1013
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
1014
+ input = $('input', input.parentNode)[0];
1015
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
1016
+ return;
1017
+ var inst = $.datepicker._getInst(input);
1018
+ if ($.datepicker._curInst && $.datepicker._curInst != inst) {
1019
+ $.datepicker._curInst.dpDiv.stop(true, true);
1020
+ if ( inst && $.datepicker._datepickerShowing ) {
1021
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
1022
+ }
1023
+ }
1024
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
1025
+ var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
1026
+ if(beforeShowSettings === false){
1027
+ //false
1028
+ return;
1029
+ }
1030
+ extendRemove(inst.settings, beforeShowSettings);
1031
+ inst.lastVal = null;
1032
+ $.datepicker._lastInput = input;
1033
+ $.datepicker._setDateFromField(inst);
1034
+ if ($.datepicker._inDialog) // hide cursor
1035
+ input.value = '';
1036
+ if (!$.datepicker._pos) { // position below input
1037
+ $.datepicker._pos = $.datepicker._findPos(input);
1038
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
1039
+ }
1040
+ var isFixed = false;
1041
+ $(input).parents().each(function() {
1042
+ isFixed |= $(this).css('position') == 'fixed';
1043
+ return !isFixed;
1044
+ });
1045
+ var offset = {
1046
+ left: $.datepicker._pos[0],
1047
+ top: $.datepicker._pos[1]
1048
+ };
1049
+ $.datepicker._pos = null;
1050
+ //to avoid flashes on Firefox
1051
+ inst.dpDiv.empty();
1052
+ // determine sizing offscreen
1053
+ inst.dpDiv.css({
1054
+ position: 'absolute',
1055
+ display: 'block',
1056
+ top: '-1000px'
1057
+ });
1058
+ $.datepicker._updateDatepicker(inst);
1059
+ // fix width for dynamic number of date pickers
1060
+ // and adjust position before showing
1061
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
1062
+ inst.dpDiv.css({
1063
+ position: ($.datepicker._inDialog && $.blockUI ?
1064
+ 'static' : (isFixed ? 'fixed' : 'absolute')),
1065
+ display: 'none',
1066
+ left: offset.left + 'px',
1067
+ top: offset.top + 'px'
1068
+ });
1069
+ if (!inst.inline) {
1070
+ var showAnim = $.datepicker._get(inst, 'showAnim');
1071
+ var duration = $.datepicker._get(inst, 'duration');
1072
+ var postProcess = function() {
1073
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
1074
+ if( !! cover.length ){
1075
+ var borders = $.datepicker._getBorders(inst.dpDiv);
1076
+ cover.css({
1077
+ left: -borders[0],
1078
+ top: -borders[1],
1079
+ width: inst.dpDiv.outerWidth(),
1080
+ height: inst.dpDiv.outerHeight()
1081
+ });
1082
+ }
1083
+ };
1084
+ inst.dpDiv.zIndex($(input).zIndex()+1);
1085
+ $.datepicker._datepickerShowing = true;
1086
+
1087
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
1088
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
1089
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
1090
+ else
1091
+ inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
1092
+ if (!showAnim || !duration)
1093
+ postProcess();
1094
+ if (inst.input.is(':visible') && !inst.input.is(':disabled'))
1095
+ inst.input.focus();
1096
+ $.datepicker._curInst = inst;
1097
+ }
1098
+ },
1099
+
1100
+ /* Generate the date picker content. */
1101
+ _updateDatepicker: function(inst) {
1102
+ this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
1103
+ var borders = $.datepicker._getBorders(inst.dpDiv);
1104
+ instActive = inst; // for delegate hover events
1105
+ inst.dpDiv.empty().append(this._generateHTML(inst));
1106
+ this._attachHandlers(inst);
1107
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
1108
+ if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
1109
+ cover.css({
1110
+ left: -borders[0],
1111
+ top: -borders[1],
1112
+ width: inst.dpDiv.outerWidth(),
1113
+ height: inst.dpDiv.outerHeight()
1114
+ })
1115
+ }
1116
+ inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
1117
+ var numMonths = this._getNumberOfMonths(inst);
1118
+ var cols = numMonths[1];
1119
+ var width = 17;
1120
+ inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
1121
+ if (cols > 1)
1122
+ inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
1123
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
1124
+ 'Class']('ui-datepicker-multi');
1125
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
1126
+ 'Class']('ui-datepicker-rtl');
1127
+ if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
1128
+ // #6694 - don't focus the input if it's already focused
1129
+ // this breaks the change event in IE
1130
+ inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
1131
+ inst.input.focus();
1132
+ // deffered render of the years select (to avoid flashes on Firefox)
1133
+ if( inst.yearshtml ){
1134
+ var origyearshtml = inst.yearshtml;
1135
+ setTimeout(function(){
1136
+ //assure that inst.yearshtml didn't change.
1137
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
1138
+ inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
1139
+ }
1140
+ origyearshtml = inst.yearshtml = null;
1141
+ }, 0);
1142
+ }
1143
+ },
1144
+
1145
+ /* Retrieve the size of left and top borders for an element.
1146
+ @param elem (jQuery object) the element of interest
1147
+ @return (number[2]) the left and top borders */
1148
+ _getBorders: function(elem) {
1149
+ var convert = function(value) {
1150
+ return {
1151
+ thin: 1,
1152
+ medium: 2,
1153
+ thick: 3
1154
+ }
1155
+ [value] || value;
1156
+ };
1157
+ return [parseFloat(convert(elem.css('border-left-width'))),
1158
+ parseFloat(convert(elem.css('border-top-width')))];
1159
+ },
1160
+
1161
+ /* Check positioning to remain on screen. */
1162
+ _checkOffset: function(inst, offset, isFixed) {
1163
+ var dpWidth = inst.dpDiv.outerWidth();
1164
+ var dpHeight = inst.dpDiv.outerHeight();
1165
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
1166
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
1167
+ var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
1168
+ var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
1169
+
1170
+ offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
1171
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
1172
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
1173
+
1174
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
1175
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
1176
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
1177
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
1178
+ Math.abs(dpHeight + inputHeight) : 0);
1179
+
1180
+ return offset;
1181
+ },
1182
+
1183
+ /* Find an object's position on the screen. */
1184
+ _findPos: function(obj) {
1185
+ var inst = this._getInst(obj);
1186
+ var isRTL = this._get(inst, 'isRTL');
1187
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
1188
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
1189
+ }
1190
+ var position = $(obj).offset();
1191
+ return [position.left, position.top];
1192
+ },
1193
+
1194
+ /* Hide the date picker from view.
1195
+ @param input element - the input field attached to the date picker */
1196
+ _hideDatepicker: function(input) {
1197
+ var inst = this._curInst;
1198
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
1199
+ return;
1200
+ if (this._datepickerShowing) {
1201
+ var showAnim = this._get(inst, 'showAnim');
1202
+ var duration = this._get(inst, 'duration');
1203
+ var postProcess = function() {
1204
+ $.datepicker._tidyDialog(inst);
1205
+ };
1206
+
1207
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
1208
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
1209
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
1210
+ else
1211
+ inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
1212
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
1213
+ if (!showAnim)
1214
+ postProcess();
1215
+ this._datepickerShowing = false;
1216
+ var onClose = this._get(inst, 'onClose');
1217
+ if (onClose)
1218
+ onClose.apply((inst.input ? inst.input[0] : null),
1219
+ [(inst.input ? inst.input.val() : ''), inst]);
1220
+ this._lastInput = null;
1221
+ if (this._inDialog) {
1222
+ this._dialogInput.css({
1223
+ position: 'absolute',
1224
+ left: '0',
1225
+ top: '-100px'
1226
+ });
1227
+ if ($.blockUI) {
1228
+ $.unblockUI();
1229
+ $('body').append(this.dpDiv);
1230
+ }
1231
+ }
1232
+ this._inDialog = false;
1233
+ }
1234
+ },
1235
+
1236
+ /* Tidy up after a dialog display. */
1237
+ _tidyDialog: function(inst) {
1238
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
1239
+ },
1240
+
1241
+ /* Close date picker if clicked elsewhere. */
1242
+ _checkExternalClick: function(event) {
1243
+ if (!$.datepicker._curInst)
1244
+ return;
1245
+
1246
+ var $target = $(event.target),
1247
+ inst = $.datepicker._getInst($target[0]);
1248
+
1249
+ if ( ( ( $target[0].id != $.datepicker._mainDivId &&
1250
+ $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
1251
+ !$target.hasClass($.datepicker.markerClassName) &&
1252
+ !$target.closest("." + $.datepicker._triggerClass).length &&
1253
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
1254
+ ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
1255
+ $.datepicker._hideDatepicker();
1256
+ },
1257
+
1258
+ /* Adjust one of the date sub-fields. */
1259
+ _adjustDate: function(id, offset, period) {
1260
+ var target = $(id);
1261
+ var inst = this._getInst(target[0]);
1262
+ if (this._isDisabledDatepicker(target[0])) {
1263
+ return;
1264
+ }
1265
+ this._adjustInstDate(inst, offset +
1266
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
1267
+ period);
1268
+ this._updateDatepicker(inst);
1269
+ },
1270
+
1271
+ /* Action for current link. */
1272
+ _gotoToday: function(id) {
1273
+ var target = $(id);
1274
+ var inst = this._getInst(target[0]);
1275
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
1276
+ inst.selectedDay = inst.currentDay;
1277
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
1278
+ inst.drawYear = inst.selectedYear = inst.currentYear;
1279
+ }
1280
+ else {
1281
+ var date = new this.CDate();//[CC]
1282
+ inst.selectedDay = date.getDate();
1283
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1284
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1285
+ }
1286
+ this._notifyChange(inst);
1287
+ this._adjustDate(target);
1288
+ },
1289
+
1290
+ /* Action for selecting a new month/year. */
1291
+ _selectMonthYear: function(id, select, period) {
1292
+ var target = $(id);
1293
+ var inst = this._getInst(target[0]);
1294
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
1295
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
1296
+ parseInt(select.options[select.selectedIndex].value,10);
1297
+ this._notifyChange(inst);
1298
+ this._adjustDate(target);
1299
+ },
1300
+
1301
+ /* Action for selecting a day. */
1302
+ _selectDay: function(id, month, year, td) {
1303
+ var target = $(id);
1304
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
1305
+ return;
1306
+ }
1307
+ var inst = this._getInst(target[0]);
1308
+ inst.selectedDay = inst.currentDay = $('a', td).html();
1309
+ inst.selectedMonth = inst.currentMonth = month;
1310
+ inst.selectedYear = inst.currentYear = year;
1311
+ this._selectDate(id, this._formatDate(inst,
1312
+ inst.currentDay, inst.currentMonth, inst.currentYear));
1313
+ },
1314
+
1315
+ /* Erase the input field and hide the date picker. */
1316
+ _clearDate: function(id) {
1317
+ var target = $(id);
1318
+ var inst = this._getInst(target[0]);
1319
+ this._selectDate(target, '');
1320
+ },
1321
+
1322
+ /* Update the input field with the selected date. */
1323
+ _selectDate: function(id, dateStr) {
1324
+ var target = $(id);
1325
+ var inst = this._getInst(target[0]);
1326
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
1327
+ if (inst.input)
1328
+ inst.input.val(dateStr);
1329
+ this._updateAlternate(inst);
1330
+ var onSelect = this._get(inst, 'onSelect');
1331
+ if (onSelect)
1332
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
1333
+ else if (inst.input)
1334
+ inst.input.trigger('change'); // fire the change event
1335
+ if (inst.inline)
1336
+ this._updateDatepicker(inst);
1337
+ else {
1338
+ this._hideDatepicker();
1339
+ this._lastInput = inst.input[0];
1340
+ if (typeof(inst.input[0]) != 'object')
1341
+ inst.input.focus(); // restore focus
1342
+ this._lastInput = null;
1343
+ }
1344
+ },
1345
+
1346
+ /* Update any alternate field to synchronise with the main field. */
1347
+ _updateAlternate: function(inst) {
1348
+ var altField = this._get(inst, 'altField');
1349
+ if (altField) { // update alternate field too
1350
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
1351
+ var date = this._getDate(inst);
1352
+ var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
1353
+ $(altField).each(function() {
1354
+ $(this).val(dateStr);
1355
+ });
1356
+ }
1357
+ },
1358
+
1359
+ /* Set as beforeShowDay function to prevent selection of weekends.
1360
+ @param date Date - the date to customise
1361
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
1362
+ noWeekends: function(date) {
1363
+ var day = date.getDay();
1364
+ return [(day > 0 && day < 6), ''];
1365
+ },
1366
+
1367
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
1368
+ @param date Date - the date to get the week for
1369
+ @return number - the number of the week within the year that contains this date */
1370
+ iso8601Week: function(date) {
1371
+ var checkDate = new Date(date.getTime());
1372
+ // Find Thursday of this week starting on Monday
1373
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
1374
+ var time = checkDate.getTime();
1375
+ checkDate.setMonth(0); // Compare with Jan 1
1376
+ checkDate.setDate(1);
1377
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
1378
+ },
1379
+
1380
+ /* Parse a string value into a date object.
1381
+ See formatDate below for the possible formats.
1382
+
1383
+ @param format string - the expected format of the date
1384
+ @param value string - the date in the above format
1385
+ @param settings Object - attributes include:
1386
+ shortYearCutoff number - the cutoff year for determining the century (optional)
1387
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1388
+ dayNames string[7] - names of the days from Sunday (optional)
1389
+ monthNamesShort string[12] - abbreviated names of the months (optional)
1390
+ monthNames string[12] - names of the months (optional)
1391
+ @return Date - the extracted date value or null if value is blank */
1392
+ parseDate: function (format, value, settings) {
1393
+ if (format == null || value == null)
1394
+ throw 'Invalid arguments';
1395
+ value = (typeof value == 'object' ? value.toString() : value + '');
1396
+ if (value == '')
1397
+ return null;
1398
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
1399
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
1400
+ new this.CDate().getFullYear() % 100 + parseInt(shortYearCutoff, 10));//[CC]
1401
+
1402
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1403
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1404
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1405
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1406
+ var year = -1;
1407
+ var month = -1;
1408
+ var day = -1;
1409
+ var doy = -1;
1410
+ var literal = false;
1411
+ // Check whether a format character is doubled
1412
+ var lookAhead = function(match) {
1413
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1414
+ if (matches)
1415
+ iFormat++;
1416
+ return matches;
1417
+ };
1418
+ // Extract a number from the string value
1419
+ var getNumber = function(match) {
1420
+ var isDoubled = lookAhead(match);
1421
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
1422
+ (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
1423
+ var digits = new RegExp('^\\d{1,' + size + '}');
1424
+ var num = value.substring(iValue).match(digits);
1425
+ if (!num)
1426
+ throw 'Missing number at position ' + iValue;
1427
+ iValue += num[0].length;
1428
+ return parseInt(num[0], 10);
1429
+ };
1430
+ // Extract a name from the string value and convert to an index
1431
+ var getName = function(match, shortNames, longNames) {
1432
+ var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
1433
+ return [ [k, v] ];
1434
+ }).sort(function (a, b) {
1435
+ return -(a[1].length - b[1].length);
1436
+ });
1437
+ var index = -1;
1438
+ $.each(names, function (i, pair) {
1439
+ var name = pair[1];
1440
+ if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
1441
+ index = pair[0];
1442
+ iValue += name.length;
1443
+ return false;
1444
+ }
1445
+ });
1446
+ if (index != -1)
1447
+ return index + 1;
1448
+ else
1449
+ throw 'Unknown name at position ' + iValue;
1450
+ };
1451
+ // Confirm that a literal character matches the string value
1452
+ var checkLiteral = function() {
1453
+ if (value.charAt(iValue) != format.charAt(iFormat))
1454
+ throw 'Unexpected literal at position ' + iValue;
1455
+ iValue++;
1456
+ };
1457
+ var iValue = 0;
1458
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1459
+ if (literal)
1460
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1461
+ literal = false;
1462
+ else
1463
+ checkLiteral();
1464
+ else
1465
+ switch (format.charAt(iFormat)) {
1466
+ case 'd':
1467
+ day = getNumber('d');
1468
+ break;
1469
+ case 'D':
1470
+ getName('D', dayNamesShort, dayNames);
1471
+ break;
1472
+ case 'o':
1473
+ doy = getNumber('o');
1474
+ break;
1475
+ case 'm':
1476
+ month = getNumber('m');
1477
+ break;
1478
+ case 'M':
1479
+ month = getName('M', monthNamesShort, monthNames);
1480
+ break;
1481
+ case 'y':
1482
+ year = getNumber('y');
1483
+ break;
1484
+ case '@':
1485
+ var date = new this.CDate(getNumber('@'));//[CC]
1486
+ year = date.getFullYear();
1487
+ month = date.getMonth() + 1;
1488
+ day = date.getDate();
1489
+ break;
1490
+ case '!':
1491
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
1492
+ year = date.getFullYear();
1493
+ month = date.getMonth() + 1;
1494
+ day = date.getDate();
1495
+ break;
1496
+ case "'":
1497
+ if (lookAhead("'"))
1498
+ checkLiteral();
1499
+ else
1500
+ literal = true;
1501
+ break;
1502
+ default:
1503
+ checkLiteral();
1504
+ }
1505
+ }
1506
+ if (iValue < value.length){
1507
+ var extra = value.substr(iValue);
1508
+ if (!/^\s+/.test(extra)) {
1509
+ throw "Extra/unparsed characters found in date: " + extra;
1510
+ }
1511
+ }
1512
+ if (year == -1)
1513
+ year = new this.CDate().getFullYear();//[CC]
1514
+
1515
+ else if (year < 100)
1516
+ year += new this.CDate().getFullYear() - new this.CDate().getFullYear() % 100 +//[CC]
1517
+ (year <= shortYearCutoff ? 0 : -100);
1518
+ if (doy > -1) {
1519
+ month = 1;
1520
+ day = doy;
1521
+ do {
1522
+ var dim = this._getDaysInMonth(year, month - 1);
1523
+ if (day <= dim)
1524
+ break;
1525
+ month++;
1526
+ day -= dim;
1527
+ } while (true);
1528
+ }
1529
+ var date = this._daylightSavingAdjust(new this.CDate(year, month - 1, day));//[CC]
1530
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
1531
+ throw 'Invalid date'; // E.g. 31/02/00
1532
+ return date;
1533
+ },
1534
+
1535
+ /* Standard date formats. */
1536
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
1537
+ COOKIE: 'D, dd M yy',
1538
+ ISO_8601: 'yy-mm-dd',
1539
+ RFC_822: 'D, d M y',
1540
+ RFC_850: 'DD, dd-M-y',
1541
+ RFC_1036: 'D, d M y',
1542
+ RFC_1123: 'D, d M yy',
1543
+ RFC_2822: 'D, d M yy',
1544
+ RSS: 'D, d M y', // RFC 822
1545
+ TICKS: '!',
1546
+ TIMESTAMP: '@',
1547
+ W3C: 'yy-mm-dd', // ISO 8601
1548
+
1549
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
1550
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
1551
+
1552
+ /* Format a date object into a string value.
1553
+ The format can be combinations of the following:
1554
+ d - day of month (no leading zero)
1555
+ dd - day of month (two digit)
1556
+ o - day of year (no leading zeros)
1557
+ oo - day of year (three digit)
1558
+ D - day name short
1559
+ DD - day name long
1560
+ m - month of year (no leading zero)
1561
+ mm - month of year (two digit)
1562
+ M - month name short
1563
+ MM - month name long
1564
+ y - year (two digit)
1565
+ yy - year (four digit)
1566
+ @ - Unix timestamp (ms since 01/01/1970)
1567
+ ! - Windows ticks (100ns since 01/01/0001)
1568
+ '...' - literal text
1569
+ '' - single quote
1570
+
1571
+ @param format string - the desired format of the date
1572
+ @param date Date - the date value to format
1573
+ @param settings Object - attributes include:
1574
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1575
+ dayNames string[7] - names of the days from Sunday (optional)
1576
+ monthNamesShort string[12] - abbreviated names of the months (optional)
1577
+ monthNames string[12] - names of the months (optional)
1578
+ @return string - the date in the above format */
1579
+ formatDate: function (format, date, settings) {
1580
+ if (!date)
1581
+ return '';
1582
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1583
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1584
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1585
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1586
+ // Check whether a format character is doubled
1587
+ var lookAhead = function(match) {
1588
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1589
+ if (matches)
1590
+ iFormat++;
1591
+ return matches;
1592
+ };
1593
+ // Format a number, with leading zero if necessary
1594
+ var formatNumber = function(match, value, len) {
1595
+ var num = '' + value;
1596
+ if (lookAhead(match))
1597
+ while (num.length < len)
1598
+ num = '0' + num;
1599
+ return num;
1600
+ };
1601
+ // Format a name, short or long as requested
1602
+ var formatName = function(match, value, shortNames, longNames) {
1603
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
1604
+ };
1605
+ var output = '';
1606
+ var literal = false;
1607
+ if (date)
1608
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1609
+ if (literal)
1610
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1611
+ literal = false;
1612
+ else
1613
+ output += format.charAt(iFormat);
1614
+ else
1615
+ switch (format.charAt(iFormat)) {
1616
+ case 'd':
1617
+ output += formatNumber('d', date.getDate(), 2);
1618
+ break;
1619
+ case 'D':
1620
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
1621
+ break;
1622
+ case 'o':
1623
+ output += formatNumber('o',
1624
+ Math.round((new this.CDate(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new this.CDate(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);//[CC]
1625
+ break;
1626
+ case 'm':
1627
+ output += formatNumber('m', date.getMonth() + 1, 2);
1628
+ break;
1629
+ case 'M':
1630
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
1631
+ break;
1632
+ case 'y':
1633
+ output += (lookAhead('y') ? date.getFullYear() :
1634
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
1635
+ break;
1636
+ case '@':
1637
+ output += date.getTime();
1638
+ break;
1639
+ case '!':
1640
+ output += date.getTime() * 10000 + this._ticksTo1970;
1641
+ break;
1642
+ case "'":
1643
+ if (lookAhead("'"))
1644
+ output += "'";
1645
+ else
1646
+ literal = true;
1647
+ break;
1648
+ default:
1649
+ output += format.charAt(iFormat);
1650
+ }
1651
+ }
1652
+ return output;
1653
+ },
1654
+
1655
+ /* Extract all possible characters from the date format. */
1656
+ _possibleChars: function (format) {
1657
+ var chars = '';
1658
+ var literal = false;
1659
+ // Check whether a format character is doubled
1660
+ var lookAhead = function(match) {
1661
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1662
+ if (matches)
1663
+ iFormat++;
1664
+ return matches;
1665
+ };
1666
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
1667
+ if (literal)
1668
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1669
+ literal = false;
1670
+ else
1671
+ chars += format.charAt(iFormat);
1672
+ else
1673
+ switch (format.charAt(iFormat)) {
1674
+ case 'd': case 'm': case 'y': case '@':
1675
+ chars += '0123456789';
1676
+ break;
1677
+ case 'D': case 'M':
1678
+ return null; // Accept anything
1679
+ case "'":
1680
+ if (lookAhead("'"))
1681
+ chars += "'";
1682
+ else
1683
+ literal = true;
1684
+ break;
1685
+ default:
1686
+ chars += format.charAt(iFormat);
1687
+ }
1688
+ return chars;
1689
+ },
1690
+
1691
+ /* Get a setting value, defaulting if necessary. */
1692
+ _get: function(inst, name) {
1693
+ return inst.settings[name] !== undefined ?
1694
+ inst.settings[name] : this._defaults[name];
1695
+ },
1696
+
1697
+ /* Parse existing date and initialise date picker. */
1698
+ _setDateFromField: function(inst, noDefault) {
1699
+ if (inst.input.val() == inst.lastVal) {
1700
+ return;
1701
+ }
1702
+ var dateFormat = this._get(inst, 'dateFormat');
1703
+ var dates = inst.lastVal = inst.input ? inst.input.val() : null;
1704
+ var date, defaultDate;
1705
+ date = defaultDate = this._getDefaultDate(inst);
1706
+ var settings = this._getFormatConfig(inst);
1707
+ try {
1708
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
1709
+ } catch (event) {
1710
+ this.log(event);
1711
+ dates = (noDefault ? '' : dates);
1712
+ }
1713
+ inst.selectedDay = date.getDate();
1714
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1715
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1716
+ inst.currentDay = (dates ? date.getDate() : 0);
1717
+ inst.currentMonth = (dates ? date.getMonth() : 0);
1718
+ inst.currentYear = (dates ? date.getFullYear() : 0);
1719
+ this._adjustInstDate(inst);
1720
+ },
1721
+
1722
+ /* Retrieve the default date shown on opening. */
1723
+ _getDefaultDate: function(inst) {
1724
+ this.CDate = this._get(inst, 'calendar');//[CC]
1725
+ return this._restrictMinMax(inst,
1726
+ this._determineDate(inst, this._get(inst, 'defaultDate'), new this.CDate()));//[CC]
1727
+ },
1728
+
1729
+ /* A date may be specified as an exact value or a relative one. */
1730
+ _determineDate: function(inst, date, defaultDate) {
1731
+ var Date = this.CDate;//[CC]
1732
+ var offsetNumeric = function(offset) {
1733
+ var date = new Date();
1734
+ date.setDate(date.getDate() + offset);
1735
+ return date;
1736
+ };
1737
+ var offsetString = function(offset) {
1738
+ try {
1739
+ return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
1740
+ offset, $.datepicker._getFormatConfig(inst));
1741
+ }
1742
+ catch (e) {
1743
+ // Ignore
1744
+ }
1745
+ var date = (offset.toLowerCase().match(/^c/) ?
1746
+ $.datepicker._getDate(inst) : null) || new Date();
1747
+ var year = date.getFullYear();
1748
+ var month = date.getMonth();
1749
+ var day = date.getDate();
1750
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
1751
+ var matches = pattern.exec(offset);
1752
+ while (matches) {
1753
+ switch (matches[2] || 'd') {
1754
+ case 'd' : case 'D' :
1755
+ day += parseInt(matches[1],10);
1756
+ break;
1757
+ case 'w' : case 'W' :
1758
+ day += parseInt(matches[1],10) * 7;
1759
+ break;
1760
+ case 'm' : case 'M' :
1761
+ month += parseInt(matches[1],10);
1762
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
1763
+ break;
1764
+ case 'y': case 'Y' :
1765
+ year += parseInt(matches[1],10);
1766
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
1767
+ break;
1768
+ }
1769
+ matches = pattern.exec(offset);
1770
+ }
1771
+ return new Date(year, month, day);
1772
+ };
1773
+ var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
1774
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
1775
+ newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
1776
+ if (newDate) {
1777
+ newDate.setHours(0);
1778
+ newDate.setMinutes(0);
1779
+ newDate.setSeconds(0);
1780
+ newDate.setMilliseconds(0);
1781
+ }
1782
+ return this._daylightSavingAdjust(newDate);
1783
+ },
1784
+
1785
+ /* Handle switch to/from daylight saving.
1786
+ Hours may be non-zero on daylight saving cut-over:
1787
+ > 12 when midnight changeover, but then cannot generate
1788
+ midnight datetime, so jump to 1AM, otherwise reset.
1789
+ @param date (Date) the date to check
1790
+ @return (Date) the corrected date */
1791
+ _daylightSavingAdjust: function(date) {
1792
+ if (!date) return null;
1793
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
1794
+ return date;
1795
+ },
1796
+
1797
+ /* Set the date(s) directly. */
1798
+ _setDate: function(inst, date, noChange) {
1799
+ var clear = !date;
1800
+ var origMonth = inst.selectedMonth;
1801
+ var origYear = inst.selectedYear;
1802
+ this.CDate = this._get(inst, 'calendar');//[CC]
1803
+ var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new this.CDate()));//[CC]
1804
+ inst.selectedDay = inst.currentDay = newDate.getDate();
1805
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
1806
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
1807
+ if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
1808
+ this._notifyChange(inst);
1809
+ this._adjustInstDate(inst);
1810
+ if (inst.input) {
1811
+ inst.input.val(clear ? '' : this._formatDate(inst));
1812
+ }
1813
+ },
1814
+
1815
+ /* Retrieve the date(s) directly. */
1816
+ _getDate: function(inst) {
1817
+ this.CDate = this._get(inst, 'calendar');//[CC]
1818
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
1819
+ this._daylightSavingAdjust(new this.CDate(//[CC]
1820
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
1821
+ return startDate;
1822
+ },
1823
+
1824
+ /* Attach the onxxx handlers. These are declared statically so
1825
+ * they work with static code transformers like Caja.
1826
+ */
1827
+ _attachHandlers: function(inst) {
1828
+ var stepMonths = this._get(inst, 'stepMonths');
1829
+ var id = '#' + inst.id.replace( /\\\\/g, "\\" );
1830
+ inst.dpDiv.find('[data-handler]').map(function () {
1831
+ var handler = {
1832
+ prev: function () {
1833
+ window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
1834
+ },
1835
+ next: function () {
1836
+ window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
1837
+ },
1838
+ hide: function () {
1839
+ window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
1840
+ },
1841
+ today: function () {
1842
+ window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
1843
+ },
1844
+ selectDay: function () {
1845
+ window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
1846
+ return false;
1847
+ },
1848
+ selectMonth: function () {
1849
+ window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
1850
+ return false;
1851
+ },
1852
+ selectYear: function () {
1853
+ window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
1854
+ return false;
1855
+ }
1856
+ };
1857
+ $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
1858
+ });
1859
+ },
1860
+
1861
+ /* Generate the HTML for the current state of the date picker. */
1862
+ _generateHTML: function(inst) {
1863
+ var today = new this.CDate();//[CC]
1864
+ today = this._daylightSavingAdjust(
1865
+ new this.CDate(today.getFullYear(), today.getMonth(), today.getDate())); // clear time //[CC]
1866
+ var isRTL = this._get(inst, 'isRTL');
1867
+ var showButtonPanel = this._get(inst, 'showButtonPanel');
1868
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
1869
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
1870
+ var numMonths = this._getNumberOfMonths(inst);
1871
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
1872
+ var stepMonths = this._get(inst, 'stepMonths');
1873
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
1874
+ var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
1875
+ new this.CDate(inst.currentYear, inst.currentMonth, inst.currentDay)));//[CC]
1876
+ var minDate = this._getMinMaxDate(inst, 'min');
1877
+ var maxDate = this._getMinMaxDate(inst, 'max');
1878
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
1879
+ var drawYear = inst.drawYear;
1880
+ if (drawMonth < 0) {
1881
+ drawMonth += 12;
1882
+ drawYear--;
1883
+ }
1884
+ if (maxDate) {
1885
+ var maxDraw = this._daylightSavingAdjust(new this.CDate(maxDate.getFullYear(),//[CC]
1886
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
1887
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
1888
+ while (this._daylightSavingAdjust(new this.CDate(drawYear, drawMonth, 1)) > maxDraw) {//[CC]
1889
+ drawMonth--;
1890
+ if (drawMonth < 0) {
1891
+ drawMonth = 11;
1892
+ drawYear--;
1893
+ }
1894
+ }
1895
+ }
1896
+ inst.drawMonth = drawMonth;
1897
+ inst.drawYear = drawYear;
1898
+ var prevText = this._get(inst, 'prevText');
1899
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
1900
+ this._daylightSavingAdjust(new this.CDate(drawYear, drawMonth - stepMonths, 1)),//[CC]
1901
+ this._getFormatConfig(inst)));
1902
+ var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
1903
+ '<a class="ui-datepicker-prev btn btn-link" data-handler="prev" data-event="click"' +
1904
+ ' title="' + prevText + '">' + (isRTL ? '<i class="icon-circle-arrow-right"></i>' : '<i class="icon-circle-arrow-left"></i>') + '</a>' :
1905
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev btn btn-link ui-state-disabled" title="'+ prevText +'">' + (isRTL ? '<i class="icon-circle-arrow-right"></i>' : '<i class="icon-circle-arrow-left"></i>') + '</a>'));
1906
+ var nextText = this._get(inst, 'nextText');
1907
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
1908
+ this._daylightSavingAdjust(new this.CDate(drawYear, drawMonth + stepMonths, 1)),//[CC]
1909
+ this._getFormatConfig(inst)));
1910
+ var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
1911
+ '<a class="ui-datepicker-next btn btn-link" data-handler="next" data-event="click"' +
1912
+ ' title="' + nextText + '">' + (isRTL ? '<i class="icon-circle-arrow-left"></i>' : '<i class="icon-circle-arrow-right"></i>') + '</a>' :
1913
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next btn btn-link ui-state-disabled" title="'+ nextText + '">' + (isRTL ? '<i class="icon-circle-arrow-left"></i>' : '<i class="icon-circle-arrow-right"></i>') + '</a>'));
1914
+ var currentText = this._get(inst, 'currentText');
1915
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
1916
+ currentText = (!navigationAsDateFormat ? currentText :
1917
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
1918
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close btn" data-handler="hide" data-event="click">' +
1919
+ this._get(inst, 'closeText') + '</button>' : '');
1920
+ var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-helper-clearfix">' + (isRTL ? controls : '') +
1921
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current btn" data-handler="today" data-event="click"' +
1922
+ '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
1923
+ var firstDay = parseInt(this._get(inst, 'firstDay'),10);
1924
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
1925
+ var showWeek = this._get(inst, 'showWeek');
1926
+ var dayNames = this._get(inst, 'dayNames');
1927
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
1928
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
1929
+ var monthNames = this._get(inst, 'monthNames');
1930
+ var monthNamesShort = this._get(inst, 'monthNamesShort');
1931
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
1932
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
1933
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
1934
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
1935
+ var defaultDate = this._getDefaultDate(inst);
1936
+ var html = '';
1937
+ for (var row = 0; row < numMonths[0]; row++) {
1938
+ var group = '';
1939
+ this.maxRows = 4;
1940
+ for (var col = 0; col < numMonths[1]; col++) {
1941
+ var selectedDate = this._daylightSavingAdjust(new this.CDate(drawYear, drawMonth, inst.selectedDay));//[CC]
1942
+ var cornerClass = ' ui-corner-all';
1943
+ var calender = '';
1944
+ if (isMultiMonth) {
1945
+ calender += '<div class="ui-datepicker-group';
1946
+ if (numMonths[1] > 1)
1947
+ switch (col) {
1948
+ case 0:
1949
+ calender += ' ui-datepicker-group-first';
1950
+ cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left');
1951
+ break;
1952
+ case numMonths[1]-1:
1953
+ calender += ' ui-datepicker-group-last';
1954
+ cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right');
1955
+ break;
1956
+ default:
1957
+ calender += ' ui-datepicker-group-middle';
1958
+ cornerClass = '';
1959
+ break;
1960
+ }
1961
+ calender += '">';
1962
+ }
1963
+ calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
1964
+ (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
1965
+ (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
1966
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
1967
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
1968
+ '</div><table class="ui-datepicker-calendar"><thead>' +
1969
+ '<tr>';
1970
+ var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
1971
+ for (var dow = 0; dow < 7; dow++) { // days of the week
1972
+ var day = (dow + firstDay) % 7;
1973
+ thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
1974
+ '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
1975
+ }
1976
+ calender += thead + '</tr></thead><tbody>';
1977
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
1978
+ if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
1979
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
1980
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
1981
+ var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
1982
+ var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
1983
+ this.maxRows = numRows;
1984
+ var printDate = this._daylightSavingAdjust(new this.CDate(drawYear, drawMonth, 1 - leadDays));//[CC]
1985
+ for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
1986
+ calender += '<tr>';
1987
+ var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
1988
+ this._get(inst, 'calculateWeek')(printDate) + '</td>');
1989
+ for (var dow = 0; dow < 7; dow++) { // create date picker days
1990
+ var daySettings = (beforeShowDay ?
1991
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
1992
+ var otherMonth = (printDate.getMonth() != drawMonth);
1993
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
1994
+ ((minDate && this._compareDate(printDate, '<', minDate)) || (maxDate && this._compareDate(printDate, '>', maxDate)));//[CC]
1995
+
1996
+ tbody += '<td class="' +
1997
+ ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
1998
+ (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
1999
+ ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
2000
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
2001
+ // or defaultDate is current printedDate and defaultDate is selectedDate
2002
+ ' ' + this._dayOverClass : '') + // highlight selected day
2003
+ (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
2004
+ (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
2005
+ (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
2006
+ (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
2007
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
2008
+ (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
2009
+ (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
2010
+ (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
2011
+ (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
2012
+ (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
2013
+ (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
2014
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
2015
+ printDate.setDate(printDate.getDate() + 1);
2016
+ printDate = this._daylightSavingAdjust(printDate);
2017
+ }
2018
+ calender += tbody + '</tr>';
2019
+ }
2020
+ drawMonth++;
2021
+ if (drawMonth > 11) {
2022
+ drawMonth = 0;
2023
+ drawYear++;
2024
+ }
2025
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
2026
+ ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
2027
+ group += calender;
2028
+ }
2029
+ html += group;
2030
+ }
2031
+ html += buttonPanel + ($.ui.ie6 && !inst.inline ?
2032
+ '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
2033
+ inst._keyEvent = false;
2034
+ return html;
2035
+ },
2036
+
2037
+ /* Generate the month and year header. */
2038
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
2039
+ secondary, monthNames, monthNamesShort) {
2040
+ var changeMonth = this._get(inst, 'changeMonth');
2041
+ var changeYear = this._get(inst, 'changeYear');
2042
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
2043
+ var html = '<div class="ui-datepicker-title">';
2044
+ var monthHtml = '';
2045
+ // month selection
2046
+ if (secondary || !changeMonth)
2047
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
2048
+ else {
2049
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
2050
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
2051
+ monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
2052
+ for (var month = 0; month < 12; month++) {
2053
+ if ((!inMinYear || month >= minDate.getMonth()) &&
2054
+ (!inMaxYear || month <= maxDate.getMonth()))
2055
+ monthHtml += '<option value="' + month + '"' +
2056
+ (month == drawMonth ? ' selected="selected"' : '') +
2057
+ '>' + monthNamesShort[month] + '</option>';
2058
+ }
2059
+ monthHtml += '</select>';
2060
+ }
2061
+ if (!showMonthAfterYear)
2062
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
2063
+ // year selection
2064
+ if ( !inst.yearshtml ) {
2065
+ inst.yearshtml = '';
2066
+ if (secondary || !changeYear)
2067
+ html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
2068
+ else {
2069
+ // determine range of years to display
2070
+ var years = this._get(inst, 'yearRange').split(':');
2071
+ var thisYear = new this.CDate().getFullYear();//[CC]
2072
+ var determineYear = function(value) {
2073
+ var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
2074
+ (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
2075
+ parseInt(value, 10)));
2076
+ return (isNaN(year) ? thisYear : year);
2077
+ };
2078
+ var year = determineYear(years[0]);
2079
+ var endYear = Math.max(year, determineYear(years[1] || ''));
2080
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
2081
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
2082
+ inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
2083
+ for (; year <= endYear; year++) {
2084
+ inst.yearshtml += '<option value="' + year + '"' +
2085
+ (year == drawYear ? ' selected="selected"' : '') +
2086
+ '>' + year + '</option>';
2087
+ }
2088
+ inst.yearshtml += '</select>';
2089
+
2090
+ html += inst.yearshtml;
2091
+ inst.yearshtml = null;
2092
+ }
2093
+ }
2094
+ html += this._get(inst, 'yearSuffix');
2095
+ if (showMonthAfterYear)
2096
+ html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
2097
+ html += '</div>'; // Close datepicker_header
2098
+ return html;
2099
+ },
2100
+
2101
+ /* Adjust one of the date sub-fields. */
2102
+ _adjustInstDate: function(inst, offset, period) {
2103
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
2104
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
2105
+ var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
2106
+ (period == 'D' ? offset : 0);
2107
+ var date = this._restrictMinMax(inst,
2108
+ this._daylightSavingAdjust(new this.CDate(year, month, day)));//[CC]
2109
+ inst.selectedDay = date.getDate();
2110
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
2111
+ inst.drawYear = inst.selectedYear = date.getFullYear();
2112
+ if (period == 'M' || period == 'Y')
2113
+ this._notifyChange(inst);
2114
+ },
2115
+
2116
+ /* Ensure a date is within any min/max bounds. */
2117
+ _restrictMinMax: function(inst, date) {
2118
+ var minDate = this._getMinMaxDate(inst, 'min');
2119
+ var maxDate = this._getMinMaxDate(inst, 'max');
2120
+ var newDate = (minDate && this._compareDate(date, '<', minDate)) ? minDate : date;//[CC]
2121
+ newDate = (maxDate && this._compareDate(newDate, '>', maxDate)) ? maxDate : newDate;//[CC]
2122
+ return newDate;
2123
+ },
2124
+
2125
+ /* Notify change of month/year. */
2126
+ _notifyChange: function(inst) {
2127
+ var onChange = this._get(inst, 'onChangeMonthYear');
2128
+ if (onChange)
2129
+ onChange.apply((inst.input ? inst.input[0] : null),
2130
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
2131
+ },
2132
+
2133
+ /* Determine the number of months to show. */
2134
+ _getNumberOfMonths: function(inst) {
2135
+ var numMonths = this._get(inst, 'numberOfMonths');
2136
+ return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
2137
+ },
2138
+
2139
+ /* Determine the current maximum date - ensure no time components are set. */
2140
+ _getMinMaxDate: function(inst, minMax) {
2141
+ return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
2142
+ },
2143
+
2144
+ /* Find the number of days in a given month. */
2145
+ _getDaysInMonth: function(year, month) {
2146
+ return 32 - this._daylightSavingAdjust(new this.CDate(year, month, 32)).getDate();//[CC]
2147
+ },
2148
+
2149
+ /* Find the day of the week of the first of a month. */
2150
+ _getFirstDayOfMonth: function(year, month) {
2151
+ return new this.CDate(year, month, 1).getDay();//[CC]
2152
+ },
2153
+
2154
+ /* Determines if we should allow a "next/prev" month display change. */
2155
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
2156
+ var numMonths = this._getNumberOfMonths(inst);
2157
+ var date = this._daylightSavingAdjust(new this.CDate(curYear,//[CC]
2158
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
2159
+ if (offset < 0)
2160
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
2161
+ return this._isInRange(inst, date);
2162
+ },
2163
+
2164
+ /* Is the given date in the accepted range? */
2165
+ _isInRange: function(inst, date) {
2166
+ var minDate = this._getMinMaxDate(inst, 'min');
2167
+ var maxDate = this._getMinMaxDate(inst, 'max');
2168
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
2169
+ (!maxDate || date.getTime() <= maxDate.getTime()));
2170
+ },
2171
+
2172
+ /* Provide the configuration settings for formatting/parsing. */
2173
+ _getFormatConfig: function(inst) {
2174
+ var shortYearCutoff = this._get(inst, 'shortYearCutoff');
2175
+ this.CDate = this._get(inst, 'calendar');//[CC]
2176
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
2177
+ new this.CDate().getFullYear() % 100 + parseInt(shortYearCutoff, 10));//[CC]
2178
+ return {
2179
+ shortYearCutoff: shortYearCutoff,
2180
+ dayNamesShort: this._get(inst, 'dayNamesShort'),
2181
+ dayNames: this._get(inst, 'dayNames'),
2182
+ monthNamesShort: this._get(inst, 'monthNamesShort'),
2183
+ monthNames: this._get(inst, 'monthNames')
2184
+ };
2185
+ },
2186
+
2187
+ /* Format the given date for display. */
2188
+ _formatDate: function(inst, day, month, year) {
2189
+ if (!day) {
2190
+ inst.currentDay = inst.selectedDay;
2191
+ inst.currentMonth = inst.selectedMonth;
2192
+ inst.currentYear = inst.selectedYear;
2193
+ }
2194
+ var date = (day ? (typeof day == 'object' ? day :
2195
+ this._daylightSavingAdjust(new this.CDate(year, month, day))) ://[CC]
2196
+ this._daylightSavingAdjust(new this.CDate(inst.currentYear, inst.currentMonth, inst.currentDay)));//[CC]
2197
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
2198
+ },
2199
+
2200
+ /* [CC]Compare two dates */
2201
+ _compareDate: function(d1, op, d2) {//[CC]
2202
+ if(d1 && d2) {//[CC]
2203
+ if(d1.getGregorianDate) d1 = d1.getGregorianDate();//[CC]
2204
+ if(d2.getGregorianDate) d2 = d2.getGregorianDate();//[CC]
2205
+ if(op == '<') return d1 < d2;//[CC]
2206
+ return d1 > d2;//[CC]
2207
+ } else {//[CC]
2208
+ return null;//[CC]
2209
+ }//[CC]
2210
+ }//[CC]
2211
+ });
2212
+
2213
+ /*
2214
+ * Bind hover events for datepicker elements.
2215
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
2216
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
2217
+ */
2218
+ function bindHover(dpDiv) {
2219
+ var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
2220
+ return dpDiv.delegate(selector, 'mouseout', function() {
2221
+ $(this).removeClass('ui-state-hover');
2222
+ if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
2223
+ if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
2224
+ })
2225
+ .delegate(selector, 'mouseover', function(){
2226
+ if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
2227
+ $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
2228
+ $(this).addClass('ui-state-hover');
2229
+ if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
2230
+ if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
2231
+ }
2232
+ });
2233
+ }
2234
+
2235
+ /* jQuery extend now ignores nulls! */
2236
+ function extendRemove(target, props) {
2237
+ $.extend(target, props);
2238
+ for (var name in props)
2239
+ if (props[name] == null || props[name] == undefined)
2240
+ target[name] = props[name];
2241
+ return target;
2242
+ };
2243
+
2244
+ /* Invoke the datepicker functionality.
2245
+ @param options string - a command, optionally followed by additional parameters or
2246
+ Object - settings for attaching new datepicker functionality
2247
+ @return jQuery object */
2248
+ $.fn.datepicker = function(options){
2249
+
2250
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
2251
+ if ( !this.length ) {
2252
+ return this;
2253
+ }
2254
+
2255
+ /* Initialise the date picker. */
2256
+ if (!$.datepicker.initialized) {
2257
+ $(document).mousedown($.datepicker._checkExternalClick).
2258
+ find(document.body).append($.datepicker.dpDiv);
2259
+ $.datepicker.initialized = true;
2260
+ }
2261
+
2262
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
2263
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
2264
+ return $.datepicker['_' + options + 'Datepicker'].
2265
+ apply($.datepicker, [this[0]].concat(otherArgs));
2266
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
2267
+ return $.datepicker['_' + options + 'Datepicker'].
2268
+ apply($.datepicker, [this[0]].concat(otherArgs));
2269
+ return this.each(function() {
2270
+ typeof options == 'string' ?
2271
+ $.datepicker['_' + options + 'Datepicker'].
2272
+ apply($.datepicker, [this].concat(otherArgs)) :
2273
+ $.datepicker._attachDatepicker(this, options);
2274
+ });
2275
+ };
2276
+
2277
+ $.datepicker = new Datepicker(); // singleton instance
2278
+ $.datepicker.initialized = false;
2279
+ $.datepicker.uuid = new Date().getTime();
2280
+ $.datepicker.version = "1.9.1";
2281
+
2282
+ // Workaround for #4055
2283
+ // Add another global to avoid noConflict issues with inline event handlers
2284
+ window['DP_jQuery_' + dpuuid] = $;
2285
+
2286
+ })(jQuery);