PageSourceSearch

https://eventos.tokyo/lib/picker.time.js

js eventos.tokyo collected 2026-09-24 08:25:04 UTC 31,975 bytes, 1,016 lines download raw bytes

1/*!
2 * Time picker for pickadate.js v3.6.2
3 * http://amsul.github.io/pickadate.js/time.htm
4 */
5
6(function ( factory ) {
7
8    // AMD.
9    if ( typeof define == 'function' && define.amd )
10        define( ['./picker', 'jquery'], factory )
11
12    // Node.js/browserify.
13    else if ( typeof exports == 'object' )
14        module.exports = factory( require('./picker.js'), require('jquery') )
15
16    // Browser globals.
17    else factory( Picker, jQuery )
18
19}(function( Picker, $ ) {
20
21
22/**
23 * Globals and constants
24 */
25var HOURS_IN_DAY = 24,
26    MINUTES_IN_HOUR = 60,
27    HOURS_TO_NOON = 12,
28    MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR,
29    _ = Picker._
30
31
32
33/**
34 * The time picker constructor
35 */
36function TimePicker( picker, settings ) {
37
38    var clock = this,
39        elementValue = picker.$node[ 0 ].value,
40        elementDataValue = picker.$node.data( 'value' ),
41        valueString = elementDataValue || elementValue,
42        formatString = elementDataValue ? settings.formatSubmit : settings.format
43
44    clock.settings = settings
45    clock.$node = picker.$node
46
47    // The queue of methods that will be used to build item objects.
48    clock.queue = {
49        interval: 'i',
50        min: 'measure create',
51        max: 'measure create',
52        now: 'now create',
53        select: 'parse create validate',
54        highlight: 'parse create validate',
55        view: 'parse create validate',
56        disable: 'deactivate',
57        enable: 'activate'
58    }
59
60    // The component's item object.
61    clock.item = {}
62
63    clock.item.clear = null
64    clock.item.interval = settings.interval || 30
65    clock.item.disable = ( settings.disable || [] ).slice( 0 )
66    clock.item.enable = -(function( collectionDisabled ) {
67        return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1
68    })( clock.item.disable )
69
70    clock.
71        set( 'min', settings.min ).
72        set( 'max', settings.max ).
73        set( 'now' )
74
75    // When there’s a value, set the `select`, which in turn
76    // also sets the `highlight` and `view`.
77    if ( valueString ) {
78        clock.set( 'select', valueString, {
79            format: formatString
80        })
81    }
82
83    // If there’s no value, default to highlighting “today”.
84    else {
85        clock.
86            set( 'select', null ).
87            set( 'highlight', clock.item.now )
88    }
89
90    // The keycode to movement mapping.
91    clock.key = {
92        40: 1, // Down
93        38: -1, // Up
94        39: 1, // Right
95        37: -1, // Left
96        go: function( timeChange ) {
97            clock.set(
98                'highlight',
99                clock.item.highlight.pick + timeChange * clock.item.interval,
100                { interval: timeChange * clock.item.interval }
101            )
102            this.render()
103        }
104    }
105
106
107    // Bind some picker events.
108    picker.
109        on( 'render', function() {
110            var $pickerHolder = picker.$root.children(),
111                $viewset = $pickerHolder.find( '.' + settings.klass.viewset ),
112                vendors = function( prop ) {
113                    return ['webkit', 'moz', 'ms', 'o', ''].map(function( vendor ) {
114                        return ( vendor ? '-' + vendor + '-' : '' ) + prop
115                    })
116                },
117                animations = function( $el, state ) {
118                    vendors( 'transform' ).map(function( prop ) {
119                        $el.css( prop, state )
120                    })
121                    vendors( 'transition' ).map(function( prop ) {
122                        $el.css( prop, state )
123                    })
124                }
125            if ( $viewset.length ) {
126                animations( $pickerHolder, 'none' )
127                $pickerHolder[ 0 ].scrollTop = ~~$viewset.position().top - ( $viewset[ 0 ].clientHeight * 2 )
128                animations( $pickerHolder, '' )
129            }
130        }, 1 ).
131        on( 'open', function() {
132            picker.$root.find( 'button' ).attr( 'disabled', false )
133        }, 1 ).
134        on( 'close', function() {
135            picker.$root.find( 'button' ).attr( 'disabled', true )
136        }, 1 )
137
138} //TimePicker
139
140
141/**
142 * Set a timepicker item object.
143 */
144TimePicker.prototype.set = function( type, value, options ) {
145
146    var clock = this,
147        clockItem = clock.item
148
149    // If the value is `null` just set it immediately.
150    if ( value === null ) {
151        if ( type == 'clear' ) type = 'select'
152        clockItem[ type ] = value
153        return clock
154    }
155
156    // Otherwise go through the queue of methods, and invoke the functions.
157    // Update this as the time unit, and set the final value as this item.
158    // * In the case of `enable`, keep the queue but set `disable` instead.
159    //   And in the case of `flip`, keep the queue but set `enable` instead.
160    clockItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = clock.queue[ type ].split( ' ' ).map( function( method ) {
161        value = clock[ method ]( type, value, options )
162        return value
163    }).pop()
164
165    // Check if we need to cascade through more updates.
166    if ( type == 'select' ) {
167        clock.set( 'highlight', clockItem.select, options )
168    }
169    else if ( type == 'highlight' ) {
170        clock.set( 'view', clockItem.highlight, options )
171    }
172    else if ( type == 'interval' ) {
173        clock.
174            set( 'min', clockItem.min, options ).
175            set( 'max', clockItem.max, options )
176    }
177    else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) {
178        if ( clockItem.select && clock.disabled( clockItem.select ) ) {
179            clock.set( 'select', value, options )
180        }
181        if ( clockItem.highlight && clock.disabled( clockItem.highlight ) ) {
182            clock.set( 'highlight', value, options )
183        }
184        if ( type == 'min' ) {
185            clock.set( 'max', clockItem.max, options )
186        }
187    }
188
189    return clock
190} //TimePicker.prototype.set
191
192
193/**
194 * Get a timepicker item object.
195 */
196TimePicker.prototype.get = function( type ) {
197    return this.item[ type ]
198} //TimePicker.prototype.get
199
200
201/**
202 * Create a picker time object.
203 */
204TimePicker.prototype.create = function( type, value, options ) {
205
206    var clock = this
207
208    // If there’s no value, use the type as the value.
209    value = value === undefined ? type : value
210
211    // If it’s a date object, convert it into an array.
212    if ( _.isDate( value ) ) {
213        value = [ value.getHours(), value.getMinutes() ]
214    }
215
216    // If it’s an object, use the “pick” value.
217    if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
218        value = value.pick
219    }
220
221    // If it’s an array, convert it into minutes.
222    else if ( $.isArray( value ) ) {
223        value = +value[ 0 ] * MINUTES_IN_HOUR + (+value[ 1 ])
224    }
225
226    // If no valid value is passed, set it to “now”.
227    else if ( !_.isInteger( value ) ) {
228        value = clock.now( type, value, options )
229    }
230
231    // If we’re setting the max, make sure it’s greater than the min.
232    if ( type == 'max' && value < clock.item.min.pick ) {
233        value += MINUTES_IN_DAY
234    }
235
236    // If the value doesn’t fall directly on the interval,
237    // add one interval to indicate it as “passed”.
238    if ( type != 'min' && type != 'max' && (value - clock.item.min.pick) % clock.item.interval !== 0 ) {
239        value += clock.item.interval
240    }
241
242    // Normalize it into a “reachable” interval.
243    value = clock.normalize( type, value, options )
244
245    // Return the compiled object.
246    return {
247
248        // Divide to get hours from minutes.
249        hour: ~~( HOURS_IN_DAY + value / MINUTES_IN_HOUR ) % HOURS_IN_DAY,
250
251        // The remainder is the minutes.
252        mins: ( MINUTES_IN_HOUR + value % MINUTES_IN_HOUR ) % MINUTES_IN_HOUR,
253
254        // The time in total minutes.
255        time: ( MINUTES_IN_DAY + value ) % MINUTES_IN_DAY,
256
257        // Reference to the “relative” value to pick.
258        pick: value % MINUTES_IN_DAY
259    }
260} //TimePicker.prototype.create
261
262
263/**
264 * Create a range limit object using an array, date object,
265 * literal “true”, or integer relative to another time.
266 */
267TimePicker.prototype.createRange = function( from, to ) {
268
269    var clock = this,
270        createTime = function( time ) {
271            if ( time === true || $.isArray( time ) || _.isDate( time ) ) {
272                return clock.create( time )
273            }
274            return time
275        }
276
277    // Create objects if possible.
278    if ( !_.isInteger( from ) ) {
279        from = createTime( from )
280    }
281    if ( !_.isInteger( to ) ) {
282        to = createTime( to )
283    }
284
285    // Create relative times.
286    if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
287        from = [ to.hour, to.mins + ( from * clock.settings.interval ) ];
288    }
289    else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
290        to = [ from.hour, from.mins + ( to * clock.settings.interval ) ];
291    }
292
293    return {
294        from: createTime( from ),
295        to: createTime( to )
296    }
297} //TimePicker.prototype.createRange
298
299
300/**
301 * Check if a time unit falls within a time range object.
302 */
303TimePicker.prototype.withinRange = function( range, timeUnit ) {
304    range = this.createRange(range.from, range.to)
305    return timeUnit.pick >= range.from.pick && timeUnit.pick <= range.to.pick
306}
307
308
309/**
310 * Check if two time range objects overlap.
311 */
312TimePicker.prototype.overlapRanges = function( one, two ) {
313
314    var clock = this
315
316    // Convert the ranges into comparable times.
317    one = clock.createRange( one.from, one.to )
318    two = clock.createRange( two.from, two.to )
319
320    return clock.withinRange( one, two.from ) || clock.withinRange( one, two.to ) ||
321        clock.withinRange( two, one.from ) || clock.withinRange( two, one.to )
322}
323
324
325/**
326 * Get the time relative to now.
327 */
328TimePicker.prototype.now = function( type, value/*, options*/ ) {
329
330    var interval = this.item.interval,
331        date = new Date(),
332        nowMinutes = date.getHours() * MINUTES_IN_HOUR + date.getMinutes(),
333        isValueInteger = _.isInteger( value ),
334        isBelowInterval
335
336    // Make sure “now” falls within the interval range.
337    nowMinutes -= nowMinutes % interval
338
339    // Check if the difference is less than the interval itself.
340    isBelowInterval = value < 0 && interval * value + nowMinutes <= -interval
341
342    // Add an interval because the time has “passed”.
343    nowMinutes += type == 'min' && isBelowInterval ? 0 : interval
344
345    // If the value is a number, adjust by that many intervals.
346    if ( isValueInteger ) {
347        nowMinutes += interval * (
348            isBelowInterval && type != 'max' ?
349                value + 1 :
350                value
351            )
352    }
353
354    // Return the final calculation.
355    return nowMinutes
356} //TimePicker.prototype.now
357
358
359/**
360 * Normalize minutes to be “reachable” based on the min and interval.
361 */
362TimePicker.prototype.normalize = function( type, value/*, options*/ ) {
363
364    var interval = this.item.interval,
365        minTime = this.item.min && this.item.min.pick || 0
366
367    // If setting min time, don’t shift anything.
368    // Otherwise get the value and min difference and then
369    // normalize the difference with the interval.
370    value -= type == 'min' ? 0 : ( value - minTime ) % interval
371
372    // Return the adjusted value.
373    return value
374} //TimePicker.prototype.normalize
375
376
377/**
378 * Measure the range of minutes.
379 */
380TimePicker.prototype.measure = function( type, value, options ) {
381
382    var clock = this
383
384    // If it’s anything false-y, set it to the default.
385    if ( !value ) {
386        value = type == 'min' ? [ 0, 0 ] : [ HOURS_IN_DAY - 1, MINUTES_IN_HOUR - 1 ]
387    }
388
389    // If it’s a string, parse it.
390    if ( typeof value == 'string' ) {
391        value = clock.parse( type, value )
392    }
393
394    // If it’s a literal true, or an integer, make it relative to now.
395    else if ( value === true || _.isInteger( value ) ) {
396        value = clock.now( type, value, options )
397    }
398
399    // If it’s an object already, just normalize it.
400    else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
401        value = clock.normalize( type, value.pick, options )
402    }
403
404    return value
405} ///TimePicker.prototype.measure
406
407
408/**
409 * Validate an object as enabled.
410 */
411TimePicker.prototype.validate = function( type, timeObject, options ) {
412
413    var clock = this,
414        interval = options && options.interval ? options.interval : clock.item.interval
415
416    // Check if the object is disabled.
417    if ( clock.disabled( timeObject ) ) {
418
419        // Shift with the interval until we reach an enabled time.
420        timeObject = clock.shift( timeObject, interval )
421    }
422
423    // Scope the object into range.
424    timeObject = clock.scope( timeObject )
425
426    // Do a second check to see if we landed on a disabled min/max.
427    // In that case, shift using the opposite interval as before.
428    if ( clock.disabled( timeObject ) ) {
429        timeObject = clock.shift( timeObject, interval * -1 )
430    }
431
432    // Return the final object.
433    return timeObject
434} //TimePicker.prototype.validate
435
436
437/**
438 * Check if an object is disabled.
439 */
440TimePicker.prototype.disabled = function( timeToVerify ) {
441
442    var clock = this,
443
444        // Filter through the disabled times to check if this is one.
445        isDisabledMatch = clock.item.disable.filter( function( timeToDisable ) {
446
447            // If the time is a number, match the hours.
448            if ( _.isInteger( timeToDisable ) ) {
449                return timeToVerify.hour == timeToDisable
450            }
451
452            // If it’s an array, create the object and match the times.
453            if ( $.isArray( timeToDisable ) || _.isDate( timeToDisable ) ) {
454                return timeToVerify.pick == clock.create( timeToDisable ).pick
455            }
456
457            // If it’s an object, match a time within the “from” and “to” range.
458            if ( $.isPlainObject( timeToDisable ) ) {
459                return clock.withinRange( timeToDisable, timeToVerify )
460            }
461        })
462
463    // If this time matches a disabled time, confirm it’s not inverted.
464    isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( timeToDisable ) {
465        return $.isArray( timeToDisable ) && timeToDisable[2] == 'inverted' ||
466            $.isPlainObject( timeToDisable ) && timeToDisable.inverted
467    }).length
468
469    // If the clock is "enabled" flag is flipped, flip the condition.
470    return clock.item.enable === -1 ? !isDisabledMatch : isDisabledMatch ||
471        timeToVerify.pick < clock.item.min.pick ||
472        timeToVerify.pick > clock.item.max.pick
473}
473 //TimePicker.prototype.disabled
474
475
476/**
477 * Shift an object by an interval until we reach an enabled object.
478 */
479TimePicker.prototype.shift = function( timeObject, interval ) {
480
481    var clock = this,
482        minLimit = clock.item.min.pick,
483        maxLimit = clock.item.max.pick/*,
484        safety = 1000*/
485
486    interval = interval || clock.item.interval
487
488    // Keep looping as long as the time is disabled.
489    while ( /*safety &&*/ clock.disabled( timeObject ) ) {
490
491        /*safety -= 1
492        if ( !safety ) {
493            throw 'Fell into an infinite loop while shifting to ' + timeObject.hour + ':' + timeObject.mins + '.'
494        }*/
495
496        // Increase/decrease the time by the interval and keep looping.
497        timeObject = clock.create( timeObject.pick += interval )
498
499        // If we've looped beyond the limits, break out of the loop.
500        if ( timeObject.pick <= minLimit || timeObject.pick >= maxLimit ) {
501            break
502        }
503    }
504
505    // Return the final object.
506    return timeObject
507} //TimePicker.prototype.shift
508
509
510/**
511 * Scope an object to be within range of min and max.
512 */
513TimePicker.prototype.scope = function( timeObject ) {
514    var minLimit = this.item.min.pick,
515        maxLimit = this.item.max.pick
516    return this.create( timeObject.pick > maxLimit ? maxLimit : timeObject.pick < minLimit ? minLimit : timeObject )
517} //TimePicker.prototype.scope
518
519
520/**
521 * Parse a string into a usable type.
522 */
523TimePicker.prototype.parse = function( type, value, options ) {
524
525    var hour, minutes, isPM, item, parseValue,
526        clock = this,
527        parsingObject = {}
528
529    // If it’s already parsed, we’re good.
530    if ( !value || typeof value != 'string' ) {
531        return value
532    }
533
534    // We need a `.format` to parse the value with.
535    if ( !( options && options.format ) ) {
536        options = options || {}
537        options.format = clock.settings.format
538    }
539
540    // Convert the format into an array and then map through it.
541    clock.formats.toArray( options.format ).map( function( label ) {
542
543        var
544            substring,
545
546            // Grab the formatting label.
547            formattingLabel = clock.formats[ label ],
548
549            // The format length is from the formatting label function or the
550            // label length without the escaping exclamation (!) mark.
551            formatLength = formattingLabel ?
552                _.trigger( formattingLabel, clock, [ value, parsingObject ] ) :
553                label.replace( /^!/, '' ).length
554
555        // If there's a format label, split the value up to the format length.
556        // Then add it to the parsing object with appropriate label.
557        if ( formattingLabel ) {
558            substring = value.substr( 0, formatLength )
559            parsingObject[ label ] = substring.match(/^\d+$/) ? +substring : substring
560        }
561
562        // Update the time value as the substring from format length to end.
563        value = value.substr( formatLength )
564    })
565
566    // Grab the hour and minutes from the parsing object.
567    for ( item in parsingObject ) {
568        parseValue = parsingObject[item]
569        if ( _.isInteger(parseValue) ) {
570            if ( item.match(/^(h|hh)$/i) ) {
571                hour = parseValue
572                if ( item == 'h' || item == 'hh' ) {
573                    hour %= 12
574                }
575            }
576            else if ( item == 'i' ) {
577                minutes = parseValue
578            }
579        }
580        else if ( item.match(/^a$/i) && parseValue.match(/^p/i) && ('h' in parsingObject || 'hh' in parsingObject) ) {
581            isPM = true
582        }
583    }
584
585    // Calculate it in minutes and return.
586    return (isPM ? hour + 12 : hour) * MINUTES_IN_HOUR + minutes
587} //TimePicker.prototype.parse
588
589
590/**
591 * Various formats to display the object in.
592 */
593TimePicker.prototype.formats = {
594
595    h: function( string, timeObject ) {
596
597        // If there's string, then get the digits length.
598        // Otherwise return the selected hour in "standard" format.
599        return string ? _.digits( string ) : timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON
600    },
601    hh: function( string, timeObject ) {
602
603        // If there's a string, then the length is always 2.
604        // Otherwise return the selected hour in "standard" format with a leading zero.
605        return string ? 2 : _.lead( timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON )
606    },
607    H: function( string, timeObject ) {
608
609        // If there's string, then get the digits length.
610        // Otherwise return the selected hour in "military" format as a string.
611        return string ? _.digits( string ) : '' + ( timeObject.hour % 24 )
612    },
613    HH: function( string, timeObject ) {
614
615        // If there's string, then get the digits length.
616        // Otherwise return the selected hour in "military" format with a leading zero.
617        return string ? _.digits( string ) : _.lead( timeObject.hour % 24 )
618    },
619    i: function( string, timeObject ) {
620
621        // If there's a string, then the length is always 2.
622        // Otherwise return the selected minutes.
623        return string ? 2 : _.lead( timeObject.mins )
624    },
625    a: function( string, timeObject ) {
626
627        // If there's a string, then the length is always 4.
628        // Otherwise check if it's more than "noon" and return either am/
628pm.
629        return string ? 4 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'a.m.' : 'p.m.'
630    },
631    A: function( string, timeObject ) {
632
633        // If there's a string, then the length is always 2.
634        // Otherwise check if it's more than "noon" and return either am/pm.
635        return string ? 2 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'AM' : 'PM'
636    },
637
638    // Create an array by splitting the formatting string passed.
639    toArray: function( formatString ) { return formatString.split( /(h{1,2}|H{1,2}|i|a|A|!.)/g ) },
640
641    // Format an object into a string using the formatting options.
642    toString: function ( formatString, itemObject ) {
643        var clock = this
644        return clock.formats.toArray( formatString ).map( function( label ) {
645            return _.trigger( clock.formats[ label ], clock, [ 0, itemObject ] ) || label.replace( /^!/, '' )
646        }).join( '' )
647    }
648} //TimePicker.prototype.formats
649
650
651
652
653/**
654 * Check if two time units are the exact.
655 */
656TimePicker.prototype.isTimeExact = function( one, two ) {
657
658    var clock = this
659
660    // When we’re working with minutes, do a direct comparison.
661    if (
662        ( _.isInteger( one ) && _.isInteger( two ) ) ||
663        ( typeof one == 'boolean' && typeof two == 'boolean' )
664     ) {
665        return one === two
666    }
667
668    // When we’re working with time representations, compare the “pick” value.
669    if (
670        ( _.isDate( one ) || $.isArray( one ) ) &&
671        ( _.isDate( two ) || $.isArray( two ) )
672    ) {
673        return clock.create( one ).pick === clock.create( two ).pick
674    }
675
676    // When we’re working with range objects, compare the “from” and “to”.
677    if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
678        return clock.isTimeExact( one.from, two.from ) && clock.isTimeExact( one.to, two.to )
679    }
680
681    return false
682}
683
684
685/**
686 * Check if two time units overlap.
687 */
688TimePicker.prototype.isTimeOverlap = function( one, two ) {
689
690    var clock = this
691
692    // When we’re working with an integer, compare the hours.
693    if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) {
694        return one === clock.create( two ).hour
695    }
696    if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
697        return two === clock.create( one ).hour
698    }
699
700    // When we’re working with range objects, check if the ranges overlap.
701    if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
702        return clock.overlapRanges( one, two )
703    }
704
705    return false
706}
707
708
709/**
710 * Flip the “enabled” state.
711 */
712TimePicker.prototype.flipEnable = function(val) {
713    var itemObject = this.item
714    itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
715}
716
717
718/**
719 * Mark a collection of times as “disabled”.
720 */
721TimePicker.prototype.deactivate = function( type, timesToDisable ) {
722
723    var clock = this,
724        disabledItems = clock.item.disable.slice(0)
725
726
727    // If we’re flipping, that’s all we need to do.
728    if ( timesToDisable == 'flip' ) {
729        clock.flipEnable()
730    }
731
732    else if ( timesToDisable === false ) {
733        clock.flipEnable(1)
734        disabledItems = []
735    }
736
737    else if ( timesToDisable === true ) {
738        clock.flipEnable(-1)
739        disabledItems = []
740    }
741
742    // Otherwise go through the times to disable.
743    else {
744
745        timesToDisable.map(function( unitToDisable ) {
746
747            var matchFound
748
749            // When we have disabled items, check for matches.
750            // If something is matched, immediately break out.
751            for ( var index = 0; index < disabledItems.length; index += 1 ) {
752                if ( clock.isTimeExact( unitToDisable, disabledItems[index] ) ) {
753                    matchFound = true
754                    break
755                }
756            }
757
758            // If nothing was found, add the validated unit to the collection.
759            if ( !matchFound ) {
760                if (
761                    _.isInteger( unitToDisable ) ||
762                    _.isDate( unitToDisable ) ||
763                    $.isArray( unitToDisable ) ||
764                    ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
765                ) {
766                    disabledItems.push( unitToDisable )
767                }
768            }
769        })
770    }
771
772    // Return the updated collection.
773    return disabledItems
774} //TimePicker.prototype.deactivate
775
776
777/**
778 * Mark a collection of times as “enabled”.
779 */
780TimePicker.prototype.activate = function( type, timesToEnable ) {
781
782    var clock = this,
783        disabledItems = clock.item.disable,
784        disabledItemsCount = disabledItems.length
785
786    // If we’re flipping, that’s all we need to do.
787    if ( timesToEnable == 'flip' ) {
788        clock.flipEnable()
789    }
790
791    else if ( timesToEnable === true ) {
792        clock.flipEnable(1)
793        disabledItems = []
794    }
795
796    else if ( timesToEnable === false ) {
797        clock.flipEnable(-1)
798        disabledItems = []
799    }
800
801    // Otherwise go through the disabled times.
802    else {
803
804        timesToEnable.map(function( unitToEnable ) {
805
806            var matchFound,
807                disabledUnit,
808                index,
809                isRangeMatched
810
811            // Go through the disabled items and try to find a match.
812            for ( index = 0; index < disabledItemsCount; index += 1 ) {
813
814                disabledUnit = disabledItems[index]
815
816                // When an exact match is found, remove it from the collection.
817                if ( clock.isTimeExact( disabledUnit, unitToEnable ) ) {
818                    matchFound = disabledItems[index] = null
819                    isRangeMatched = true
820                    break
821                }
822
823                // When an overlapped match is found, add the “inverted” state to it.
824                else if ( clock.isTimeOverlap( disabledUnit, unitToEnable ) ) {
825                    if ( $.isPlainObject( unitToEnable ) ) {
826                        unitToEnable.inverted = true
827                        matchFound = unitToEnable
828                    }
829                    else if ( $.isArray( unitToEnable ) ) {
830                        matchFound = unitToEnable
831                        if ( !matchFound[2] ) matchFound.push( '
831inverted' )
832                    }
833                    else if ( _.isDate( unitToEnable ) ) {
834                        matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
835                    }
836                    break
837                }
838            }
839
840            // If a match was found, remove a previous duplicate entry.
841            if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
842                if ( clock.isTimeExact( disabledItems[index], unitToEnable ) ) {
843                    disabledItems[index] = null
844                    break
845                }
846            }
847
848            // In the event that we’re dealing with an overlap of range times,
849            // make sure there are no “inverted” times because of it.
850            if ( isRangeMatched ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
851                if ( clock.isTimeOverlap( disabledItems[index], unitToEnable ) ) {
852                    disabledItems[index] = null
853                    break
854                }
855            }
856
857            // If something is still matched, add it into the collection.
858            if ( matchFound ) {
859                disabledItems.push( matchFound )
860            }
861        })
862    }
863
864    // Return the updated collection.
865    return disabledItems.filter(function( val ) { return val != null })
866} //TimePicker.prototype.activate
867
868
869/**
870 * The division to use for the range intervals.
871 */
872TimePicker.prototype.i = function( type, value/*, options*/ ) {
873    return _.isInteger( value ) && value > 0 ? value : this.item.interval
874}
875
876
877/**
878 * Create a string for the nodes in the picker.
879 */
880TimePicker.prototype.nodes = function( isOpen ) {
881
882    var
883        clock = this,
884        settings = clock.settings,
885        selectedObject = clock.item.select,
886        highlightedObject = clock.item.highlight,
887        viewsetObject = clock.item.view,
888        disabledCollection = clock.item.disable
889
890    return _.node(
891        'ul',
892        _.group({
893            min: clock.item.min.pick,
894            max: clock.item.max.pick,
895            i: clock.item.interval,
896            node: 'li',
897            item: function( loopedTime ) {
898                loopedTime = clock.create( loopedTime )
899                var timeMinutes = loopedTime.pick,
900                    isSelected = selectedObject && selectedObject.pick == timeMinutes,
901                    isHighlighted = highlightedObject && highlightedObject.pick == timeMinutes,
902                    isDisabled = disabledCollection && clock.disabled( loopedTime ),
903                    formattedTime = _.trigger( clock.formats.toString, clock, [ settings.format, loopedTime ] )
904                return [
905                    _.trigger( clock.formats.toString, clock, [ _.trigger( settings.formatLabel, clock, [ loopedTime ] ) || settings.format, loopedTime ] ),
906                    (function( klasses ) {
907
908                        if ( isSelected ) {
909                            klasses.push( settings.klass.selected )
910                        }
911
912                        if ( isHighlighted ) {
913                            klasses.push( settings.klass.highlighted )
914                        }
915
916                        if ( viewsetObject && viewsetObject.pick == timeMinutes ) {
917                            klasses.push( settings.klass.viewset )
918                        }
919
920                        if ( isDisabled ) {
921                            klasses.push( settings.klass.disabled )
922                        }
923
924                        return klasses.join( ' ' )
925                    })( [ settings.klass.listItem ] ),
926                    'data-pick=' + loopedTime.pick + ' ' + _.ariaAttr({
927                        role: 'option',
928                        label: formattedTime,
929                        selected: isSelected && clock.$node.val() === formattedTime ? true : null,
930                        activedescendant: isHighlighted ? true : null,
931                        disabled: isDisabled ? true : null
932                    })
933                ]
934            }
935        }) +
936
937        // * For Firefox forms to submit, make sure to set the button’s `type` attribute as “button”.
938        _.node(
939            'li',
940            _.node(
941                'button',
942                settings.clear,
943                settings.klass.buttonClear,
944                'type=button data-clear=1' + ( isOpen ? '' : ' disabled' ) + ' ' +
945                _.ariaAttr({ controls: clock.$node[0].id })
946            ),
947            '', _.ariaAttr({ role: 'presentation' })
948        ),
949        settings.klass.list,
950        _.ariaAttr({ role: 'listbox', controls: clock.$node[0].id })
951    )
952} //TimePicker.prototype.nodes
953
954
955
956
957
958
959
960/**
961 * Extend the picker to add the component with the defaults.
962 */
963TimePicker.defaults = (function( prefix ) {
964
965    return {
966
967        // Clear
968        clear: 'Clear',
969
970        // The format to show on the `input` element
971        format: 'h:i A',
972
973        // The interval between each time
974        interval: 30,
975
976        // Picker close behavior
977        closeOnSelect: true,
978        closeOnClear: true,
979
980        // Update input value on select/clear
981        updateInput: true,
982
983        // Classes
984        klass: {
985
986            picker: prefix + ' ' + prefix + '--time',
987            holder: prefix + '__holder',
988
989            list: prefix + '__list',
990            listItem: prefix + '__list-item',
991
992            disabled: prefix + '__list-item--disabled',
993            selected: prefix + '__list-item--selected',
994            highlighted: prefix + '__list-item--highlighted',
995            viewset: prefix + '__list-item--viewset',
996            now: prefix + '__list-item--now',
997
998            buttonClear: prefix + '__button--clear'
999        }
1000    }
1001})( Picker.klasses().picker )
1002
1003
1004
1005
1006
1007/**
1008 * Extend the picker to add the time picker.
1009 */
1010Picker.extend( 'pickatime', TimePicker )
1011
1012
1013}));
1014
1015
1016

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.