pickadate-rails 1.3.2 → 1.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7ecab16b12a07768c82fb511574de65471ee0f84
4
- data.tar.gz: b58d663694fe7f0dbe57f0029e63d2f5502d1024
3
+ metadata.gz: b8bbf39c9f159feed3de69900df634b556e902ac
4
+ data.tar.gz: 44c4abfe39c4d8a63c0181b812cb0ff68a9e85a1
5
5
  SHA512:
6
- metadata.gz: 1cf838b0a21a732e6e812b91f9dd24cbb2027564ff33166e80f75f4b52628e7bbeaab7c7ae6e3b34fd5a999a5d63944711aca9b46f2bc0f75a52aa47bdb7571a
7
- data.tar.gz: 837f6c6e499d31bf216dc337b03b7f41ccb36c503e048a0d476939639fc18d48104226ad1668521f56bda52a6bf4a749fb414fcb1d87e86bd610a5d9767f28f7
6
+ metadata.gz: 7621c5f039ba977bfb838997b0e74902d7d7bbacaa6c0abddc7204cf25ed6d3bdd297969e5c0c53d9c6004c4ef8ca3e181b1139842aeb35a54f3f93ab5f8b3c9
7
+ data.tar.gz: 2661ae990c6fdaf3148aaabbd4916f0c69c9cfecf64c3ebe853e29ce022e953060fe1de27b3edae9c4b088a72d432f683c714545303fb5abf6bb141331eb68a1
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Pickadate-Rails [![Gem Version](https://badge.fury.io/rb/pickadate-rails.png)](http://badge.fury.io/rb/pickadate-rails)
2
2
 
3
- ## Pickadate Version: 3.3.2
3
+ ## Pickadate Version: 3.4.0
4
4
 
5
5
  Easily add [pickadate.js](https://github.com/amsul/pickadate.js) to your Rails 3.1+ application using the asset pipeline.
6
6
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ namespace :pickadate do
5
5
  task :download do
6
6
  require 'fileutils'
7
7
 
8
- system "curl https://github.com/amsul/pickadate.js/archive/gh-pages.zip -f -L -o tmp/pickadate.zip"
8
+ system "curl https://github.com/amsul/pickadate.js/archive/gh-pages.zip -f -L --create-dirs -o tmp/pickadate.zip"
9
9
  system "unzip tmp/pickadate.zip -d tmp/"
10
10
  system "rm tmp/pickadate.zip"
11
11
 
@@ -23,4 +23,4 @@ namespace :pickadate do
23
23
 
24
24
  system "rm -rf tmp/pickadate*"
25
25
  end
26
- end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module PickadateRails
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -1,22 +1,13 @@
1
1
 
2
2
  /*!
3
- * Date picker for pickadate.js v3.3.2
3
+ * Date picker for pickadate.js v3.4.0
4
4
  * http://amsul.github.io/pickadate.js/date.htm
5
5
  */
6
6
 
7
- /*jshint
8
- debug: true,
9
- devel: true,
10
- browser: true,
11
- asi: true,
12
- unused: true,
13
- boss: true
14
- */
15
-
16
7
  (function ( factory ) {
17
8
 
18
9
  // Register as an anonymous module.
19
- if ( typeof define === 'function' && define.amd )
10
+ if ( typeof define == 'function' && define.amd )
20
11
  define( ['picker','jquery'], factory )
21
12
 
22
13
  // Or using browser globals.
@@ -29,7 +20,8 @@
29
20
  * Globals and constants
30
21
  */
31
22
  var DAYS_IN_WEEK = 7,
32
- WEEKS_IN_CALENDAR = 6
23
+ WEEKS_IN_CALENDAR = 6,
24
+ _ = Picker._
33
25
 
34
26
 
35
27
 
@@ -48,6 +40,7 @@ function DatePicker( picker, settings ) {
48
40
  }
49
41
 
50
42
  calendar.settings = settings
43
+ calendar.$node = picker.$node
51
44
 
52
45
  // The queue of methods that will be used to build item objects.
53
46
  calendar.queue = {
@@ -55,10 +48,10 @@ function DatePicker( picker, settings ) {
55
48
  max: 'measure create',
56
49
  now: 'now create',
57
50
  select: 'parse create validate',
58
- highlight: 'navigate create validate',
59
- view: 'create validate viewset',
60
- disable: 'flipItem',
61
- enable: 'flipItem'
51
+ highlight: 'parse navigate create validate',
52
+ view: 'parse create validate viewset',
53
+ disable: 'deactivate',
54
+ enable: 'activate'
62
55
  }
63
56
 
64
57
  // The component's item object.
@@ -72,24 +65,23 @@ function DatePicker( picker, settings ) {
72
65
  calendar.
73
66
  set( 'min', settings.min ).
74
67
  set( 'max', settings.max ).
75
- set( 'now' ).
76
-
77
- // Setting the `select` also sets the `highlight` and `view`.
78
- set( 'select',
79
-
80
- // Use the value provided or default to selecting “today”.
81
- valueString || calendar.item.now,
82
- {
83
- // Use the appropriate format.
84
- format: formatString,
85
-
86
- // Set user-provided month data as true when there is a
87
- // “mm” or “m” used in the relative format string.
88
- data: (function( formatArray ) {
89
- return valueString && ( formatArray.indexOf( 'mm' ) > -1 || formatArray.indexOf( 'm' ) > -1 )
90
- })( calendar.formats.toArray( formatString ) )
91
- }
92
- )
68
+ set( 'now' )
69
+
70
+ // When there’s a value, set the `select`, which in turn
71
+ // also sets the `highlight` and `view`.
72
+ if ( valueString ) {
73
+ calendar.set( 'select', valueString, {
74
+ format: formatString,
75
+ fromValue: !!elementValue
76
+ })
77
+ }
78
+
79
+ // If there’s no value, default to highlighting “today”.
80
+ else {
81
+ calendar.
82
+ set( 'select', null ).
83
+ set( 'highlight', calendar.item.now )
84
+ }
93
85
 
94
86
 
95
87
  // The keycode to movement mapping.
@@ -99,7 +91,13 @@ function DatePicker( picker, settings ) {
99
91
  39: function() { return isRTL() ? -1 : 1 }, // Right
100
92
  37: function() { return isRTL() ? 1 : -1 }, // Left
101
93
  go: function( timeChange ) {
102
- calendar.set( 'highlight', [ calendar.item.highlight.year, calendar.item.highlight.month, calendar.item.highlight.date + timeChange ], { interval: timeChange } )
94
+ var highlightedObject = calendar.item.highlight,
95
+ targetDate = new Date( highlightedObject.year, highlightedObject.month, highlightedObject.date + timeChange )
96
+ calendar.set(
97
+ 'highlight',
98
+ [ targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate() ],
99
+ { interval: timeChange }
100
+ )
103
101
  this.render()
104
102
  }
105
103
  }
@@ -109,12 +107,18 @@ function DatePicker( picker, settings ) {
109
107
  picker.
110
108
  on( 'render', function() {
111
109
  picker.$root.find( '.' + settings.klass.selectMonth ).on( 'change', function() {
112
- picker.set( 'highlight', [ picker.get( 'view' ).year, this.value, picker.get( 'highlight' ).date ] )
113
- picker.$root.find( '.' + settings.klass.selectMonth ).trigger( 'focus' )
110
+ var value = this.value
111
+ if ( value ) {
112
+ picker.set( 'highlight', [ picker.get( 'view' ).year, value, picker.get( 'highlight' ).date ] )
113
+ picker.$root.find( '.' + settings.klass.selectMonth ).trigger( 'focus' )
114
+ }
114
115
  })
115
116
  picker.$root.find( '.' + settings.klass.selectYear ).on( 'change', function() {
116
- picker.set( 'highlight', [ this.value, picker.get( 'view' ).month, picker.get( 'highlight' ).date ] )
117
- picker.$root.find( '.' + settings.klass.selectYear ).trigger( 'focus' )
117
+ var value = this.value
118
+ if ( value ) {
119
+ picker.set( 'highlight', [ value, picker.get( 'view' ).month, picker.get( 'highlight' ).date ] )
120
+ picker.$root.find( '.' + settings.klass.selectYear ).trigger( 'focus' )
121
+ }
118
122
  })
119
123
  }).
120
124
  on( 'open', function() {
@@ -132,27 +136,38 @@ function DatePicker( picker, settings ) {
132
136
  */
133
137
  DatePicker.prototype.set = function( type, value, options ) {
134
138
 
135
- var calendar = this
139
+ var calendar = this,
140
+ calendarItem = calendar.item
141
+
142
+ // If the value is `null` just set it immediately.
143
+ if ( value === null ) {
144
+ calendarItem[ type ] = value
145
+ return calendar
146
+ }
136
147
 
137
- // Go through the queue of methods, and invoke the function. Update this
138
- // as the time unit, and set the final resultant as this item type.
148
+ // Otherwise go through the queue of methods, and invoke the functions.
149
+ // Update this as the time unit, and set the final value as this item.
139
150
  // * In the case of `enable`, keep the queue but set `disable` instead.
140
151
  // And in the case of `flip`, keep the queue but set `enable` instead.
141
- calendar.item[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = calendar.queue[ type ].split( ' ' ).map( function( method ) {
142
- return value = calendar[ method ]( type, value, options )
152
+ calendarItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = calendar.queue[ type ].split( ' ' ).map( function( method ) {
153
+ value = calendar[ method ]( type, value, options )
154
+ return value
143
155
  }).pop()
144
156
 
145
157
  // Check if we need to cascade through more updates.
146
158
  if ( type == 'select' ) {
147
- calendar.set( 'highlight', calendar.item.select, options )
159
+ calendar.set( 'highlight', calendarItem.select, options )
148
160
  }
149
161
  else if ( type == 'highlight' ) {
150
- calendar.set( 'view', calendar.item.highlight, options )
162
+ calendar.set( 'view', calendarItem.highlight, options )
151
163
  }
152
- else if ( ( type == 'flip' || type == 'min' || type == 'max' || type == 'disable' || type == 'enable' ) && calendar.item.select && calendar.item.highlight ) {
153
- calendar.
154
- set( 'select', calendar.item.select, options ).
155
- set( 'highlight', calendar.item.highlight, options )
164
+ else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) {
165
+ if ( calendarItem.select && calendar.disabled( calendarItem.select ) ) {
166
+ calendar.set( 'select', calendarItem.select, options )
167
+ }
168
+ if ( calendarItem.highlight && calendar.disabled( calendarItem.highlight ) ) {
169
+ calendar.set( 'highlight', calendarItem.highlight, options )
170
+ }
156
171
  }
157
172
 
158
173
  return calendar
@@ -185,7 +200,7 @@ DatePicker.prototype.create = function( type, value, options ) {
185
200
  }
186
201
 
187
202
  // If it’s an object, use the native date object.
188
- else if ( $.isPlainObject( value ) && Picker._.isInteger( value.pick ) ) {
203
+ else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
189
204
  value = value.obj
190
205
  }
191
206
 
@@ -193,11 +208,11 @@ DatePicker.prototype.create = function( type, value, options ) {
193
208
  // that it’s a valid date – otherwise default to today.
194
209
  else if ( $.isArray( value ) ) {
195
210
  value = new Date( value[ 0 ], value[ 1 ], value[ 2 ] )
196
- value = Picker._.isDate( value ) ? value : calendar.create().obj
211
+ value = _.isDate( value ) ? value : calendar.create().obj
197
212
  }
198
213
 
199
214
  // If it’s a number or date object, make a normalized date.
200
- else if ( Picker._.isInteger( value ) || Picker._.isDate( value ) ) {
215
+ else if ( _.isInteger( value ) || _.isDate( value ) ) {
201
216
  value = calendar.normalize( new Date( value ), options )
202
217
  }
203
218
 
@@ -218,6 +233,68 @@ DatePicker.prototype.create = function( type, value, options ) {
218
233
  } //DatePicker.prototype.create
219
234
 
220
235
 
236
+ /**
237
+ * Create a range limit object using an array, date object,
238
+ * literal “true”, or integer relative to another time.
239
+ */
240
+ DatePicker.prototype.createRange = function( from, to ) {
241
+
242
+ var calendar = this,
243
+ createDate = function( date ) {
244
+ if ( date === true || $.isArray( date ) || _.isDate( date ) ) {
245
+ return calendar.create( date )
246
+ }
247
+ return date
248
+ }
249
+
250
+ // Create objects if possible.
251
+ if ( !_.isInteger( from ) ) {
252
+ from = createDate( from )
253
+ }
254
+ if ( !_.isInteger( to ) ) {
255
+ to = createDate( to )
256
+ }
257
+
258
+ // Create relative dates.
259
+ if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
260
+ from = [ to.year, to.month, to.date + from ];
261
+ }
262
+ else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
263
+ to = [ from.year, from.month, from.date + to ];
264
+ }
265
+
266
+ return {
267
+ from: createDate( from ),
268
+ to: createDate( to )
269
+ }
270
+ } //DatePicker.prototype.createRange
271
+
272
+
273
+ /**
274
+ * Check if a date unit falls within a date range object.
275
+ */
276
+ DatePicker.prototype.withinRange = function( range, dateUnit ) {
277
+ range = this.createRange(range.from, range.to)
278
+ return dateUnit.pick >= range.from.pick && dateUnit.pick <= range.to.pick
279
+ }
280
+
281
+
282
+ /**
283
+ * Check if two date range objects overlap.
284
+ */
285
+ DatePicker.prototype.overlapRanges = function( one, two ) {
286
+
287
+ var calendar = this
288
+
289
+ // Convert the ranges into comparable dates.
290
+ one = calendar.createRange( one.from, one.to )
291
+ two = calendar.createRange( two.from, two.to )
292
+
293
+ return calendar.withinRange( one, two.from ) || calendar.withinRange( one, two.to ) ||
294
+ calendar.withinRange( two, one.from ) || calendar.withinRange( two, one.to )
295
+ }
296
+
297
+
221
298
  /**
222
299
  * Get the date today.
223
300
  */
@@ -227,7 +304,7 @@ DatePicker.prototype.now = function( type, value, options ) {
227
304
  value.setDate( value.getDate() + options.rel )
228
305
  }
229
306
  return this.normalize( value, options )
230
- } //DatePicker.prototype.now
307
+ }
231
308
 
232
309
 
233
310
  /**
@@ -235,20 +312,52 @@ DatePicker.prototype.now = function( type, value, options ) {
235
312
  */
236
313
  DatePicker.prototype.navigate = function( type, value, options ) {
237
314
 
238
- if ( $.isPlainObject( value ) ) {
315
+ var targetDateObject,
316
+ targetYear,
317
+ targetMonth,
318
+ targetDate,
319
+ isTargetArray = $.isArray( value ),
320
+ isTargetObject = $.isPlainObject( value ),
321
+ viewsetObject = this.item.view/*,
322
+ safety = 100*/
239
323
 
240
- var targetDateObject = new Date( value.year, value.month + ( options && options.nav ? options.nav : 0 ), 1 ),
241
- year = targetDateObject.getFullYear(),
242
- month = targetDateObject.getMonth(),
243
- date = value.date
244
324
 
245
- // Make sure the date is valid and if the month we’re going to doesn’t have enough
246
- // days, keep decreasing the date until we reach the month’s last date.
247
- while ( Picker._.isDate( targetDateObject ) && new Date( year, month, date ).getMonth() !== month ) {
248
- date -= 1
325
+ if ( isTargetArray || isTargetObject ) {
326
+
327
+ if ( isTargetObject ) {
328
+ targetYear = value.year
329
+ targetMonth = value.month
330
+ targetDate = value.date
331
+ }
332
+ else {
333
+ targetYear = +value[0]
334
+ targetMonth = +value[1]
335
+ targetDate = +value[2]
336
+ }
337
+
338
+ // If we’re navigating months but the view is in a different
339
+ // month, navigate to the view’s year and month.
340
+ if ( options && options.nav && viewsetObject && viewsetObject.month !== targetMonth ) {
341
+ targetYear = viewsetObject.year
342
+ targetMonth = viewsetObject.month
249
343
  }
250
344
 
251
- value = [ year, month, date ]
345
+ // Figure out the expected target year and month.
346
+ targetDateObject = new Date( targetYear, targetMonth + ( options && options.nav ? options.nav : 0 ), 1 )
347
+ targetYear = targetDateObject.getFullYear()
348
+ targetMonth = targetDateObject.getMonth()
349
+
350
+ // If the month we’re going to doesn’t have enough days,
351
+ // keep decreasing the date until we reach the month’s last date.
352
+ while ( /*safety &&*/ new Date( targetYear, targetMonth, targetDate ).getMonth() !== targetMonth ) {
353
+ targetDate -= 1
354
+ /*safety -= 1
355
+ if ( !safety ) {
356
+ throw 'Fell into an infinite loop while navigating to ' + new Date( targetYear, targetMonth, targetDate ) + '.'
357
+ }*/
358
+ }
359
+
360
+ value = [ targetYear, targetMonth, targetDate ]
252
361
  }
253
362
 
254
363
  return value
@@ -277,7 +386,7 @@ DatePicker.prototype.measure = function( type, value/*, options*/ ) {
277
386
  }
278
387
 
279
388
  // If it's an integer, get a date relative to today.
280
- else if ( Picker._.isInteger( value ) ) {
389
+ else if ( _.isInteger( value ) ) {
281
390
  value = calendar.now( type, value, { rel: value } )
282
391
  }
283
392
 
@@ -330,25 +439,27 @@ DatePicker.prototype.validate = function( type, dateObject, options ) {
330
439
  }
331
440
 
332
441
  // Return only integers for enabled weekdays.
333
- return Picker._.isInteger( value )
334
- }).length
442
+ return _.isInteger( value )
443
+ }).length/*,
444
+
445
+ safety = 100*/
335
446
 
336
447
 
337
448
 
338
449
  // Cases to validate for:
339
450
  // [1] Not inverted and date disabled.
340
451
  // [2] Inverted and some dates enabled.
341
- // [3] Out of range.
452
+ // [3] Not inverted and out of range.
342
453
  //
343
454
  // Cases to **not** validate for:
344
455
  // • Navigating months.
345
456
  // • Not inverted and date enabled.
346
457
  // • Inverted and all dates disabled.
347
458
  // • ..and anything else.
348
- if ( !options.nav ) if (
459
+ if ( !options || !options.nav ) if (
349
460
  /* 1 */ ( !isFlippedBase && calendar.disabled( dateObject ) ) ||
350
461
  /* 2 */ ( isFlippedBase && calendar.disabled( dateObject ) && ( hasEnabledWeekdays || hasEnabledBeforeTarget || hasEnabledAfterTarget ) ) ||
351
- /* 3 */ ( dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick )
462
+ /* 3 */ ( !isFlippedBase && (dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick) )
352
463
  ) {
353
464
 
354
465
 
@@ -360,24 +471,31 @@ DatePicker.prototype.validate = function( type, dateObject, options ) {
360
471
 
361
472
 
362
473
  // Keep looping until we reach an enabled date.
363
- while ( calendar.disabled( dateObject ) ) {
474
+ while ( /*safety &&*/ calendar.disabled( dateObject ) ) {
364
475
 
476
+ /*safety -= 1
477
+ if ( !safety ) {
478
+ throw 'Fell into an infinite loop while validating ' + dateObject.obj + '.'
479
+ }*/
365
480
 
366
- // If we’ve looped into the next/prev month, return to the original date and flatten the interval.
481
+
482
+ // If we’ve looped into the next/prev month with a large interval, return to the original date and flatten the interval.
367
483
  if ( Math.abs( interval ) > 1 && ( dateObject.month < originalDateObject.month || dateObject.month > originalDateObject.month ) ) {
368
484
  dateObject = originalDateObject
369
- interval = Math.abs( interval ) / interval
485
+ interval = interval > 0 ? 1 : -1
370
486
  }
371
487
 
372
488
 
373
- // If we’ve reached the min/max limit, reverse the direction and flatten the interval.
489
+ // If we’ve reached the min/max limit, reverse the direction, flatten the interval and set it to the limit.
374
490
  if ( dateObject.pick <= minLimitObject.pick ) {
375
491
  reachedMin = true
376
492
  interval = 1
493
+ dateObject = calendar.create([ minLimitObject.year, minLimitObject.month, minLimitObject.date - 1 ])
377
494
  }
378
495
  else if ( dateObject.pick >= maxLimitObject.pick ) {
379
496
  reachedMax = true
380
497
  interval = -1
498
+ dateObject = calendar.create([ maxLimitObject.year, maxLimitObject.month, maxLimitObject.date + 1 ])
381
499
  }
382
500
 
383
501
 
@@ -402,34 +520,41 @@ DatePicker.prototype.validate = function( type, dateObject, options ) {
402
520
  /**
403
521
  * Check if a date is disabled.
404
522
  */
405
- DatePicker.prototype.disabled = function( dateObject ) {
523
+ DatePicker.prototype.disabled = function( dateToVerify ) {
406
524
 
407
- var calendar = this,
525
+ var
526
+ calendar = this,
408
527
 
409
528
  // Filter through the disabled dates to check if this is one.
410
529
  isDisabledMatch = calendar.item.disable.filter( function( dateToDisable ) {
411
530
 
412
531
  // If the date is a number, match the weekday with 0index and `firstDay` check.
413
- if ( Picker._.isInteger( dateToDisable ) ) {
414
- return dateObject.day === ( calendar.settings.firstDay ? dateToDisable : dateToDisable - 1 ) % 7
532
+ if ( _.isInteger( dateToDisable ) ) {
533
+ return dateToVerify.day === ( calendar.settings.firstDay ? dateToDisable : dateToDisable - 1 ) % 7
415
534
  }
416
535
 
417
536
  // If it’s an array or a native JS date, create and match the exact date.
418
- if ( $.isArray( dateToDisable ) || Picker._.isDate( dateToDisable ) ) {
419
- return dateObject.pick === calendar.create( dateToDisable ).pick
537
+ if ( $.isArray( dateToDisable ) || _.isDate( dateToDisable ) ) {
538
+ return dateToVerify.pick === calendar.create( dateToDisable ).pick
539
+ }
540
+
541
+ // If it’s an object, match a date within the “from” and “to” range.
542
+ if ( $.isPlainObject( dateToDisable ) ) {
543
+ return calendar.withinRange( dateToDisable, dateToVerify )
420
544
  }
421
545
  })
422
546
 
423
547
  // If this date matches a disabled date, confirm it’s not inverted.
424
548
  isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( dateToDisable ) {
425
- return $.isArray( dateToDisable ) && dateToDisable[3] == 'inverted'
549
+ return $.isArray( dateToDisable ) && dateToDisable[3] == 'inverted' ||
550
+ $.isPlainObject( dateToDisable ) && dateToDisable.inverted
426
551
  }).length
427
552
 
428
553
  // Check the calendar “enabled” flag and respectively flip the
429
554
  // disabled state. Then also check if it’s beyond the min/max limits.
430
555
  return calendar.item.enable === -1 ? !isDisabledMatch : isDisabledMatch ||
431
- dateObject.pick < calendar.item.min.pick ||
432
- dateObject.pick > calendar.item.max.pick
556
+ dateToVerify.pick < calendar.item.min.pick ||
557
+ dateToVerify.pick > calendar.item.max.pick
433
558
 
434
559
  } //DatePicker.prototype.disabled
435
560
 
@@ -440,18 +565,22 @@ DatePicker.prototype.disabled = function( dateObject ) {
440
565
  DatePicker.prototype.parse = function( type, value, options ) {
441
566
 
442
567
  var calendar = this,
443
- parsingObject = {}
568
+ parsingObject = {},
569
+ monthIndex
444
570
 
445
- if ( !value || Picker._.isInteger( value ) || $.isArray( value ) || Picker._.isDate( value ) || $.isPlainObject( value ) && Picker._.isInteger( value.pick ) ) {
571
+ if ( !value || _.isInteger( value ) || $.isArray( value ) || _.isDate( value ) || $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
446
572
  return value
447
573
  }
448
574
 
449
- // We need a `.format` to parse the value.
575
+ // We need a `.format` to parse the value with.
450
576
  if ( !( options && options.format ) ) {
451
- // should probably default to the default format.
452
- throw "Need a formatting option to parse this.."
577
+ options = options || {}
578
+ options.format = calendar.settings.format
453
579
  }
454
580
 
581
+ // Calculate the month index to adjust with.
582
+ monthIndex = typeof value == 'string' && !options.fromValue ? 1 : 0
583
+
455
584
  // Convert the format into an array and then map through it.
456
585
  calendar.formats.toArray( options.format ).map( function( label ) {
457
586
 
@@ -461,7 +590,7 @@ DatePicker.prototype.parse = function( type, value, options ) {
461
590
 
462
591
  // The format length is from the formatting label function or the
463
592
  // label length without the escaping exclamation (!) mark.
464
- formatLength = formattingLabel ? Picker._.trigger( formattingLabel, calendar, [ value, parsingObject ] ) : label.replace( /^!/, '' ).length
593
+ formatLength = formattingLabel ? _.trigger( formattingLabel, calendar, [ value, parsingObject ] ) : label.replace( /^!/, '' ).length
465
594
 
466
595
  // If there's a format label, split the value up to the format length.
467
596
  // Then add it to the parsing object with appropriate label.
@@ -474,7 +603,11 @@ DatePicker.prototype.parse = function( type, value, options ) {
474
603
  })
475
604
 
476
605
  // If it’s parsing a user provided month value, compensate for month 0index.
477
- return [ parsingObject.yyyy || parsingObject.yy, +( parsingObject.mm || parsingObject.m ) - ( options.data ? 1 : 0 ), parsingObject.dd || parsingObject.d ]
606
+ return [
607
+ parsingObject.yyyy || parsingObject.yy,
608
+ +( parsingObject.mm || parsingObject.m ) - monthIndex,
609
+ parsingObject.dd || parsingObject.d
610
+ ]
478
611
  } //DatePicker.prototype.parse
479
612
 
480
613
 
@@ -509,13 +642,13 @@ DatePicker.prototype.formats = (function() {
509
642
 
510
643
  // If there's string, then get the digits length.
511
644
  // Otherwise return the selected date.
512
- return string ? Picker._.digits( string ) : dateObject.date
645
+ return string ? _.digits( string ) : dateObject.date
513
646
  },
514
647
  dd: function( string, dateObject ) {
515
648
 
516
649
  // If there's a string, then the length is always 2.
517
650
  // Otherwise return the selected date with a leading zero.
518
- return string ? 2 : Picker._.lead( dateObject.date )
651
+ return string ? 2 : _.lead( dateObject.date )
519
652
  },
520
653
  ddd: function( string, dateObject ) {
521
654
 
@@ -533,13 +666,13 @@ DatePicker.prototype.formats = (function() {
533
666
 
534
667
  // If there's a string, then get the length of the digits
535
668
  // Otherwise return the selected month with 0index compensation.
536
- return string ? Picker._.digits( string ) : dateObject.month + 1
669
+ return string ? _.digits( string ) : dateObject.month + 1
537
670
  },
538
671
  mm: function( string, dateObject ) {
539
672
 
540
673
  // If there's a string, then the length is always 2.
541
674
  // Otherwise return the selected month with 0index and leading zero.
542
- return string ? 2 : Picker._.lead( dateObject.month + 1 )
675
+ return string ? 2 : _.lead( dateObject.month + 1 )
543
676
  },
544
677
  mmm: function( string, dateObject ) {
545
678
 
@@ -577,164 +710,229 @@ DatePicker.prototype.formats = (function() {
577
710
  toString: function ( formatString, itemObject ) {
578
711
  var calendar = this
579
712
  return calendar.formats.toArray( formatString ).map( function( label ) {
580
- return Picker._.trigger( calendar.formats[ label ], calendar, [ 0, itemObject ] ) || label.replace( /^!/, '' )
713
+ return _.trigger( calendar.formats[ label ], calendar, [ 0, itemObject ] ) || label.replace( /^!/, '' )
581
714
  }).join( '' )
582
715
  }
583
716
  }
584
717
  })() //DatePicker.prototype.formats
585
718
 
586
719
 
720
+
721
+
587
722
  /**
588
- * Flip an item as enabled or disabled.
723
+ * Check if two date units are the exact.
589
724
  */
590
- DatePicker.prototype.flipItem = function( type, value/*, options*/ ) {
591
-
592
- var calendar = this,
593
- collection = calendar.item.disable,
594
- isFlippedBase = calendar.item.enable === -1
725
+ DatePicker.prototype.isDateExact = function( one, two ) {
595
726
 
596
- // Flip the enabled and disabled dates.
597
- if ( value == 'flip' ) {
598
- calendar.item.enable = isFlippedBase ? 1 : -1
599
- }
727
+ var calendar = this
600
728
 
601
- // Reset the collection and enable the base state.
602
- else if ( ( type == 'enable' && value === true ) || ( type == 'disable' && value === false ) ) {
603
- calendar.item.enable = 1
604
- collection = []
729
+ // When we’re working with weekdays, do a direct comparison.
730
+ if (
731
+ ( _.isInteger( one ) && _.isInteger( two ) ) ||
732
+ ( typeof one == 'boolean' && typeof two == 'boolean' )
733
+ ) {
734
+ return one === two
605
735
  }
606
736
 
607
- // Reset the collection and disable the base state.
608
- else if ( ( type == 'enable' && value === false ) || ( type == 'disable' && value === true ) ) {
609
- calendar.item.enable = -1
610
- collection = []
737
+ // When we’re working with date representations, compare the “pick” value.
738
+ if (
739
+ ( _.isDate( one ) || $.isArray( one ) ) &&
740
+ ( _.isDate( two ) || $.isArray( two ) )
741
+ ) {
742
+ return calendar.create( one ).pick === calendar.create( two ).pick
611
743
  }
612
744
 
613
- // Make sure a collection of things was passed to add/remove.
614
- else if ( $.isArray( value ) ) {
615
-
616
- // Check if we have to add/remove from collection.
617
- if ( isFlippedBase && type == 'enable' || !isFlippedBase && type == 'disable' ) {
618
- collection = calendar.addDisabled( collection, value )
619
- }
620
- else if ( !isFlippedBase && type == 'enable' ) {
621
- collection = calendar.addEnabled( collection, value )
622
- }
623
- else if ( isFlippedBase && type == 'disable' ) {
624
- collection = calendar.removeDisabled( collection, value )
625
- }
745
+ // When we’re working with range objects, compare the “from” and “to”.
746
+ if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
747
+ return calendar.isDateExact( one.from, two.from ) && calendar.isDateExact( one.to, two.to )
626
748
  }
627
749
 
628
- return collection
629
- } //DatePicker.prototype.flipItem
750
+ return false
751
+ }
630
752
 
631
753
 
632
754
  /**
633
- * Add an enabled (inverted) item to the disabled collection.
755
+ * Check if two date units overlap.
634
756
  */
635
- DatePicker.prototype.addEnabled = function( collection, item ) {
757
+ DatePicker.prototype.isDateOverlap = function( one, two ) {
636
758
 
637
759
  var calendar = this
638
760
 
639
- // Go through each item to enable.
640
- item.map( function( timeUnit ) {
641
-
642
- // Check if the time unit is already within the collection.
643
- if ( calendar.filterDisabled( collection, timeUnit, 1 ).length ) {
644
-
645
- // Remove the unit directly from the collection.
646
- collection = calendar.removeDisabled( collection, [timeUnit] )
647
-
648
- // If the unit is an array and it falls within a
649
- // disabled weekday, invert it and then insert it.
650
- if (
651
- $.isArray( timeUnit ) &&
652
- collection.filter( function( disabledDate ) {
653
- return Picker._.isInteger( disabledDate ) && calendar.create( timeUnit ).day === disabledDate - 1
654
- }).length
655
- ) {
656
- timeUnit = timeUnit.slice(0)
657
- timeUnit.push( 'inverted' )
658
- collection.push( timeUnit )
659
- }
660
- }
661
- })
761
+ // When we’re working with a weekday index, compare the days.
762
+ if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) {
763
+ return one === calendar.create( two ).day + 1
764
+ }
765
+ if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
766
+ return two === calendar.create( one ).day + 1
767
+ }
662
768
 
663
- // Return the final collection.
664
- return collection
665
- } //DatePicker.prototype.addEnabled
769
+ // When we’re working with range objects, check if the ranges overlap.
770
+ if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
771
+ return calendar.overlapRanges( one, two )
772
+ }
773
+
774
+ return false
775
+ }
666
776
 
667
777
 
668
778
  /**
669
- * Add an item to the disabled collection.
779
+ * Flip the “enabled” state.
670
780
  */
671
- DatePicker.prototype.addDisabled = function( collection, item ) {
781
+ DatePicker.prototype.flipEnable = function(val) {
782
+ var itemObject = this.item
783
+ itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
784
+ }
672
785
 
673
- var calendar = this
674
786
 
675
- // Go through each item to disable.
676
- item.map( function( timeUnit ) {
787
+ /**
788
+ * Mark a collection of dates as “disabled”.
789
+ */
790
+ DatePicker.prototype.deactivate = function( type, datesToDisable ) {
791
+
792
+ var calendar = this,
793
+ disabledItems = calendar.item.disable.slice(0)
677
794
 
678
- // Add the time unit if it isn’t already within the collection.
679
- if ( !calendar.filterDisabled( collection, timeUnit ).length ) {
680
- collection.push( timeUnit )
681
- }
682
795
 
683
- // If the time unit is an array and falls within the range, just remove it.
684
- else if ( $.isArray( timeUnit ) && calendar.filterDisabled( collection, timeUnit, 1 ).length ) {
685
- collection = calendar.removeDisabled( collection, [timeUnit] )
686
- }
687
- })
796
+ // If we’re flipping, that’s all we need to do.
797
+ if ( datesToDisable == 'flip' ) {
798
+ calendar.flipEnable()
799
+ }
688
800
 
689
- // Return the final collection.
690
- return collection
691
- } //DatePicker.prototype.addDisabled
801
+ else if ( datesToDisable === false ) {
802
+ calendar.flipEnable(1)
803
+ disabledItems = []
804
+ }
692
805
 
806
+ else if ( datesToDisable === true ) {
807
+ calendar.flipEnable(-1)
808
+ disabledItems = []
809
+ }
693
810
 
694
- /**
695
- * Remove an item from the disabled collection.
696
- */
697
- DatePicker.prototype.removeDisabled = function( collection, item ) {
811
+ // Otherwise go through the dates to disable.
812
+ else {
698
813
 
699
- var calendar = this
814
+ datesToDisable.map(function( unitToDisable ) {
700
815
 
701
- // Go through each item to enable.
702
- item.map( function( timeUnit ) {
816
+ var matchFound
703
817
 
704
- // Filter each item out of the collection.
705
- collection = calendar.filterDisabled( collection, timeUnit, 1 )
706
- })
818
+ // When we have disabled items, check for matches.
819
+ // If something is matched, immediately break out.
820
+ for ( var index = 0; index < disabledItems.length; index += 1 ) {
821
+ if ( calendar.isDateExact( unitToDisable, disabledItems[index] ) ) {
822
+ matchFound = true
823
+ break
824
+ }
825
+ }
707
826
 
708
- // Return the final colleciton.
709
- return collection
710
- } //DatePicker.prototype.removeDisabled
827
+ // If nothing was found, add the validated unit to the collection.
828
+ if ( !matchFound ) {
829
+ if (
830
+ _.isInteger( unitToDisable ) ||
831
+ _.isDate( unitToDisable ) ||
832
+ $.isArray( unitToDisable ) ||
833
+ ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
834
+ ) {
835
+ disabledItems.push( unitToDisable )
836
+ }
837
+ }
838
+ })
839
+ }
840
+
841
+ // Return the updated collection.
842
+ return disabledItems
843
+ } //DatePicker.prototype.deactivate
711
844
 
712
845
 
713
846
  /**
714
- * Filter through the disabled collection to find a time unit.
847
+ * Mark a collection of dates as “enabled”.
715
848
  */
716
- DatePicker.prototype.filterDisabled = function( collection, timeUnit, isRemoving ) {
849
+ DatePicker.prototype.activate = function( type, datesToEnable ) {
717
850
 
718
851
  var calendar = this,
852
+ disabledItems = calendar.item.disable,
853
+ disabledItemsCount = disabledItems.length
719
854
 
720
- // Check if the time unit passed is an array or date object.
721
- timeIsObject = $.isArray( timeUnit ) || Picker._.isDate( timeUnit ),
855
+ // If we’re flipping, that’s all we need to do.
856
+ if ( datesToEnable == 'flip' ) {
857
+ calendar.flipEnable()
858
+ }
722
859
 
723
- // Grab the comparison value if it’s an object.
724
- timeObjectValue = timeIsObject && calendar.create( timeUnit ).pick
860
+ else if ( datesToEnable === true ) {
861
+ calendar.flipEnable(1)
862
+ disabledItems = []
863
+ }
725
864
 
726
- // Go through the disabled collection and try to match this time unit.
727
- return collection.filter( function( disabledTimeUnit ) {
865
+ else if ( datesToEnable === false ) {
866
+ calendar.flipEnable(-1)
867
+ disabledItems = []
868
+ }
728
869
 
729
- // Check if it’s an object and the collection item is an object,
730
- // use the comparison values. Otherwise to a direct comparison.
731
- var isMatch = timeIsObject && ( $.isArray( disabledTimeUnit ) || Picker._.isDate( disabledTimeUnit ) ) ?
732
- timeObjectValue === calendar.create( disabledTimeUnit ).pick : timeUnit === disabledTimeUnit
870
+ // Otherwise go through the disabled dates.
871
+ else {
733
872
 
734
- // Invert the match if we’re removing from the collection.
735
- return isRemoving ? !isMatch : isMatch
736
- })
737
- } //DatePicker.prototype.filterDisabled
873
+ datesToEnable.map(function( unitToEnable ) {
874
+
875
+ var matchFound,
876
+ disabledUnit,
877
+ index,
878
+ isExactRange
879
+
880
+ // Go through the disabled items and try to find a match.
881
+ for ( index = 0; index < disabledItemsCount; index += 1 ) {
882
+
883
+ disabledUnit = disabledItems[index]
884
+
885
+ // When an exact match is found, remove it from the collection.
886
+ if ( calendar.isDateExact( disabledUnit, unitToEnable ) ) {
887
+ matchFound = disabledItems[index] = null
888
+ isExactRange = true
889
+ break
890
+ }
891
+
892
+ // When an overlapped match is found, add the “inverted” state to it.
893
+ else if ( calendar.isDateOverlap( disabledUnit, unitToEnable ) ) {
894
+ if ( $.isPlainObject( unitToEnable ) ) {
895
+ unitToEnable.inverted = true
896
+ matchFound = unitToEnable
897
+ }
898
+ else if ( $.isArray( unitToEnable ) ) {
899
+ matchFound = unitToEnable
900
+ if ( !matchFound[3] ) matchFound.push( 'inverted' )
901
+ }
902
+ else if ( _.isDate( unitToEnable ) ) {
903
+ matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
904
+ }
905
+ break
906
+ }
907
+ }
908
+
909
+ // If a match was found, remove a previous duplicate entry.
910
+ if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
911
+ if ( calendar.isDateExact( disabledItems[index], unitToEnable ) ) {
912
+ disabledItems[index] = null
913
+ break
914
+ }
915
+ }
916
+
917
+ // In the event that we’re dealing with an exact range of dates,
918
+ // make sure there are no “inverted” dates because of it.
919
+ if ( isExactRange ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
920
+ if ( calendar.isDateOverlap( disabledItems[index], unitToEnable ) ) {
921
+ disabledItems[index] = null
922
+ break
923
+ }
924
+ }
925
+
926
+ // If something is still matched, add it into the collection.
927
+ if ( matchFound ) {
928
+ disabledItems.push( matchFound )
929
+ }
930
+ })
931
+ }
932
+
933
+ // Return the updated collection.
934
+ return disabledItems.filter(function( val ) { return val != null })
935
+ } //DatePicker.prototype.activate
738
936
 
739
937
 
740
938
  /**
@@ -745,13 +943,14 @@ DatePicker.prototype.nodes = function( isOpen ) {
745
943
  var
746
944
  calendar = this,
747
945
  settings = calendar.settings,
748
- nowObject = calendar.item.now,
749
- selectedObject = calendar.item.select,
750
- highlightedObject = calendar.item.highlight,
751
- viewsetObject = calendar.item.view,
752
- disabledCollection = calendar.item.disable,
753
- minLimitObject = calendar.item.min,
754
- maxLimitObject = calendar.item.max,
946
+ calendarItem = calendar.item,
947
+ nowObject = calendarItem.now,
948
+ selectedObject = calendarItem.select,
949
+ highlightedObject = calendarItem.highlight,
950
+ viewsetObject = calendarItem.view,
951
+ disabledCollection = calendarItem.disable,
952
+ minLimitObject = calendarItem.min,
953
+ maxLimitObject = calendarItem.max,
755
954
 
756
955
 
757
956
  // Create the calendar table head using a copy of weekday labels collection.
@@ -764,20 +963,23 @@ DatePicker.prototype.nodes = function( isOpen ) {
764
963
  }
765
964
 
766
965
  // Create and return the table head group.
767
- return Picker._.node(
966
+ return _.node(
768
967
  'thead',
769
- Picker._.group({
770
- min: 0,
771
- max: DAYS_IN_WEEK - 1,
772
- i: 1,
773
- node: 'th',
774
- item: function( counter ) {
775
- return [
776
- collection[ counter ],
777
- settings.klass.weekdays
778
- ]
779
- }
780
- })
968
+ _.node(
969
+ 'tr',
970
+ _.group({
971
+ min: 0,
972
+ max: DAYS_IN_WEEK - 1,
973
+ i: 1,
974
+ node: 'th',
975
+ item: function( counter ) {
976
+ return [
977
+ collection[ counter ],
978
+ settings.klass.weekdays
979
+ ]
980
+ }
981
+ })
982
+ )
781
983
  ) //endreturn
782
984
  })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysShort ).slice( 0 ) ), //tableHead
783
985
 
@@ -786,7 +988,7 @@ DatePicker.prototype.nodes = function( isOpen ) {
786
988
  createMonthNav = function( next ) {
787
989
 
788
990
  // Otherwise, return the created month tag.
789
- return Picker._.node(
991
+ return _.node(
790
992
  'div',
791
993
  ' ',
792
994
  settings.klass[ 'nav' + ( next ? 'Next' : 'Prev' ) ] + (
@@ -807,7 +1009,7 @@ DatePicker.prototype.nodes = function( isOpen ) {
807
1009
  // If there are months to select, add a dropdown menu.
808
1010
  if ( settings.selectMonths ) {
809
1011
 
810
- return Picker._.node( 'select', Picker._.group({
1012
+ return _.node( 'select', _.group({
811
1013
  min: 0,
812
1014
  max: 11,
813
1015
  i: 1,
@@ -835,7 +1037,7 @@ DatePicker.prototype.nodes = function( isOpen ) {
835
1037
  }
836
1038
 
837
1039
  // If there's a need for a month selector
838
- return Picker._.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month )
1040
+ return _.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month )
839
1041
  }, //createMonthLabel
840
1042
 
841
1043
 
@@ -876,7 +1078,7 @@ DatePicker.prototype.nodes = function( isOpen ) {
876
1078
  highestYear = maxYear
877
1079
  }
878
1080
 
879
- return Picker._.node( 'select', Picker._.group({
1081
+ return _.node( 'select', _.group({
880
1082
  min: lowestYear,
881
1083
  max: highestYear,
882
1084
  i: 1,
@@ -895,23 +1097,23 @@ DatePicker.prototype.nodes = function( isOpen ) {
895
1097
  }
896
1098
 
897
1099
  // Otherwise just return the year focused
898
- return Picker._.node( 'div', focusedYear, settings.klass.year )
1100
+ return _.node( 'div', focusedYear, settings.klass.year )
899
1101
  } //createYearLabel
900
1102
 
901
1103
 
902
1104
  // Create and return the entire calendar.
903
- return Picker._.node(
1105
+ return _.node(
904
1106
  'div',
905
1107
  createMonthNav() + createMonthNav( 1 ) +
906
1108
  createMonthLabel( settings.showMonthsShort ? settings.monthsShort : settings.monthsFull ) +
907
1109
  createYearLabel(),
908
1110
  settings.klass.header
909
- ) + Picker._.node(
1111
+ ) + _.node(
910
1112
  'table',
911
1113
  tableHead +
912
- Picker._.node(
1114
+ _.node(
913
1115
  'tbody',
914
- Picker._.group({
1116
+ _.group({
915
1117
  min: 0,
916
1118
  max: WEEKS_IN_CALENDAR - 1,
917
1119
  i: 1,
@@ -922,7 +1124,7 @@ DatePicker.prototype.nodes = function( isOpen ) {
922
1124
  var shiftDateBy = settings.firstDay && calendar.create([ viewsetObject.year, viewsetObject.month, 1 ]).day === 0 ? -7 : 0
923
1125
 
924
1126
  return [
925
- Picker._.group({
1127
+ _.group({
926
1128
  min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1, // Add 1 for weekday 0index
927
1129
  max: function() {
928
1130
  return this.min + DAYS_IN_WEEK - 1
@@ -934,8 +1136,12 @@ DatePicker.prototype.nodes = function( isOpen ) {
934
1136
  // Convert the time date from a relative date to a target date.
935
1137
  targetDate = calendar.create([ viewsetObject.year, viewsetObject.month, targetDate + ( settings.firstDay ? 1 : 0 ) ])
936
1138
 
1139
+ var isSelected = selectedObject && selectedObject.pick == targetDate.pick,
1140
+ isHighlighted = highlightedObject && highlightedObject.pick == targetDate.pick,
1141
+ isDisabled = disabledCollection && calendar.disabled( targetDate ) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick
1142
+
937
1143
  return [
938
- Picker._.node(
1144
+ _.node(
939
1145
  'div',
940
1146
  targetDate.date,
941
1147
  (function( klasses ) {
@@ -949,23 +1155,33 @@ DatePicker.prototype.nodes = function( isOpen ) {
949
1155
  }
950
1156
 
951
1157
  // Add the `selected` class if something's selected and the time matches.
952
- if ( selectedObject && selectedObject.pick == targetDate.pick ) {
1158
+ if ( isSelected ) {
953
1159
  klasses.push( settings.klass.selected )
954
1160
  }
955
1161
 
956
1162
  // Add the `highlighted` class if something's highlighted and the time matches.
957
- if ( highlightedObject && highlightedObject.pick == targetDate.pick ) {
1163
+ if ( isHighlighted ) {
958
1164
  klasses.push( settings.klass.highlighted )
959
1165
  }
960
1166
 
961
1167
  // Add the `disabled` class if something's disabled and the object matches.
962
- if ( disabledCollection && calendar.disabled( targetDate ) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick ) {
1168
+ if ( isDisabled ) {
963
1169
  klasses.push( settings.klass.disabled )
964
1170
  }
965
1171
 
966
1172
  return klasses.join( ' ' )
967
1173
  })([ settings.klass.day ]),
968
- 'data-pick=' + targetDate.pick
1174
+ 'data-pick=' + targetDate.pick + ' ' + _.ariaAttr({
1175
+ role: 'button',
1176
+ controls: calendar.$node[0].id,
1177
+ checked: isSelected && calendar.$node.val() === _.trigger(
1178
+ calendar.formats.toString,
1179
+ calendar,
1180
+ [ settings.format, targetDate ]
1181
+ ) ? true : null,
1182
+ activedescendant: isHighlighted ? true : null,
1183
+ disabled: isDisabled ? true : null
1184
+ })
969
1185
  )
970
1186
  ] //endreturn
971
1187
  }
@@ -978,10 +1194,10 @@ DatePicker.prototype.nodes = function( isOpen ) {
978
1194
  ) +
979
1195
 
980
1196
  // * For Firefox forms to submit, make sure to set the buttons’ `type` attributes as “button”.
981
- Picker._.node(
1197
+ _.node(
982
1198
  'div',
983
- Picker._.node( 'button', settings.today, settings.klass.buttonToday, 'type=button data-pick=' + nowObject.pick + ( isOpen ? '' : ' disabled' ) ) +
984
- Picker._.node( 'button', settings.clear, settings.klass.buttonClear, 'type=button data-clear=1' + ( isOpen ? '' : ' disabled' ) ),
1199
+ _.node( 'button', settings.today, settings.klass.buttonToday, 'type=button data-pick=' + nowObject.pick + ( isOpen ? '' : ' disabled' ) ) +
1200
+ _.node( 'button', settings.clear, settings.klass.buttonClear, 'type=button data-clear=1' + ( isOpen ? '' : ' disabled' ) ),
985
1201
  settings.klass.footer
986
1202
  ) //endreturn
987
1203
  } //DatePicker.prototype.nodes