12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016 |
- /*!
- * Time picker for pickadate.js v3.6.4
- * 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,
- // Update input value on select/clear
- updateInput: 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 )
- }));
|