vendor/assets/javascripts/pickadate/picker.date.js in pickadate-rails-1.4.0 vs vendor/assets/javascripts/pickadate/picker.date.js in pickadate-rails-1.5.0

- old
+ new

@@ -1,8 +1,8 @@ /*! - * Date picker for pickadate.js v3.4.0 + * Date picker for pickadate.js v3.5.0 * http://amsul.github.io/pickadate.js/date.htm */ (function ( factory ) { @@ -55,10 +55,11 @@ } // The component's item object. calendar.item = {} + calendar.item.clear = null calendar.item.disable = ( settings.disable || [] ).slice( 0 ) calendar.item.enable = -(function( collectionDisabled ) { return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1 })( calendar.item.disable ) @@ -68,14 +69,11 @@ set( 'now' ) // When there’s a value, set the `select`, which in turn // also sets the `highlight` and `view`. if ( valueString ) { - calendar.set( 'select', valueString, { - format: formatString, - fromValue: !!elementValue - }) + calendar.set( 'select', valueString, { format: formatString }) } // If there’s no value, default to highlighting “today”. else { calendar. @@ -139,10 +137,11 @@ var calendar = this, calendarItem = calendar.item // If the value is `null` just set it immediately. if ( value === null ) { + if ( type == 'clear' ) type = 'select' calendarItem[ type ] = value return calendar } // Otherwise go through the queue of methods, and invoke the functions. @@ -288,11 +287,11 @@ // Convert the ranges into comparable dates. one = calendar.createRange( one.from, one.to ) two = calendar.createRange( two.from, two.to ) - return calendar.withinRange( one, two.from ) || calendar.withinRange( one, two.to ) || + return calendar.withinRange( one, two.from ) || calendar.withinRange( one, two.to ) || calendar.withinRange( two, one.from ) || calendar.withinRange( two, one.to ) } /** @@ -488,16 +487,24 @@ // If we’ve reached the min/max limit, reverse the direction, flatten the interval and set it to the limit. if ( dateObject.pick <= minLimitObject.pick ) { reachedMin = true interval = 1 - dateObject = calendar.create([ minLimitObject.year, minLimitObject.month, minLimitObject.date - 1 ]) + dateObject = calendar.create([ + minLimitObject.year, + minLimitObject.month, + minLimitObject.date + (dateObject.pick === minLimitObject.pick ? 0 : -1) + ]) } else if ( dateObject.pick >= maxLimitObject.pick ) { reachedMax = true interval = -1 - dateObject = calendar.create([ maxLimitObject.year, maxLimitObject.month, maxLimitObject.date + 1 ]) + dateObject = calendar.create([ + maxLimitObject.year, + maxLimitObject.month, + maxLimitObject.date + (dateObject.pick === maxLimitObject.pick ? 0 : 1) + ]) } // If we’ve reached both limits, just break out of the loop. if ( reachedMin && reachedMax ) { @@ -563,26 +570,23 @@ * Parse a string into a usable type. */ DatePicker.prototype.parse = function( type, value, options ) { var calendar = this, - parsingObject = {}, - monthIndex + parsingObject = {} - if ( !value || _.isInteger( value ) || $.isArray( value ) || _.isDate( value ) || $.isPlainObject( value ) && _.isInteger( value.pick ) ) { + // If it’s already parsed, we’re good. + if ( !value || typeof value != 'string' ) { return value } // We need a `.format` to parse the value with. if ( !( options && options.format ) ) { options = options || {} options.format = calendar.settings.format } - // Calculate the month index to adjust with. - monthIndex = typeof value == 'string' && !options.fromValue ? 1 : 0 - // Convert the format into an array and then map through it. calendar.formats.toArray( options.format ).map( function( label ) { var // Grab the formatting label. @@ -600,14 +604,14 @@ // Update the value as the substring from format length to end. value = value.substr( formatLength ) }) - // If it’s parsing a user provided month value, compensate for month 0index. + // Compensate for month 0index. return [ parsingObject.yyyy || parsingObject.yy, - +( parsingObject.mm || parsingObject.m ) - monthIndex, + +( parsingObject.mm || parsingObject.m ) - 1, parsingObject.dd || parsingObject.d ] } //DatePicker.prototype.parse @@ -622,11 +626,11 @@ // Grab the first word from the string. var word = string.match( /\w+/ )[ 0 ] // If there's no month index, add it to the date object if ( !dateObject.mm && !dateObject.m ) { - dateObject.m = collection.indexOf( word ) + dateObject.m = collection.indexOf( word ) + 1 } // Return the length of the word. return word.length } @@ -953,15 +957,16 @@ maxLimitObject = calendarItem.max, // Create the calendar table head using a copy of weekday labels collection. // * We do a copy so we don't mutate the original array. - tableHead = (function( collection ) { + tableHead = (function( collection, fullCollection ) { // If the first day should be Monday, move Sunday to the end. if ( settings.firstDay ) { collection.push( collection.shift() ) + fullCollection.push( fullCollection.shift() ) } // Create and return the table head group. return _.node( 'thead', @@ -973,17 +978,18 @@ i: 1, node: 'th', item: function( counter ) { return [ collection[ counter ], - settings.klass.weekdays + settings.klass.weekdays, + 'scope=col title="' + fullCollection[ counter ] + '"' ] } }) ) ) //endreturn - })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysShort ).slice( 0 ) ), //tableHead + })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysShort ).slice( 0 ), settings.weekdaysFull.slice( 0 ) ), //tableHead // Create the nav for next/prev month. createMonthNav = function( next ) { @@ -996,46 +1002,59 @@ // If the focused month is outside the range, disabled the button. ( next && viewsetObject.year >= maxLimitObject.year && viewsetObject.month >= maxLimitObject.month ) || ( !next && viewsetObject.year <= minLimitObject.year && viewsetObject.month <= minLimitObject.month ) ? ' ' + settings.klass.navDisabled : '' ), - 'data-nav=' + ( next || -1 ) + 'data-nav=' + ( next || -1 ) + ' ' + + _.ariaAttr({ + role: 'button', + controls: calendar.$node[0].id + '_table' + }) + ' ' + + 'title="' + (next ? settings.labelMonthNext : settings.labelMonthPrev ) + '"' ) //endreturn }, //createMonthNav // Create the month label. - createMonthLabel = function( monthsCollection ) { + createMonthLabel = function() { + var monthsCollection = settings.showMonthsShort ? settings.monthsShort : settings.monthsFull + // If there are months to select, add a dropdown menu. if ( settings.selectMonths ) { - return _.node( 'select', _.group({ - min: 0, - max: 11, - i: 1, - node: 'option', - item: function( loopedMonth ) { + return _.node( 'select', + _.group({ + min: 0, + max: 11, + i: 1, + node: 'option', + item: function( loopedMonth ) { - return [ + return [ - // The looped month and no classes. - monthsCollection[ loopedMonth ], 0, + // The looped month and no classes. + monthsCollection[ loopedMonth ], 0, - // Set the value and selected index. - 'value=' + loopedMonth + - ( viewsetObject.month == loopedMonth ? ' selected' : '' ) + - ( + // Set the value and selected index. + 'value=' + loopedMonth + + ( viewsetObject.month == loopedMonth ? ' selected' : '' ) + ( - ( viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month ) || - ( viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month ) - ) ? - ' disabled' : '' - ) - ] - } - }), settings.klass.selectMonth, isOpen ? '' : 'disabled' ) + ( + ( viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month ) || + ( viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month ) + ) ? + ' disabled' : '' + ) + ] + } + }), + settings.klass.selectMonth, + ( isOpen ? '' : 'disabled' ) + ' ' + + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' + + 'title="' + settings.labelMonthSelect + '"' + ) } // If there's a need for a month selector return _.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month ) }, //createMonthLabel @@ -1076,39 +1095,43 @@ lowestYear -= availableYears > neededYears ? neededYears : availableYears highestYear = maxYear } - return _.node( 'select', _.group({ - min: lowestYear, - max: highestYear, - i: 1, - node: 'option', - item: function( loopedYear ) { - return [ + return _.node( 'select', + _.group({ + min: lowestYear, + max: highestYear, + i: 1, + node: 'option', + item: function( loopedYear ) { + return [ - // The looped year and no classes. - loopedYear, 0, + // The looped year and no classes. + loopedYear, 0, - // Set the value and selected index. - 'value=' + loopedYear + ( focusedYear == loopedYear ? ' selected' : '' ) - ] - } - }), settings.klass.selectYear, isOpen ? '' : 'disabled' ) + // Set the value and selected index. + 'value=' + loopedYear + ( focusedYear == loopedYear ? ' selected' : '' ) + ] + } + }), + settings.klass.selectYear, + ( isOpen ? '' : 'disabled' ) + ' ' + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' + + 'title="' + settings.labelYearSelect + '"' + ) } // Otherwise just return the year focused return _.node( 'div', focusedYear, settings.klass.year ) } //createYearLabel // Create and return the entire calendar. return _.node( 'div', - createMonthNav() + createMonthNav( 1 ) + - createMonthLabel( settings.showMonthsShort ? settings.monthsShort : settings.monthsFull ) + - createYearLabel(), + ( settings.selectYears ? createYearLabel() + createMonthLabel() : createMonthLabel() + createYearLabel() ) + + createMonthNav() + createMonthNav( 1 ), settings.klass.header ) + _.node( 'table', tableHead + _.node( @@ -1170,36 +1193,48 @@ } return klasses.join( ' ' ) })([ settings.klass.day ]), 'data-pick=' + targetDate.pick + ' ' + _.ariaAttr({ - role: 'button', - controls: calendar.$node[0].id, - checked: isSelected && calendar.$node.val() === _.trigger( + role: 'gridcell', + selected: isSelected && calendar.$node.val() === _.trigger( calendar.formats.toString, calendar, [ settings.format, targetDate ] ) ? true : null, activedescendant: isHighlighted ? true : null, disabled: isDisabled ? true : null }) - ) + ), + '', + _.ariaAttr({ role: 'presentation' }) ] //endreturn } }) ] //endreturn } }) ), - settings.klass.table + settings.klass.table, + 'id="' + calendar.$node[0].id + '_table' + '" ' + _.ariaAttr({ + role: 'grid', + controls: calendar.$node[0].id, + readonly: true + }) ) + // * For Firefox forms to submit, make sure to set the buttons’ `type` attributes as “button”. _.node( 'div', - _.node( 'button', settings.today, settings.klass.buttonToday, 'type=button data-pick=' + nowObject.pick + ( isOpen ? '' : ' disabled' ) ) + - _.node( 'button', settings.clear, settings.klass.buttonClear, 'type=button data-clear=1' + ( isOpen ? '' : ' disabled' ) ), + _.node( 'button', settings.today, settings.klass.buttonToday, + 'type=button data-pick=' + nowObject.pick + + ( isOpen ? '' : ' disabled' ) + ' ' + + _.ariaAttr({ controls: calendar.$node[0].id }) ) + + _.node( 'button', settings.clear, settings.klass.buttonClear, + 'type=button data-clear=1' + + ( isOpen ? '' : ' disabled' ) + ' ' + + _.ariaAttr({ controls: calendar.$node[0].id }) ), settings.klass.footer ) //endreturn } //DatePicker.prototype.nodes @@ -1209,9 +1244,17 @@ * The date picker defaults. */ DatePicker.defaults = (function( prefix ) { return { + + // The title label to use for the month nav buttons + labelMonthNext: 'Next month', + labelMonthPrev: 'Previous month', + + // The title label to use for the dropdown selectors + labelMonthSelect: 'Select a month', + labelYearSelect: 'Select a year', // Months and weekdays monthsFull: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ], monthsShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], weekdaysFull: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],