/*! * Time picker for pickadate.js v3.5.6 * http://amsul.github.io/pickadate.js/time.htm */ (function ( factory ) { // AMD. if ( typeof define == 'function' && define.amd ) define( ['picker', 'jquery'], factory ) // Node.js/browserify. else if ( typeof exports == 'object' ) module.exports = factory( require('./picker.js'), require('jquery') ) // Browser globals. else factory( Picker, jQuery ) }(function( Picker, $ ) { /** * Globals and constants */ var HOURS_IN_DAY = 24, MINUTES_IN_HOUR = 60, HOURS_TO_NOON = 12, MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR, _ = Picker._ /** * The time picker constructor */ function TimePicker( picker, settings ) { var clock = this, elementValue = picker.$node[ 0 ].value, elementDataValue = picker.$node.data( 'value' ), valueString = elementDataValue || elementValue, formatString = elementDataValue ? settings.formatSubmit : settings.format clock.settings = settings clock.$node = picker.$node // The queue of methods that will be used to build item objects. clock.queue = { interval: 'i', min: 'measure create', max: 'measure create', now: 'now create', select: 'parse create validate', highlight: 'parse create validate', view: 'parse create validate', disable: 'deactivate', enable: 'activate' } // The component's item object. clock.item = {} clock.item.clear = null clock.item.interval = settings.interval || 30 clock.item.disable = ( settings.disable || [] ).slice( 0 ) clock.item.enable = -(function( collectionDisabled ) { return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1 })( clock.item.disable ) clock. set( 'min', settings.min ). set( 'max', settings.max ). set( 'now' ) // When there’s a value, set the `select`, which in turn // also sets the `highlight` and `view`. if ( valueString ) { clock.set( 'select', valueString, { format: formatString }) } // If there’s no value, default to highlighting “today”. else { clock. set( 'select', null ). set( 'highlight', clock.item.now ) } // The keycode to movement mapping. clock.key = { 40: 1, // Down 38: -1, // Up 39: 1, // Right 37: -1, // Left go: function( timeChange ) { clock.set( 'highlight', clock.item.highlight.pick + timeChange * clock.item.interval, { interval: timeChange * clock.item.interval } ) this.render() } } // Bind some picker events. picker. on( 'render', function() { var $pickerHolder = picker.$root.children(), $viewset = $pickerHolder.find( '.' + settings.klass.viewset ), vendors = function( prop ) { return ['webkit', 'moz', 'ms', 'o', ''].map(function( vendor ) { return ( vendor ? '-' + vendor + '-' : '' ) + prop }) }, animations = function( $el, state ) { vendors( 'transform' ).map(function( prop ) { $el.css( prop, state ) }) vendors( 'transition' ).map(function( prop ) { $el.css( prop, state ) }) } if ( $viewset.length ) { animations( $pickerHolder, 'none' ) $pickerHolder[ 0 ].scrollTop = ~~$viewset.position().top - ( $viewset[ 0 ].clientHeight * 2 ) animations( $pickerHolder, '' ) } }, 1 ). on( 'open', function() { picker.$root.find( 'button' ).attr( 'disabled', false ) }, 1 ). on( 'close', function() { picker.$root.find( 'button' ).attr( 'disabled', true ) }, 1 ) } //TimePicker /** * Set a timepicker item object. */ TimePicker.prototype.set = function( type, value, options ) { var clock = this, clockItem = clock.item // If the value is `null` just set it immediately. if ( value === null ) { if ( type == 'clear' ) type = 'select' clockItem[ type ] = value return clock } // Otherwise go through the queue of methods, and invoke the functions. // Update this as the time unit, and set the final value as this item. // * In the case of `enable`, keep the queue but set `disable` instead. // And in the case of `flip`, keep the queue but set `enable` instead. clockItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = clock.queue[ type ].split( ' ' ).map( function( method ) { value = clock[ method ]( type, value, options ) return value }).pop() // Check if we need to cascade through more updates. if ( type == 'select' ) { clock.set( 'highlight', clockItem.select, options ) } else if ( type == 'highlight' ) { clock.set( 'view', clockItem.highlight, options ) } else if ( type == 'interval' ) { clock. set( 'min', clockItem.min, options ). set( 'max', clockItem.max, options ) } else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) { if ( clockItem.select && clock.disabled( clockItem.select ) ) { clock.set( 'select', value, options ) } if ( clockItem.highlight && clock.disabled( clockItem.highlight ) ) { clock.set( 'highlight', value, options ) } if ( type == 'min' ) { clock.set( 'max', clockItem.max, options ) } } return clock } //TimePicker.prototype.set /** * Get a timepicker item object. */ TimePicker.prototype.get = function( type ) { return this.item[ type ] } //TimePicker.prototype.get /** * Create a picker time object. */ TimePicker.prototype.create = function( type, value, options ) { var clock = this // If there’s no value, use the type as the value. value = value === undefined ? type : value // If it’s a date object, convert it into an array. if ( _.isDate( value ) ) { value = [ value.getHours(), value.getMinutes() ] } // If it’s an object, use the “pick” value. if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) { value = value.pick } // If it’s an array, convert it into minutes. else if ( $.isArray( value ) ) { value = +value[ 0 ] * MINUTES_IN_HOUR + (+value[ 1 ]) } // If no valid value is passed, set it to “now”. else if ( !_.isInteger( value ) ) { value = clock.now( type, value, options ) } // If we’re setting the max, make sure it’s greater than the min. if ( type == 'max' && value < clock.item.min.pick ) { value += MINUTES_IN_DAY } // If the value doesn’t fall directly on the interval, // add one interval to indicate it as “passed”. if ( type != 'min' && type != 'max' && (value - clock.item.min.pick) % clock.item.interval !== 0 ) { value += clock.item.interval } // Normalize it into a “reachable” interval. value = clock.normalize( type, value, options ) // Return the compiled object. return { // Divide to get hours from minutes. hour: ~~( HOURS_IN_DAY + value / MINUTES_IN_HOUR ) % HOURS_IN_DAY, // The remainder is the minutes. mins: ( MINUTES_IN_HOUR + value % MINUTES_IN_HOUR ) % MINUTES_IN_HOUR, // The time in total minutes. time: ( MINUTES_IN_DAY + value ) % MINUTES_IN_DAY, // Reference to the “relative” value to pick. pick: value % MINUTES_IN_DAY } } //TimePicker.prototype.create /** * Create a range limit object using an array, date object, * literal “true”, or integer relative to another time. */ TimePicker.prototype.createRange = function( from, to ) { var clock = this, createTime = function( time ) { if ( time === true || $.isArray( time ) || _.isDate( time ) ) { return clock.create( time ) } return time } // Create objects if possible. if ( !_.isInteger( from ) ) { from = createTime( from ) } if ( !_.isInteger( to ) ) { to = createTime( to ) } // Create relative times. if ( _.isInteger( from ) && $.isPlainObject( to ) ) { from = [ to.hour, to.mins + ( from * clock.settings.interval ) ]; } else if ( _.isInteger( to ) && $.isPlainObject( from ) ) { to = [ from.hour, from.mins + ( to * clock.settings.interval ) ]; } return { from: createTime( from ), to: createTime( to ) } } //TimePicker.prototype.createRange /** * Check if a time unit falls within a time range object. */ TimePicker.prototype.withinRange = function( range, timeUnit ) { range = this.createRange(range.from, range.to) return timeUnit.pick >= range.from.pick && timeUnit.pick <= range.to.pick } /** * Check if two time range objects overlap. */ TimePicker.prototype.overlapRanges = function( one, two ) { var clock = this // Convert the ranges into comparable times. one = clock.createRange( one.from, one.to ) two = clock.createRange( two.from, two.to ) return clock.withinRange( one, two.from ) || clock.withinRange( one, two.to ) || clock.withinRange( two, one.from ) || clock.withinRange( two, one.to ) } /** * Get the time relative to now. */ TimePicker.prototype.now = function( type, value/*, options*/ ) { var interval = this.item.interval, date = new Date(), nowMinutes = date.getHours() * MINUTES_IN_HOUR + date.getMinutes(), isValueInteger = _.isInteger( value ), isBelowInterval // Make sure “now” falls within the interval range. nowMinutes -= nowMinutes % interval // Check if the difference is less than the interval itself. isBelowInterval = value < 0 && interval * value + nowMinutes <= -interval // Add an interval because the time has “passed”. nowMinutes += type == 'min' && isBelowInterval ? 0 : interval // If the value is a number, adjust by that many intervals. if ( isValueInteger ) { nowMinutes += interval * ( isBelowInterval && type != 'max' ? value + 1 : value ) } // Return the final calculation. return nowMinutes } //TimePicker.prototype.now /** * Normalize minutes to be “reachable” based on the min and interval. */ TimePicker.prototype.normalize = function( type, value/*, options*/ ) { var interval = this.item.interval, minTime = this.item.min && this.item.min.pick || 0 // If setting min time, don’t shift anything. // Otherwise get the value and min difference and then // normalize the difference with the interval. value -= type == 'min' ? 0 : ( value - minTime ) % interval // Return the adjusted value. return value } //TimePicker.prototype.normalize /** * Measure the range of minutes. */ TimePicker.prototype.measure = function( type, value, options ) { var clock = this // If it’s anything false-y, set it to the default. if ( !value ) { value = type == 'min' ? [ 0, 0 ] : [ HOURS_IN_DAY - 1, MINUTES_IN_HOUR - 1 ] } // If it’s a string, parse it. if ( typeof value == 'string' ) { value = clock.parse( type, value ) } // If it’s a literal true, or an integer, make it relative to now. else if ( value === true || _.isInteger( value ) ) { value = clock.now( type, value, options ) } // If it’s an object already, just normalize it. else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) { value = clock.normalize( type, value.pick, options ) } return value } ///TimePicker.prototype.measure /** * Validate an object as enabled. */ TimePicker.prototype.validate = function( type, timeObject, options ) { var clock = this, interval = options && options.interval ? options.interval : clock.item.interval // Check if the object is disabled. if ( clock.disabled( timeObject ) ) { // Shift with the interval until we reach an enabled time. timeObject = clock.shift( timeObject, interval ) } // Scope the object into range. timeObject = clock.scope( timeObject ) // Do a second check to see if we landed on a disabled min/max. // In that case, shift using the opposite interval as before. if ( clock.disabled( timeObject ) ) { timeObject = clock.shift( timeObject, interval * -1 ) } // Return the final object. return timeObject } //TimePicker.prototype.validate /** * Check if an object is disabled. */ TimePicker.prototype.disabled = function( timeToVerify ) { var clock = this, // Filter through the disabled times to check if this is one. isDisabledMatch = clock.item.disable.filter( function( timeToDisable ) { // If the time is a number, match the hours. if ( _.isInteger( timeToDisable ) ) { return timeToVerify.hour == timeToDisable } // If it’s an array, create the object and match the times. if ( $.isArray( timeToDisable ) || _.isDate( timeToDisable ) ) { return timeToVerify.pick == clock.create( timeToDisable ).pick } // If it’s an object, match a time within the “from” and “to” range. if ( $.isPlainObject( timeToDisable ) ) { return clock.withinRange( timeToDisable, timeToVerify ) } }) // If this time matches a disabled time, confirm it’s not inverted. isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( timeToDisable ) { return $.isArray( timeToDisable ) && timeToDisable[2] == 'inverted' || $.isPlainObject( timeToDisable ) && timeToDisable.inverted }).length // If the clock is "enabled" flag is flipped, flip the condition. return clock.item.enable === -1 ? !isDisabledMatch : isDisabledMatch || timeToVerify.pick < clock.item.min.pick || timeToVerify.pick > clock.item.max.pick } //TimePicker.prototype.disabled /** * Shift an object by an interval until we reach an enabled object. */ TimePicker.prototype.shift = function( timeObject, interval ) { var clock = this, minLimit = clock.item.min.pick, maxLimit = clock.item.max.pick/*, safety = 1000*/ interval = interval || clock.item.interval // Keep looping as long as the time is disabled. while ( /*safety &&*/ clock.disabled( timeObject ) ) { /*safety -= 1 if ( !safety ) { throw 'Fell into an infinite loop while shifting to ' + timeObject.hour + ':' + timeObject.mins + '.' }*/ // Increase/decrease the time by the interval and keep looping. timeObject = clock.create( timeObject.pick += interval ) // If we've looped beyond the limits, break out of the loop. if ( timeObject.pick <= minLimit || timeObject.pick >= maxLimit ) { break } } // Return the final object. return timeObject } //TimePicker.prototype.shift /** * Scope an object to be within range of min and max. */ TimePicker.prototype.scope = function( timeObject ) { var minLimit = this.item.min.pick, maxLimit = this.item.max.pick return this.create( timeObject.pick > maxLimit ? maxLimit : timeObject.pick < minLimit ? minLimit : timeObject ) } //TimePicker.prototype.scope /** * Parse a string into a usable type. */ TimePicker.prototype.parse = function( type, value, options ) { var hour, minutes, isPM, item, parseValue, clock = this, parsingObject = {} // 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 = clock.settings.format } // Convert the format into an array and then map through it. clock.formats.toArray( options.format ).map( function( label ) { var substring, // Grab the formatting label. formattingLabel = clock.formats[ label ], // The format length is from the formatting label function or the // label length without the escaping exclamation (!) mark. formatLength = formattingLabel ? _.trigger( formattingLabel, clock, [ value, parsingObject ] ) : label.replace( /^!/, '' ).length // If there's a format label, split the value up to the format length. // Then add it to the parsing object with appropriate label. if ( formattingLabel ) { substring = value.substr( 0, formatLength ) parsingObject[ label ] = substring.match(/^\d+$/) ? +substring : substring } // Update the time value as the substring from format length to end. value = value.substr( formatLength ) }) // Grab the hour and minutes from the parsing object. for ( item in parsingObject ) { parseValue = parsingObject[item] if ( _.isInteger(parseValue) ) { if ( item.match(/^(h|hh)$/i) ) { hour = parseValue if ( item == 'h' || item == 'hh' ) { hour %= 12 } } else if ( item == 'i' ) { minutes = parseValue } } else if ( item.match(/^a$/i) && parseValue.match(/^p/i) && ('h' in parsingObject || 'hh' in parsingObject) ) { isPM = true } } // Calculate it in minutes and return. return (isPM ? hour + 12 : hour) * MINUTES_IN_HOUR + minutes } //TimePicker.prototype.parse /** * Various formats to display the object in. */ TimePicker.prototype.formats = { h: function( string, timeObject ) { // If there's string, then get the digits length. // Otherwise return the selected hour in "standard" format. return string ? _.digits( string ) : timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON }, hh: function( string, timeObject ) { // If there's a string, then the length is always 2. // Otherwise return the selected hour in "standard" format with a leading zero. return string ? 2 : _.lead( timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON ) }, H: function( string, timeObject ) { // If there's string, then get the digits length. // Otherwise return the selected hour in "military" format as a string. return string ? _.digits( string ) : '' + ( timeObject.hour % 24 ) }, HH: function( string, timeObject ) { // If there's string, then get the digits length. // Otherwise return the selected hour in "military" format with a leading zero. return string ? _.digits( string ) : _.lead( timeObject.hour % 24 ) }, i: function( string, timeObject ) { // If there's a string, then the length is always 2. // Otherwise return the selected minutes. return string ? 2 : _.lead( timeObject.mins ) }, a: function( string, timeObject ) { // If there's a string, then the length is always 4. // Otherwise check if it's more than "noon" and return either am/pm. return string ? 4 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'a.m.' : 'p.m.' }, A: function( string, timeObject ) { // If there's a string, then the length is always 2. // Otherwise check if it's more than "noon" and return either am/pm. return string ? 2 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'AM' : 'PM' }, // Create an array by splitting the formatting string passed. toArray: function( formatString ) { return formatString.split( /(h{1,2}|H{1,2}|i|a|A|!.)/g ) }, // Format an object into a string using the formatting options. toString: function ( formatString, itemObject ) { var clock = this return clock.formats.toArray( formatString ).map( function( label ) { return _.trigger( clock.formats[ label ], clock, [ 0, itemObject ] ) || label.replace( /^!/, '' ) }).join( '' ) } } //TimePicker.prototype.formats /** * Check if two time units are the exact. */ TimePicker.prototype.isTimeExact = function( one, two ) { var clock = this // When we’re working with minutes, do a direct comparison. if ( ( _.isInteger( one ) && _.isInteger( two ) ) || ( typeof one == 'boolean' && typeof two == 'boolean' ) ) { return one === two } // When we’re working with time representations, compare the “pick” value. if ( ( _.isDate( one ) || $.isArray( one ) ) && ( _.isDate( two ) || $.isArray( two ) ) ) { return clock.create( one ).pick === clock.create( two ).pick } // When we’re working with range objects, compare the “from” and “to”. if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) { return clock.isTimeExact( one.from, two.from ) && clock.isTimeExact( one.to, two.to ) } return false } /** * Check if two time units overlap. */ TimePicker.prototype.isTimeOverlap = function( one, two ) { var clock = this // When we’re working with an integer, compare the hours. if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) { return one === clock.create( two ).hour } if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) { return two === clock.create( one ).hour } // When we’re working with range objects, check if the ranges overlap. if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) { return clock.overlapRanges( one, two ) } return false } /** * Flip the “enabled” state. */ TimePicker.prototype.flipEnable = function(val) { var itemObject = this.item itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1) } /** * Mark a collection of times as “disabled”. */ TimePicker.prototype.deactivate = function( type, timesToDisable ) { var clock = this, disabledItems = clock.item.disable.slice(0) // If we’re flipping, that’s all we need to do. if ( timesToDisable == 'flip' ) { clock.flipEnable() } else if ( timesToDisable === false ) { clock.flipEnable(1) disabledItems = [] } else if ( timesToDisable === true ) { clock.flipEnable(-1) disabledItems = [] } // Otherwise go through the times to disable. else { timesToDisable.map(function( unitToDisable ) { var matchFound // When we have disabled items, check for matches. // If something is matched, immediately break out. for ( var index = 0; index < disabledItems.length; index += 1 ) { if ( clock.isTimeExact( unitToDisable, disabledItems[index] ) ) { matchFound = true break } } // If nothing was found, add the validated unit to the collection. if ( !matchFound ) { if ( _.isInteger( unitToDisable ) || _.isDate( unitToDisable ) || $.isArray( unitToDisable ) || ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to ) ) { disabledItems.push( unitToDisable ) } } }) } // Return the updated collection. return disabledItems } //TimePicker.prototype.deactivate /** * Mark a collection of times as “enabled”. */ TimePicker.prototype.activate = function( type, timesToEnable ) { var clock = this, disabledItems = clock.item.disable, disabledItemsCount = disabledItems.length // If we’re flipping, that’s all we need to do. if ( timesToEnable == 'flip' ) { clock.flipEnable() } else if ( timesToEnable === true ) { clock.flipEnable(1) disabledItems = [] } else if ( timesToEnable === false ) { clock.flipEnable(-1) disabledItems = [] } // Otherwise go through the disabled times. else { timesToEnable.map(function( unitToEnable ) { var matchFound, disabledUnit, index, isRangeMatched // Go through the disabled items and try to find a match. for ( index = 0; index < disabledItemsCount; index += 1 ) { disabledUnit = disabledItems[index] // When an exact match is found, remove it from the collection. if ( clock.isTimeExact( disabledUnit, unitToEnable ) ) { matchFound = disabledItems[index] = null isRangeMatched = true break } // When an overlapped match is found, add the “inverted” state to it. else if ( clock.isTimeOverlap( disabledUnit, unitToEnable ) ) { if ( $.isPlainObject( unitToEnable ) ) { unitToEnable.inverted = true matchFound = unitToEnable } else if ( $.isArray( unitToEnable ) ) { matchFound = unitToEnable if ( !matchFound[2] ) matchFound.push( 'inverted' ) } else if ( _.isDate( unitToEnable ) ) { matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ] } break } } // If a match was found, remove a previous duplicate entry. if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) { if ( clock.isTimeExact( disabledItems[index], unitToEnable ) ) { disabledItems[index] = null break } } // In the event that we’re dealing with an overlap of range times, // make sure there are no “inverted” times because of it. if ( isRangeMatched ) for ( index = 0; index < disabledItemsCount; index += 1 ) { if ( clock.isTimeOverlap( disabledItems[index], unitToEnable ) ) { disabledItems[index] = null break } } // If something is still matched, add it into the collection. if ( matchFound ) { disabledItems.push( matchFound ) } }) } // Return the updated collection. return disabledItems.filter(function( val ) { return val != null }) } //TimePicker.prototype.activate /** * The division to use for the range intervals. */ TimePicker.prototype.i = function( type, value/*, options*/ ) { return _.isInteger( value ) && value > 0 ? value : this.item.interval } /** * Create a string for the nodes in the picker. */ TimePicker.prototype.nodes = function( isOpen ) { var clock = this, settings = clock.settings, selectedObject = clock.item.select, highlightedObject = clock.item.highlight, viewsetObject = clock.item.view, disabledCollection = clock.item.disable return _.node( 'ul', _.group({ min: clock.item.min.pick, max: clock.item.max.pick, i: clock.item.interval, node: 'li', item: function( loopedTime ) { loopedTime = clock.create( loopedTime ) var timeMinutes = loopedTime.pick, isSelected = selectedObject && selectedObject.pick == timeMinutes, isHighlighted = highlightedObject && highlightedObject.pick == timeMinutes, isDisabled = disabledCollection && clock.disabled( loopedTime ), formattedTime = _.trigger( clock.formats.toString, clock, [ settings.format, loopedTime ] ) return [ _.trigger( clock.formats.toString, clock, [ _.trigger( settings.formatLabel, clock, [ loopedTime ] ) || settings.format, loopedTime ] ), (function( klasses ) { if ( isSelected ) { klasses.push( settings.klass.selected ) } if ( isHighlighted ) { klasses.push( settings.klass.highlighted ) } if ( viewsetObject && viewsetObject.pick == timeMinutes ) { klasses.push( settings.klass.viewset ) } if ( isDisabled ) { klasses.push( settings.klass.disabled ) } return klasses.join( ' ' ) })( [ settings.klass.listItem ] ), 'data-pick=' + loopedTime.pick + ' ' + _.ariaAttr({ role: 'option', label: formattedTime, selected: isSelected && clock.$node.val() === formattedTime ? true : null, activedescendant: isHighlighted ? true : null, disabled: isDisabled ? true : null }) ] } }) + // * For Firefox forms to submit, make sure to set the button’s `type` attribute as “button”. _.node( 'li', _.node( 'button', settings.clear, settings.klass.buttonClear, 'type=button data-clear=1' + ( isOpen ? '' : ' disabled' ) + ' ' + _.ariaAttr({ controls: clock.$node[0].id }) ), '', _.ariaAttr({ role: 'presentation' }) ), settings.klass.list, _.ariaAttr({ role: 'listbox', controls: clock.$node[0].id }) ) } //TimePicker.prototype.nodes /** * Extend the picker to add the component with the defaults. */ TimePicker.defaults = (function( prefix ) { return { // Clear clear: 'Clear', // The format to show on the `input` element format: 'h:i A', // The interval between each time interval: 30, // Picker close behavior closeOnSelect: true, closeOnClear: true, // Classes klass: { picker: prefix + ' ' + prefix + '--time', holder: prefix + '__holder', list: prefix + '__list', listItem: prefix + '__list-item', disabled: prefix + '__list-item--disabled', selected: prefix + '__list-item--selected', highlighted: prefix + '__list-item--highlighted', viewset: prefix + '__list-item--viewset', now: prefix + '__list-item--now', buttonClear: prefix + '__button--clear' } } })( Picker.klasses().picker ) /** * Extend the picker to add the time picker. */ Picker.extend( 'pickatime', TimePicker ) }));