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.