1/*! jQuery Timepicker Addon - v1.6.3 - 2016-04-20 2 * http://trentrichardson.com/examples/timepicker 3 * Modified version of jQuery Timepicker 4 * Copyright (c) 2016 Trent Richardson; Licensed MIT */ 5( function( factory ) { 6 'use strict'; 7 if ( typeof window.define === 'function' && window.define.amd ) { 8 window.define( [ 'jquery', 'jquery-ui' ], factory ); 9 } else { 10 factory( window.jQuery ); 11 } 12}( function( $ ) { 13 'use strict'; 14 15 /* 16 * jQuery extend now ignores nulls! 17 */ 18 var extendRemove = function( target, props ) { 19 var name; 20 $.extend( target, props ); 21 for ( name in props ) { 22 if ( props[ name ] === null || props[ name ] === undefined ) { 23 target[ name ] = props[ name ]; 24 } 25 } 26 return target; 27 }; 28 29 /* 30 * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype, 31 * it will return false for all objects 32 */ 33 var isEmptyObject = function( obj ) { 34 var prop; 35 for ( prop in obj ) { 36 if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { 37 return false; 38 } 39 } 40 return true; 41 }; 42 43 /* 44 * Determine by the time format which units are supported 45 * Returns an object of booleans for each unit 46 */ 47 var detectSupport = function( timeFormat ) { 48 var tf = timeFormat.replace( /'.*?'/g, '' ).toLowerCase(), // removes literals 49 isIn = function( f, t ) { 50 // does the format contain the token? 51 return f.indexOf( t ) !== -1 ? true : false; 52 }; 53 return { 54 hour: isIn( tf, 'h' ), 55 minute: isIn( tf, 'm' ), 56 second: isIn( tf, 's' ), 57 millisec: isIn( tf, 'l' ), 58 microsec: isIn( tf, 'c' ), 59 timezone: isIn( tf, 'z' ), 60 ampm: isIn( tf, 't' ) && isIn( timeFormat, 'h' ), 61 iso8601: isIn( timeFormat, 'Z' ) 62 }; 63 }; 64 65 /* 66 * Converts 24 hour format into 12 hour 67 * Returns 12 hour without leading 0 68 */ 69 var convert24to12 = function( hour ) { 70 hour %= 12; 71 72 if ( hour === 0 ) { 73 hour = 12; 74 } 75 76 return String( hour ); 77 }; 78 79 var computeEffectiveSetting = function( settings, property ) { 80 return settings && settings[ property ] ? settings[ property ] : $.tm_timepicker._defaults[ property ]; 81 }; 82 83 /* 84 * Splits datetime string into date and time substrings. 85 * Throws exception when date can't be parsed
86 * Returns {dateString: dateString, timeString: timeString} 87 */ 88 var splitDateTime = function( dateTimeString, timeSettings ) { 89 // The idea is to get the number separator occurrences in datetime and the time format requested (since time has 90 // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split. 91 var separator = computeEffectiveSetting( timeSettings, 'separator' ), 92 format = computeEffectiveSetting( timeSettings, 'timeFormat' ), 93 timeParts = format.split( separator ), // how many occurrences of separator may be in our format? 94 timePartsLen = timeParts.length, 95 allParts = dateTimeString.split( separator ), 96 allPartsLen = allParts.length; 97 98 if ( allPartsLen > 1 ) { 99 return { 100 dateString: allParts.splice( 0, allPartsLen - timePartsLen ).join( separator ), 101 timeString: allParts.splice( 0, timePartsLen ).join( separator ) 102 }; 103 } 104 105 return { 106 dateString: dateTimeString, 107 timeString: '' 108 }; 109 }; 110 111 /* 112 * Internal function to parse datetime interval 113 * Returns: {date: Date, timeObj: Object}, where 114 * date - parsed date without time (type Date) 115 * timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional 116 */ 117 var parseDateTimeInternal = function( dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings ) { 118 var date, parts, parsedTime; 119 120 parts = splitDateTime( dateTimeString, timeSettings ); 121 date = $.tm_datepicker._base_parseDate( dateFormat, parts.dateString, dateSettings ); 122 123 if ( parts.timeString === '' ) { 124 return { 125 date: date 126 }; 127 } 128 129 parsedTime = $.tm_datepicker.parseTime( timeFormat, parts.timeString, timeSettings ); 130 131 if ( ! parsedTime ) { 132 throw 'Wrong time format'; 133 } 134 135 return { 136 date: date, 137 timeObj: parsedTime 138 }; 139 }; 140 141 /* 142 * Internal function to set timezone_select to the local timezone 143 */ 144 var selectLocalTimezone = function( tp_inst, date ) { 145 var now; 146 if ( tp_inst && tp_inst.timezone_select ) { 147 now = date || new Date(); 148 tp_inst.timezone_select.val( -now.getTimezoneOffset() ); 149 } 150 }; 151 152 /* 153 * Timepicker manager. 154 * Use the singleton instance of this class, $.tm_timepicker, to interact with the time picker. 155 * Settings for (groups of) time pickers are maintained in an instance object, 156 * allowing multiple different settings on the same page. 157 */ 158 var Timepicker = function() { 159 this.regional = []; // Available regional settings, indexed by language code 160 this.regional[ '' ] = { 161 // Default regional settings 162 currentText: 'Now', 163 closeText: 'Done', 164 amNames: [ 'AM', 'A' ], 165 pmNames: [ 'PM', 'P' ], 166 timeFormat: 'HH:mm', 167 timeSuffix: '', 168 timeOnlyTitle: 'Choose Time', 169 timeText: 'Time', 170 hourText: 'Hour', 171 minuteText: 'Minute', 172 secondText: 'Second', 173 millisecText: 'Millisecond', 174 microsecText: 'Microsecond', 175 timezoneText: 'Time Zone', 176 isRTL: false 177 }; 178 this._defaults = { 179 // Global defaults for all the datetime picker instances 180 showButtonPanel: true, 181 timeOnly: false, 182 timeOnlyShowDate: false, 183 showHour: null, 184 showMinute: null, 185 showSecond: null, 186 showMillisec: null, 187 showMicrosec: null, 188 showTimezone: null, 189 showTime: true, 190 stepHour: 1, 191 stepMinute: 1, 192 stepSecond: 1, 193 stepMillisec: 1, 194 stepMicrosec: 1, 195 hour: 0, 196 minute: 0, 197 second: 0, 198 millisec: 0, 199 microsec: 0, 200 timezone: null, 201 hourMin: 0, 202 minuteMin: 0, 203 secondMin: 0, 204 millisecMin: 0, 205 microsecMin: 0, 206 hourMax: 23, 207 minuteMax: 59, 208 secondMax: 59, 209 millisecMax: 999, 210 microsecMax: 999, 211 minDateTime: null, 212 maxDateTime: null, 213 maxTime: null, 214 minTime: null, 215 onSelect: null, 216 hourGrid: 0, 217 minuteGrid: 0, 218 secondGrid: 0, 219 millisecGrid: 0, 220 microsecGrid: 0, 221 alwaysSetTime: true, 222 separator: ' ', 223 altFieldTimeOnly: true, 224 altTimeFormat: null, 225 altSeparator: null, 226 altTimeSuffix: null, 227 altRedirectFocus: true, 228 pickerTimeFormat: null, 229 pickerTimeSuffix: null, 230 showTimepicker: true, 231 timezoneList: null, 232 addSliderAccess: false, 233 sliderAccessArgs: null, 234 controlType: 'slider', 235 oneLine: false, 236 defaultValue: null, 237 parse: 'strict', 238 afterInject: null 239 }; 240 $.extend( this._defaults, this.regional[ '' ] ); 241 }; 242 243 /* 244 * Lets not redefine tm_timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded" 245 */ 246 $.ui.tm_timepicker = $.ui.tm_timepicker || {}; 247 if ( $.ui.tm_timepicker.version ) { 248 return; 249 } 250 251 /* 252 * Extend jQueryUI, get it started with our version number 253 */ 254 $.extend( $.ui, { 255 tm_timepicker: { 256 version: '1.6.3' 257 } 258 } ); 259 260 $.extend( Timepicker.prototype, { 261 $input: null, 262 $altInput: null, 263 $timeObj: null, 264 inst: null, 265 hour_slider: null, 266 minute_slider: null, 267 second_slider: null, 268 millisec_slider: null, 269 microsec_slider: null, 270 timezone_select: null, 271 maxTime: null, 272 minTime: null, 273 hour: 0, 274 minute: 0, 275 second: 0, 276 millisec: 0, 277 microsec: 0, 278 timezone: null,
279 hourMinOriginal: null, 280 minuteMinOriginal: null, 281 secondMinOriginal: null, 282 millisecMinOriginal: null, 283 microsecMinOriginal: null, 284 hourMaxOriginal: null, 285 minuteMaxOriginal: null, 286 secondMaxOriginal: null, 287 millisecMaxOriginal: null, 288 microsecMaxOriginal: null, 289 ampm: '', 290 formattedDate: '', 291 formattedTime: '', 292 formattedDateTime: '', 293 timezoneList: null, 294 units: [ 'hour', 'minute', 'second', 'millisec', 'microsec' ], 295 support: {}, 296 control: null, 297 298 /* 299 * Override the default settings for all instances of the time picker. 300 * @param {Object} settings object - the new settings to use as defaults (anonymous object) 301 * @return {Object} the manager object 302 */ 303 setDefaults: function( settings ) { 304 extendRemove( this._defaults, settings || {} ); 305 return this; 306 }, 307 308 /* 309 * Create a new Timepicker instance 310 */ 311 _newInst: function( $input, opts ) { 312 var tp_inst = new Timepicker(), 313 inlineSettings = {}, 314 fns = {}, 315 overrides, 316 i; 317 var attrName; 318 var attrValue; 319 var timezoneList; 320 var tzl; 321 var tzi = 0; 322 var tzv = null; 323 324 for ( attrName in this._defaults ) { 325 if ( Object.prototype.hasOwnProperty.call( this._defaults, attrName ) ) { 326 attrValue = $input.attr( 'data-' + attrName ); 327 if ( attrValue ) { 328 inlineSettings[ attrName ] = attrValue; 329 } 330 } 331 } 332 333 overrides = { 334 beforeShow: function( input, dp_inst ) { 335 if ( typeof tp_inst._defaults.evnts.beforeShow === 'function' ) { 336 return tp_inst._defaults.evnts.beforeShow.call( $input[ 0 ], input, dp_inst, tp_inst ); 337 } 338 }, 339 onChangeMonthYear: function( year, month, dp_inst ) { 340 // Update the time as well : this prevents the time from disappearing from the $input field. 341 // tp_inst._updateDateTime(dp_inst); 342 if ( typeof tp_inst._defaults.evnts.onChangeMonthYear === 'function' ) { 343 tp_inst._defaults.evnts.onChangeMonthYear.call( $input[ 0 ], year, month, dp_inst, tp_inst ); 344 } 345 }, 346 onClose: function( dateText, dp_inst ) { 347 if ( tp_inst.timeDefined === true && $input.val() !== '' ) { 348 tp_inst._updateDateTime( dp_inst ); 349 } 350 if ( typeof tp_inst._defaults.evnts.onClose === 'function' ) { 351 tp_inst._defaults.evnts.onClose.call( $input[ 0 ], dateText, dp_inst, tp_inst ); 352 } 353 } 354 }; 355 for ( i in overrides ) { 356 if ( Object.prototype.hasOwnProperty.call( overrides, i ) ) { 357 fns[ i ] = opts[ i ] || this._defaults[ i ] || null; 358 } 359 } 360 361 tp_inst._defaults = $.extend( {}, this._defaults, inlineSettings, opts, overrides, { 362 evnts: fns, 363 tm_timepicker: tp_inst // add tm_timepicker as a property of tm_datepicker: $.tm_datepicker._get(dp_inst, 'tm_timepicker'); 364 } ); 365 tp_inst.amNames = $.map( tp_inst._defaults.amNames, function( val ) { 366 return val.toUpperCase(); 367 } ); 368 tp_inst.pmNames = $.map( tp_inst._defaults.pmNames, function( val ) { 369 return val.toUpperCase(); 370 } ); 371 372 // detect which units are supported 373 tp_inst.support = detectSupport( tp_inst._defaults.timeFormat + ( tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '' ) + ( tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : '' ) ); 374 375 // controlType is string - key to our this._controls 376 if ( typeof tp_inst._defaults.controlType === 'string' ) { 377 if ( tp_inst._defaults.controlType === 'slider' && typeof $.ui.slider === 'undefined' ) { 378 tp_inst._defaults.controlType = 'select'; 379 } 380 tp_inst.control = tp_inst._controls[ tp_inst._defaults.controlType ]; 381 } else { 382 // controlType is an object and must implement create, options, value methods 383 tp_inst.control = tp_inst._defaults.controlType; 384 } 385 386 // prep the timezone options 387 timezoneList = [ -720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60, 0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360, 390, 420, 480, 525, 540, 570, 600, 630, 660, 690, 720, 765, 780, 840 ]; 388 if ( tp_inst._defaults.timezoneList !== null ) { 389 timezoneList = tp_inst._defaults.timezoneList; 390 } 391 tzl = timezoneList.length; 392 393 if ( tzl > 0 && typeof timezoneList[ 0 ] !== 'object' ) { 394 for ( ; tzi < tzl; tzi += 1 ) { 395 tzv = timezoneList[ tzi ]; 396 timezoneList[ tzi ] = { 397 value: tzv, 398 label: $.tm_timepicker.timezoneOffsetString( tzv, tp_inst.support.iso8601 ) 399 }; 400 } 401 } 402 tp_inst._defaults.timezoneList = timezoneList; 403 404 // set the default units 405 tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.tm_timepicker.timezoneOffsetNumber( tp_inst._defaults.timezone ) : new Date().getTimezoneOffset() * -1; 406 tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin : tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour; 407 tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin : tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute; 408 tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin : tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second; 409 tp_inst.millisec = 410 tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin : tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec; 411 tp_inst.microsec =
412 tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin : tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec; 413 tp_inst.ampm = ''; 414 tp_inst.$input = $input; 415 416 if ( tp_inst._defaults.altField ) { 417 tp_inst.$altInput = $( tp_inst._defaults.altField ); 418 if ( tp_inst._defaults.altRedirectFocus === true ) { 419 tp_inst.$altInput 420 .css( { 421 cursor: 'pointer' 422 } ) 423 .on( 'focus', function() { 424 $input.trigger( 'focus' ); 425 } ); 426 } 427 } 428 429 if ( tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0 ) { 430 tp_inst._defaults.minDate = new Date(); 431 } 432 if ( tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0 ) { 433 tp_inst._defaults.maxDate = new Date(); 434 } 435 436 // tm_datepicker needs minDate/maxDate, tm_timepicker needs minDateTime/maxDateTime.. 437 if ( tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date ) { 438 tp_inst._defaults.minDateTime = new Date( tp_inst._defaults.minDate.getTime() ); 439 } 440 if ( tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date ) { 441 tp_inst._defaults.minDate = new Date( tp_inst._defaults.minDateTime.getTime() ); 442 } 443 if ( tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date ) { 444 tp_inst._defaults.maxDateTime = new Date( tp_inst._defaults.maxDate.getTime() ); 445 } 446 if ( tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date ) { 447 tp_inst._defaults.maxDate = new Date( tp_inst._defaults.maxDateTime.getTime() ); 448 } 449 tp_inst.$input.on( 'focus', function() { 450 tp_inst._onFocus(); 451 } ); 452 453 tp_inst.$input.next( '.ui-tm-timepicker-trigger' ).on( 'click', function() { 454 tp_inst._onFocus(); 455 /*if ( $.tm_datepicker._datepickerShowing && $.tm_datepicker._lastInput === input[ 0 ] ) { 456 $.tm_datepicker._hideDatepicker(); 457 } else if ( $.tm_datepicker._datepickerShowing && $.tm_datepicker._lastInput !== input[ 0 ] ) { 458 $.tm_datepicker._hideDatepicker(); 459 $.tm_datepicker._showDatepicker( input[ 0 ] ); 460 } else { 461 $.tm_datepicker._showDatepicker( input[ 0 ] ); 462 }*/ 463 return false; 464 } ); 465 466 return tp_inst; 467 }, 468 469 /* 470 * add our sliders to the calendar 471 */ 472 _addTimePicker: function( dp_inst ) { 473 var currDT = $.epoAPI.util.trim( this.$altInput && this._defaults.altFieldTimeOnly ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val() ); 474 475 this.timeDefined = this._parseTime( currDT ); 476 this._limitMinMaxDateTime( dp_inst, false ); 477 this._injectTimePicker(); 478 this._afterInject(); 479 }, 480 481 /* 482 * parse the time string from input value or _setTime 483 */ 484 _parseTime: function( timeString, withDate ) { 485 var dp_dateFormat; 486 var parseRes; 487 var timeObj; 488 489 if ( ! this.inst ) { 490 this.inst = $.tm_datepicker._getInst( this.$input[ 0 ] ); 491 } 492 493 if ( withDate || ! this._defaults.timeOnly ) { 494 dp_dateFormat = $.tm_datepicker._get( this.inst, 'dateFormat' ); 495 try { 496 parseRes = parseDateTimeInternal( dp_dateFormat, this._defaults.timeFormat, timeString, $.tm_datepicker._getFormatConfig( this.inst ), this._defaults ); 497 if ( ! parseRes.timeObj ) { 498 return false; 499 } 500 $.extend( this, parseRes.timeObj ); 501 } catch ( err ) { 502 $.tm_timepicker.log( 'Error parsing the date/time string: ' + err + '\ndate/time string = ' + timeString + '\ntimeFormat = ' + this._defaults.timeFormat + '\ndateFormat = ' + dp_dateFormat ); 503 return false; 504 } 505 return true; 506 } 507 timeObj = $.tm_datepicker.parseTime( this._defaults.timeFormat, timeString, this._defaults ); 508 if ( ! timeObj ) { 509 return false; 510 } 511 $.extend( this, timeObj ); 512 return true; 513 }, 514 515 /* 516 * Handle callback option after injecting tm_timepicker 517 */ 518 _afterInject: function() { 519 var o = this.inst.settings; 520 if ( typeof o.afterInject === 'function' ) { 521 o.afterInject.call( this ); 522 } 523 }, 524 525 _ui_tpicker_onclick: function( event ) { 526 var $t = $( event.target ), 527 h = $t.html(), 528 n = parseInt( h.replace( /[^0-9]/g ), 10 ), 529 ap = h.replace( /[^apm]/gi ), 530 f = $t.data( 'for' ); // loses scope, so we use data-for 531 532 if ( f === 'hour' ) { 533 if ( ap.indexOf( 'p' ) !== -1 && n < 12 ) { 534 n += 12; 535 } else if ( ap.indexOf( 'a' ) !== -1 && n === 12 ) { 536 n = 0; 537 } 538 } 539 540 event.data.tp_inst.control.value( event.data.tp_inst, event.data.tp_inst[ f + '_slider' ], event.data.litem, n ); 541 542 event.data.tp_inst._onTimeChange(); 543 event.data.tp_inst._onSelectHandler(); 544 }, 545 /* 546 * generate and inject html for tm_timepicker into ui tm_datepicker 547 */ 548 _injectTimePicker: function() { 549 var $dp = this.inst.dpDiv, 550 o = this.inst.settings, 551 tp_inst = this, 552 litem = '', 553 uitem = '', 554 show = null, 555 max = {}, 556 gridSize = {}, 557 size = null, 558 i = 0, 559 l = 0; 560 var noDisplay; 561 var html; 562 var h; 563 var tmph; 564 var m; 565 var showTz; 566 var $tp; 567 var local_timezone; 568 var $buttonPanel; 569 var timeDefined; 570 var sliderAccessArgs; 571 var rtl; 572 573 // Prevent displaying twice 574 if ( $dp.find( 'div.ui-tm-timepicker-div' ).length === 0 && o.showTimepicker ) { 575 noDisplay = ' ui_tpicker_unit_hide'; 576 html = 577 '<div class="ui-tm-timepicker-div' + 578 ( o.isRTL ? ' ui-tm-timepicker-rtl' : '' ) + 579 ( o.oneLine && o.controlType === 'select' ? ' ui-tm-timepicker-oneLine' : '' ) + 580 '"><dl>' + 581 '<dt class="ui_tpicker_time_label' + 582 ( o.showTime ? '' : noDisplay ) + 583 '">' + 584 o.timeText + 585 '</dt>' + 586 '<dd class="ui_tpicker_time ' + 587 ( o.showTime ? '' : noDisplay ) + 588 '"><input class="ui_tpicker_time_input" ' + 589 ( o.timeInput ? '' : 'disabled' ) + 590 '></dd>'; 591 592 // Create the markup 593 for ( i = 0, l = this.units.length; i < l; i += 1 ) { 594 litem = this.units[ i ]; 595 uitem = litem.substring( 0, 1 ).toUpperCase() + litem.substring( 1 ); 596 show = o[ 'show' + uitem ] !== null ? o[ 'show' + uitem ] : this.support[ litem ]; 597 598 // Added by Peter Medeiros: 599 // - Figure out what the hour/minute/second max should be based on the step values. 600 // - Example: if stepMinute is 15, then minMax is 45. 601 max[ litem ] = parseInt( o[ litem + 'Max' ] - ( ( o[ litem + 'Max' ] - o[ litem + 'Min' ] ) % o[ 'step' + uitem ] ), 10 ); 602 gridSize[ litem ] = 0; 603 604 html += 605 '<dt class="ui_tpicker_' + 606 litem + 607 '_label' + 608 ( show ? '' : noDisplay ) + 609 '">' + 610 o[ litem + 'Text' ] + 611 '</dt>' + 612 '<dd class="ui_tpicker_' + 613 litem + 614 ( show ? '' : noDisplay ) + 615 '"><div class="ui_tpicker_' + 616 litem + 617 '_slider' + 618 ( show ? '' : noDisplay ) + 619 '"></div>'; 620 621 if ( show && o[ litem + 'Grid' ] > 0 ) { 622 html += '<div><table class="ui-tpicker-grid-label"><tr>'; 623 624 if ( litem === 'hour' ) { 625 for ( h = o[ litem + 'Min' ]; h <= max[ litem ]; h += parseInt( o[ litem + 'Grid' ], 10 ) ) { 626 gridSize[ litem ] += 1; 627 tmph = $.tm_datepicker.formatTime( this.support.ampm ? 'hht' : 'HH', { hour: h }, o ); 628 html += '<td data-for="' + litem + '">' + tmph + '</td>'; 629 } 630 } else { 631 for ( m = o[ litem + 'Min' ]; m <= max[ litem ]; m += parseInt( o[ litem + 'Grid' ], 10 ) ) { 632 gridSize[ litem ] += 1; 633 html += '<td data-for="' + litem + '">' + ( m < 10 ? '0' : '' ) + m + '</td>'; 634 } 635 } 636 637 html += '</tr></table></div>'; 638 } 639 html += '</dd>'; 640 } 641 642 // Timezone 643 showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone; 644 html += '<dt class="ui_tpicker_timezone_label' + ( showTz ? '' : noDisplay ) + '">' + o.timezoneText + '</dt>'; 645 html += '<dd class="ui_tpicker_timezone' + ( showTz ? '' : noDisplay ) + '"></dd>'; 646 647 // Create the elements from string 648 html += '</dl></div>'; 649 $tp = $( html ); 650 651 // if we only want time picker... 652 if ( o.timeOnly === true ) { 653 $tp.prepend( '<div class="tm-ui-widget-header">' + '<div class="tm-ui-tp-title">' + o.timeOnlyTitle + '</div>' + '</div>' ); 654 $dp.find( '.tm-ui-dp-inner-container' ).hide(); 655 } 656 657 // add sliders, adjust grids, add events 658 for ( i = 0, l = tp_inst.units.length; i < l; i += 1 ) { 659 litem = tp_inst.units[ i ]; 660 uitem = litem.substring( 0, 1 ).toUpperCase() + litem.substring( 1 ); 661 show = o[ 'show' + uitem ] !== null ? o[ 'show' + uitem ] : this.support[ litem ]; 662 663 // add the slider 664 tp_inst[ litem + '_slider' ] = tp_inst.control.create( tp_inst, $tp.find( '.ui_tpicker_' + litem + '_slider' ), litem, tp_inst[ litem ], o[ litem + 'Min' ], max[ litem ], o[ 'step' + uitem ] ); 665 666 // adjust the grid and add click event 667 if ( show && o[ litem + 'Grid' ] > 0 ) { 668 size = ( 100 * gridSize[ litem ] * o[ litem + 'Grid' ] ) / ( max[ litem ] - o[ litem + 'Min' ] ); 669 $tp.find( '.ui_tpicker_' + litem + ' table' ) 670 .css( { 671 width: size + '%', 672 marginLeft: o.isRTL ? '0' : ( size / ( -2 * gridSize[ litem ] ) ) + '%', 673 marginRight: o.isRTL ? ( size / ( -2 * gridSize[ litem ] ) ) + '%' : '0', 674 borderCollapse: 'collapse' 675 } ) 676 .find( 'td' ) 677 .on( 'click', { that: this, tp_inst: tp_inst, litem: litem }, this._ui_tpicker_onclick ) 678 .css( { 679 cursor: 'pointer', 680 width: ( 100 / gridSize[ litem ] ) + '%', 681 textAlign: 'center', 682 overflow: 'hidden' 683 } ); 684 } // end if grid > 0 685 } // end for loop 686 687 // Add timezone options 688 this.timezone_select = $tp.find( '.ui_tpicker_timezone' ).append( '<select></select>' ).find( 'select' ); 689 $.fn.append.apply( 690 this.timezone_select, 691 $.map( o.timezoneList, function( val ) { 692 return $( '<option />' ) 693 .val( typeof val === 'object' ? val.value : val ) 694 .text( typeof val === 'object' ? val.label : val ); 695 } ) 696 ); 697 if ( typeof this.timezone !== 'undefined' && this.timezone !== null && this.timezone !== '' ) { 698 local_timezone = new Date( this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12 ).getTimezoneOffset() * -1; 699 if ( local_timezone === this.timezone ) { 700 selectLocalTimezone( tp_inst ); 701 } else { 702 this.timezone_select.val( this.timezone ); 703 } 704 } else if ( typeof this.hour !== 'undefined' && this.hour !== null && this.hour !== '' ) { 705 this.timezone_select.val( o.timezone ); 706 } else { 707 selectLocalTimezone( tp_inst ); 708 } 709 this.timezone_select.on( 'change', function() { 710 tp_inst._onTimeChange(); 711 tp_inst._onSelectHandler(); 712 tp_inst._afterInject(); 713 } ); 714 // End timezone options 715 716 // inject tm_timepicker into tm_datepicker 717 $buttonPanel = $dp.find( '.tm-ui-dp-buttonpane' ); 718 if ( $buttonPanel.length ) { 719 $buttonPanel.before( $tp ); 720 } else { 721 $dp.append( $tp ); 722 } 723 724 this.$timeObj = $tp.find( '.ui_tpicker_time_input' ); 725 this.$timeObj.on( 'change', function() { 726 var timeFormat = tp_inst.inst.settings.timeFormat; 727 var parsedTime = $.tm_datepicker.parseTime( timeFormat, this.value ); 728 var update = new Date(); 729 if ( parsedTime ) { 730 update.setHours( parsedTime.hour ); 731 update.setMinutes( parsedTime.minute ); 732 update.setSeconds( parsedTime.second ); 733 $.datepicker._setTime( tp_inst.inst, update ); 734 } else { 735 this.value = tp_inst.formattedTime; 736 this.trigger( 'blur' ); 737 } 738 } ); 739 740 if ( this.inst !== null ) { 741 timeDefined = this.timeDefined; 742 this._onTimeChange(); 743 this.timeDefined = timeDefined; 744 } 745 746 // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/ 747 if ( this._defaults.addSliderAccess ) { 748 sliderAccessArgs = this._defaults.sliderAccessArgs; 749 rtl = this._defaults.isRTL; 750 sliderAccessArgs.isRTL = rtl; 751 752 setTimeout( function() { 753 // fix for inline mode 754 var sliderAccessWidth; 755 if ( $tp.find( '.ui-slider-access' ).length === 0 ) { 756 $tp.find( '.ui-slider:visible' ).sliderAccess( sliderAccessArgs ); 757 758 // fix any grids since sliders are shorter 759 sliderAccessWidth = $tp.find( '.ui-slider-access:eq(0)' ).outerWidth( true ); 760 if ( sliderAccessWidth ) { 761 $tp.find( 'table:visible' ).each( function() { 762 var $g = $( this ), 763 oldWidth = $g.outerWidth(), 764 oldMarginLeft = $g 765 .css( rtl ? 'marginRight' : 'marginLeft' ) 766 .toString() 767 .replace( '%', '' ), 768 newWidth = oldWidth - sliderAccessWidth, 769 newMarginLeft = ( ( oldMarginLeft * newWidth ) / oldWidth ) + '%', 770 css = { width: newWidth, marginRight: 0, marginLeft: 0 }; 771 css[ rtl ? 'marginRight' : 'marginLeft' ] = newMarginLeft; 772 $g.css( css ); 773 } ); 774 } 775 } 776 }, 10 ); 777 } 778 // end slideAccess integration 779 780 tp_inst._limitMinMaxDateTime( this.inst, true ); 781 } 782 }, 783 784 /* 785 * This function tries to limit the ability to go outside the 786 * min/max date range 787 */ 788 _limitMinMaxDateTime: function( dp_inst, adjustSliders ) { 789 var o = this._defaults, 790 dp_date = new Date( dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay ); 791 var minDateTime; 792 var minDateTimeDate; 793 var maxDateTime; 794 var maxDateTimeDate; 795 var tempMinTime; 796 var tempMaxTime; 797 var hourMax; 798 var minMax; 799 var secMax; 800 var millisecMax;
vendor: 4,262 bytes, lines 801-887
801 var microsecMax; 802 803 if ( ! this._defaults.showTimepicker ) { 804 return; 805 } // No time so nothing to check here 806 807 if ( $.tm_datepicker._get( dp_inst, 'minDateTime' ) !== null && $.tm_datepicker._get( dp_inst, 'minDateTime' ) !== undefined && dp_date ) { 808 minDateTime = $.tm_datepicker._get( dp_inst, 'minDateTime' ); 809 minDateTimeDate = new Date( minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0 ); 810 811 if ( this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null ) { 812 this.hourMinOriginal = o.hourMin; 813 this.minuteMinOriginal = o.minuteMin; 814 this.secondMinOriginal = o.secondMin; 815 this.millisecMinOriginal = o.millisecMin; 816 this.microsecMinOriginal = o.microsecMin; 817 } 818 819 if ( dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime() ) { 820 this._defaults.hourMin = minDateTime.getHours(); 821 if ( this.hour <= this._defaults.hourMin ) { 822 this.hour = this._defaults.hourMin; 823 this._defaults.minuteMin = minDateTime.getMinutes(); 824 if ( this.minute <= this._defaults.minuteMin ) { 825 this.minute = this._defaults.minuteMin; 826 this._defaults.secondMin = minDateTime.getSeconds(); 827 if ( this.second <= this._defaults.secondMin ) { 828 this.second = this._defaults.secondMin; 829 this._defaults.millisecMin = minDateTime.getMilliseconds(); 830 if ( this.millisec <= this._defaults.millisecMin ) { 831 this.millisec = this._defaults.millisecMin; 832 this._defaults.microsecMin = minDateTime.getMicroseconds(); 833 } else { 834 if ( this.microsec < this._defaults.microsecMin ) { 835 this.microsec = this._defaults.microsecMin; 836 } 837 this._defaults.microsecMin = this.microsecMinOriginal; 838 } 839 } else { 840 this._defaults.millisecMin = this.millisecMinOriginal; 841 this._defaults.microsecMin = this.microsecMinOriginal; 842 } 843 } else { 844 this._defaults.secondMin = this.secondMinOriginal; 845 this._defaults.millisecMin = this.millisecMinOriginal; 846 this._defaults.microsecMin = this.microsecMinOriginal; 847 } 848 } else { 849 this._defaults.minuteMin = this.minuteMinOriginal; 850 this._defaults.secondMin = this.secondMinOriginal; 851 this._defaults.millisecMin = this.millisecMinOriginal; 852 this._defaults.microsecMin = this.microsecMinOriginal; 853 } 854 } else { 855 this._defaults.hourMin = this.hourMinOriginal; 856 this._defaults.minuteMin = this.minuteMinOriginal; 857 this._defaults.secondMin = this.secondMinOriginal; 858 this._defaults.millisecMin = this.millisecMinOriginal; 859 this._defaults.microsecMin = this.microsecMinOriginal; 860 } 861 } 862 863 if ( $.tm_datepicker._get( dp_inst, 'maxDateTime' ) !== null && $.tm_datepicker._get( dp_inst, 'maxDateTime' ) !== undefined && dp_date ) { 864 maxDateTime = $.tm_datepicker._get( dp_inst, 'maxDateTime' ); 865 maxDateTimeDate = new Date( maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0 ); 866 867 if ( this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null ) { 868 this.hourMaxOriginal = o.hourMax; 869 this.minuteMaxOriginal = o.minuteMax; 870 this.secondMaxOriginal = o.secondMax; 871 this.millisecMaxOriginal = o.millisecMax; 872 this.microsecMaxOriginal = o.microsecMax; 873 } 874 875 if ( dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime() ) { 876 this._defaults.hourMax = maxDateTime.getHours(); 877 if ( this.hour >= this._defaults.hourMax ) { 878 this.hour = this._defaults.hourMax; 879 this._defaults.minuteMax = maxDateTime.getMinutes(); 880 if ( this.minute >= this._defaults.minuteMax ) { 881 this.minute = this._defaults.minuteMax; 882 this._defaults.secondMax = maxDateTime.getSeconds(); 883 if ( this.second >= this._defaults.secondMax ) { 884 this.second = this._defaults.secondMax; 885 this._defaults.millisecMax = maxDateTime.getMilliseconds(); 886 if ( this.millisec >= this._defaults.millisecMax ) { 887 this.millisec = this._defaults.millisecMax;
888 this._defaults.microsecMax = maxDateTime.getMicroseconds(); 889 } else { 890 if ( this.microsec > this._defaults.microsecMax ) { 891 this.microsec = this._defaults.microsecMax; 892 } 893 this._defaults.microsecMax = this.microsecMaxOriginal; 894 } 895 } else { 896 this._defaults.millisecMax = this.millisecMaxOriginal; 897 this._defaults.microsecMax = this.microsecMaxOriginal; 898 } 899 } else { 900 this._defaults.secondMax = this.secondMaxOriginal; 901 this._defaults.millisecMax = this.millisecMaxOriginal; 902 this._defaults.microsecMax = this.microsecMaxOriginal; 903 } 904 } else { 905 this._defaults.minuteMax = this.minuteMaxOriginal; 906 this._defaults.secondMax = this.secondMaxOriginal; 907 this._defaults.millisecMax = this.millisecMaxOriginal; 908 this._defaults.microsecMax = this.microsecMaxOriginal; 909 } 910 } else { 911 this._defaults.hourMax = this.hourMaxOriginal; 912 this._defaults.minuteMax = this.minuteMaxOriginal; 913 this._defaults.secondMax = this.secondMaxOriginal; 914 this._defaults.millisecMax = this.millisecMaxOriginal; 915 this._defaults.microsecMax = this.microsecMaxOriginal; 916 } 917 } 918 919 if ( dp_inst.settings.minTime !== null ) { 920 tempMinTime = new Date( '01/01/1970 ' + dp_inst.settings.minTime ); 921 if ( parseFloat( dp_inst.settings.minTime ).toString() === dp_inst.settings.minTime ) { 922 tempMinTime = new Date( Date.now() + parseFloat( dp_inst.settings.minTime ) ); 923 } 924 if ( this.hour < tempMinTime.getHours() ) { 925 this._defaults.hourMin = tempMinTime.getHours(); 926 this.hour = this._defaults.hourMin; 927 this._defaults.minuteMin = tempMinTime.getMinutes(); 928 this.minute = this._defaults.minuteMin; 929 } else if ( this.hour === tempMinTime.getHours() && this.minute < tempMinTime.getMinutes() ) { 930 this._defaults.minuteMin = tempMinTime.getMinutes(); 931 this.minute = this._defaults.minuteMin; 932 } else if ( this._defaults.hourMin < tempMinTime.getHours() ) { 933 this._defaults.hourMin = tempMinTime.getHours(); 934 this._defaults.minuteMin = tempMinTime.getMinutes(); 935 } else if ( ( this._defaults.hourMin === tempMinTime.getHours() ) === this.hour && this._defaults.minuteMin < tempMinTime.getMinutes() ) { 936 this._defaults.minuteMin = tempMinTime.getMinutes(); 937 } else { 938 this._defaults.minuteMin = 0; 939 } 940 } 941 942 if ( dp_inst.settings.maxTime !== null ) { 943 tempMaxTime = new Date( '01/01/1970 ' + dp_inst.settings.maxTime ); 944 if ( this.hour > tempMaxTime.getHours() ) { 945 this._defaults.hourMax = tempMaxTime.getHours(); 946 this.hour = this._defaults.hourMax; 947 this._defaults.minuteMax = tempMaxTime.getMinutes(); 948 this.minute = this._defaults.minuteMax; 949 } else if ( this.hour === tempMaxTime.getHours() && this.minute > tempMaxTime.getMinutes() ) { 950 this._defaults.minuteMax = tempMaxTime.getMinutes(); 951 this.minute = this._defaults.minuteMax; 952 } else if ( this._defaults.hourMax > tempMaxTime.getHours() ) { 953 this._defaults.hourMax = tempMaxTime.getHours(); 954 this._defaults.minuteMax = tempMaxTime.getMinutes(); 955 } else if ( ( this._defaults.hourMax === tempMaxTime.getHours() ) === this.hour && this._defaults.minuteMax > tempMaxTime.getMinutes() ) { 956 this._defaults.minuteMax = tempMaxTime.getMinutes(); 957 } else { 958 this._defaults.minuteMax = 59; 959 } 960 } 961 962 if ( adjustSliders !== undefined && adjustSliders === true ) { 963 hourMax = parseInt( this._defaults.hourMax - ( ( this._defaults.hourMax - this._defaults.hourMin ) % this._defaults.stepHour ), 10 ); 964 minMax = parseInt( this._defaults.minuteMax - ( ( this._defaults.minuteMax - this._defaults.minuteMin ) % this._defaults.stepMinute ), 10 ); 965 secMax = parseInt( this._defaults.secondMax - ( ( this._defaults.secondMax - this._defaults.secondMin ) % this._defaults.stepSecond ), 10 ); 966 millisecMax = parseInt( this._defaults.millisecMax - ( ( this._defaults.millisecMax - this._defaults.millisecMin ) % this._defaults.stepMillisec ), 10 );
967 microsecMax = parseInt( this._defaults.microsecMax - ( ( this._defaults.microsecMax - this._defaults.microsecMin ) % this._defaults.stepMicrosec ), 10 ); 968 969 if ( this.hour_slider ) { 970 this.control.options( this, this.hour_slider, 'hour', { 971 min: this._defaults.hourMin, 972 max: hourMax, 973 step: this._defaults.stepHour 974 } ); 975 this.control.value( this, this.hour_slider, 'hour', this.hour - ( this.hour % this._defaults.stepHour ) ); 976 } 977 if ( this.minute_slider ) { 978 this.control.options( this, this.minute_slider, 'minute', { 979 min: this._defaults.minuteMin, 980 max: minMax, 981 step: this._defaults.stepMinute 982 } ); 983 this.control.value( this, this.minute_slider, 'minute', this.minute - ( this.minute % this._defaults.stepMinute ) ); 984 } 985 if ( this.second_slider ) { 986 this.control.options( this, this.second_slider, 'second', { 987 min: this._defaults.secondMin, 988 max: secMax, 989 step: this._defaults.stepSecond 990 } ); 991 this.control.value( this, this.second_slider, 'second', this.second - ( this.second % this._defaults.stepSecond ) ); 992 } 993 if ( this.millisec_slider ) { 994 this.control.options( this, this.millisec_slider, 'millisec', { 995 min: this._defaults.millisecMin, 996 max: millisecMax, 997 step: this._defaults.stepMillisec 998 } ); 999 this.control.value( this, this.millisec_slider, 'millisec', this.millisec - ( this.millisec % this._defaults.stepMillisec ) ); 1000 } 1001 if ( this.microsec_slider ) { 1002 this.control.options( this, this.microsec_slider, 'microsec', { 1003 min: this._defaults.microsecMin, 1004 max: microsecMax, 1005 step: this._defaults.stepMicrosec 1006 } ); 1007 this.control.value( this, this.microsec_slider, 'microsec', this.microsec - ( this.microsec % this._defaults.stepMicrosec ) ); 1008 } 1009 } 1010 }, 1011 1012 /* 1013 * when a slider moves, set the internal time... 1014 * on time change is also called when the time is updated in the text field 1015 */ 1016 _onTimeChange: function() { 1017 var hour = this.hour_slider ? this.control.value( this, this.hour_slider, 'hour' ) : false, 1018 minute = this.minute_slider ? this.control.value( this, this.minute_slider, 'minute' ) : false, 1019 second = this.second_slider ? this.control.value( this, this.second_slider, 'second' ) : false, 1020 millisec = this.millisec_slider ? this.control.value( this, this.millisec_slider, 'millisec' ) : false, 1021 microsec = this.microsec_slider ? this.control.value( this, this.microsec_slider, 'microsec' ) : false, 1022 timezone = this.timezone_select ? this.timezone_select.val() : false, 1023 o = this._defaults, 1024 pickerTimeFormat = o.pickerTimeFormat || o.timeFormat, 1025 pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix; 1026 var ampm; 1027 var hasChanged; 1028 var sPos; 1029 var ePos; 1030 1031 if ( ! this._defaults.showTimepicker ) { 1032 return; 1033 } 1034 1035 if ( typeof hour === 'object' ) { 1036 hour = false;
vendor: 20,658 bytes, lines 1037-1714
1037 } 1038 if ( typeof minute === 'object' ) { 1039 minute = false; 1040 } 1041 if ( typeof second === 'object' ) { 1042 second = false; 1043 } 1044 if ( typeof millisec === 'object' ) { 1045 millisec = false; 1046 } 1047 if ( typeof microsec === 'object' ) { 1048 microsec = false; 1049 } 1050 if ( typeof timezone === 'object' ) { 1051 timezone = false; 1052 } 1053 1054 if ( hour !== false ) { 1055 hour = parseInt( hour, 10 ); 1056 } 1057 if ( minute !== false ) { 1058 minute = parseInt( minute, 10 ); 1059 } 1060 if ( second !== false ) { 1061 second = parseInt( second, 10 ); 1062 } 1063 if ( millisec !== false ) { 1064 millisec = parseInt( millisec, 10 ); 1065 } 1066 if ( microsec !== false ) { 1067 microsec = parseInt( microsec, 10 ); 1068 } 1069 if ( timezone !== false ) { 1070 timezone = timezone.toString(); 1071 } 1072 1073 ampm = o[ hour < 12 ? 'amNames' : 'pmNames' ][ 0 ]; 1074 1075 // If the update was done in the input field, the input field should not be updated. 1076 // If the update was done using the sliders, update the input field. 1077 hasChanged = 1078 hour !== parseInt( this.hour, 10 ) || // sliders should all be numeric 1079 minute !== parseInt( this.minute, 10 ) || 1080 second !== parseInt( this.second, 10 ) || 1081 millisec !== parseInt( this.millisec, 10 ) || 1082 microsec !== parseInt( this.microsec, 10 ) || 1083 ( this.ampm.length > 0 && ( hour < 12 ) !== ( $.inArray( this.ampm.toUpperCase(), this.amNames ) !== -1 ) ) || 1084 ( this.timezone !== null && timezone !== this.timezone.toString() ); // could be numeric or "EST" format, so use toString() 1085 1086 if ( hasChanged ) { 1087 if ( hour !== false ) { 1088 this.hour = hour; 1089 } 1090 if ( minute !== false ) { 1091 this.minute = minute; 1092 } 1093 if ( second !== false ) { 1094 this.second = second; 1095 } 1096 if ( millisec !== false ) { 1097 this.millisec = millisec; 1098 } 1099 if ( microsec !== false ) { 1100 this.microsec = microsec; 1101 } 1102 if ( timezone !== false ) { 1103 this.timezone = timezone; 1104 } 1105 1106 if ( ! this.inst ) { 1107 this.inst = $.tm_datepicker._getInst( this.$input[ 0 ] ); 1108 } 1109 1110 this._limitMinMaxDateTime( this.inst, true ); 1111 } 1112 if ( this.support.ampm ) { 1113 this.ampm = ampm; 1114 } 1115 1116 // Updates the time within the tm_timepicker 1117 this.formattedTime = $.tm_datepicker.formatTime( o.timeFormat, this, o ); 1118 if ( this.$timeObj ) { 1119 if ( pickerTimeFormat === o.timeFormat ) { 1120 this.$timeObj.val( this.formattedTime + pickerTimeSuffix ); 1121 } else { 1122 this.$timeObj.val( $.tm_datepicker.formatTime( pickerTimeFormat, this, o ) + pickerTimeSuffix ); 1123 } 1124 if ( this.$timeObj[ 0 ].setSelectionRange ) { 1125 sPos = this.$timeObj[ 0 ].selectionStart; 1126 ePos = this.$timeObj[ 0 ].selectionEnd; 1127 this.$timeObj[ 0 ].setSelectionRange( sPos, ePos ); 1128 } 1129 } 1130 1131 this.timeDefined = true; 1132 if ( hasChanged ) { 1133 this._updateDateTime(); 1134 //this.$input.trigger(' focus' ); // may automatically open the picker on setDate 1135 } 1136 }, 1137 1138 /* 1139 * call custom onSelect. 1140 * bind to sliders slidestop, and grid click. 1141 */ 1142 _onSelectHandler: function() { 1143 var onSelect = this._defaults.onSelect || this.inst.settings.onSelect; 1144 var inputEl = this.$input ? this.$input[ 0 ] : null; 1145 if ( onSelect && inputEl ) { 1146 onSelect.apply( inputEl, [ this.formattedDateTime, this ] ); 1147 } 1148 }, 1149 1150 /* 1151 * update our input with the new date time.. 1152 */ 1153 _updateDateTime: function( dp_inst ) { 1154 var dtTmp; 1155 var dt; 1156 var dateFmt; 1157 var formatCfg; 1158 var timeAvailable; 1159 var formattedDateTime; 1160 var altFormattedDateTime = ''; 1161 var altSeparator; 1162 var altTimeSuffix; 1163 1164 dp_inst = this.inst || dp_inst; 1165 dtTmp = dp_inst.currentYear > 0 ? new Date( dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay ) : new Date( dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay ); 1166 dt = $.tm_datepicker._daylightSavingAdjust( dtTmp ); 1167 //dt = $.tm_datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)), 1168 //dt = $.tm_datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)), 1169 dateFmt = $.tm_datepicker._get( dp_inst, 'dateFormat' ); 1170 formatCfg = $.tm_datepicker._getFormatConfig( dp_inst ); 1171 timeAvailable = dt !== null && this.timeDefined; 1172 this.formattedDate = $.tm_datepicker.formatDate( dateFmt, dt === null ? new Date() : dt, formatCfg ); 1173 formattedDateTime = this.formattedDate; 1174 1175 // if a slider was changed but tm_datepicker doesn't have a value yet, set it 1176 if ( dp_inst.lastVal === '' ) { 1177 dp_inst.currentYear = dp_inst.selectedYear; 1178 dp_inst.currentMonth = dp_inst.selectedMonth; 1179 dp_inst.currentDay = dp_inst.selectedDay; 1180 } 1181 1182 /* 1183 * remove following lines to force every changes in date picker to change the input value 1184 * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker. 1185 * If the user manually empty the value in the input field, the date picker will never change selected value. 1186 */ 1187 //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) { 1188 //return; 1189 //} 1190 1191 if ( this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === false ) { 1192 formattedDateTime = this.formattedTime; 1193 } else if ( ( this._defaults.timeOnly !== true && ( this._defaults.alwaysSetTime || timeAvailable ) ) || ( this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === true ) ) { 1194 formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix; 1195 } 1196 1197 this.formattedDateTime = formattedDateTime; 1198 1199 if ( ! this._defaults.showTimepicker ) { 1200 this.$input.val( this.formattedDate ); 1201 } else if ( this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true ) { 1202 this.$altInput.val( this.formattedTime ); 1203 this.$input.val( this.formattedDate ); 1204 } else if ( this.$altInput ) { 1205 this.$input.val( formattedDateTime ); 1206 altFormattedDateTime = ''; 1207 altSeparator = this._defaults.altSeparator !== null ? this._defaults.altSeparator : this._defaults.separator; 1208 altTimeSuffix = this._defaults.altTimeSuffix !== null ? this._defaults.altTimeSuffix : this._defaults.timeSuffix; 1209 1210 if ( ! this._defaults.timeOnly ) { 1211 if ( this._defaults.altFormat ) { 1212 altFormattedDateTime = $.tm_datepicker.formatDate( this._defaults.altFormat, dt === null ? new Date() : dt, formatCfg ); 1213 } else { 1214 altFormattedDateTime = this.formattedDate; 1215 } 1216 1217 if ( altFormattedDateTime ) { 1218 altFormattedDateTime += altSeparator; 1219 } 1220 } 1221 1222 if ( this._defaults.altTimeFormat !== null ) { 1223 altFormattedDateTime += $.tm_datepicker.formatTime( this._defaults.altTimeFormat, this, this._defaults ) + altTimeSuffix; 1224 } else { 1225 altFormattedDateTime += this.formattedTime + altTimeSuffix; 1226 } 1227 this.$altInput.val( altFormattedDateTime ); 1228 } else { 1229 this.$input.val( formattedDateTime ); 1230 } 1231 1232 this.$input.trigger( 'change' ); 1233 }, 1234 1235 _onFocus: function() { 1236 var inst; 1237 var tp_inst; 1238 if ( ! this.$input.val() && this._defaults.defaultValue ) { 1239 this.$input.val( this._defaults.defaultValue ); 1240 inst = $.tm_datepicker._getInst( this.$input.get( 0 ) ); 1241 tp_inst = $.tm_datepicker._get( inst, 'tm_timepicker' ); 1242 if ( tp_inst ) { 1243 if ( tp_inst._defaults.timeOnly && inst.input.val() !== inst.lastVal ) { 1244 try { 1245 $.tm_datepicker._updateDatepicker( inst ); 1246 } catch ( err ) { 1247 $.tm_timepicker.log( err ); 1248 } 1249 } 1250 } 1251 } 1252 }, 1253 1254 /* 1255 * Small abstraction to control types 1256 * We can add more, just be sure to follow the pattern: create, options, value 1257 */ 1258 _controls: { 1259 // slider methods 1260 slider: { 1261 create: function( tp_inst, obj, unit, val, min, max, step ) { 1262 var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60 1263 return obj.prop( 'slide', null ).slider( { 1264 orientation: 'horizontal', 1265 value: rtl ? val * -1 : val, 1266 min: rtl ? max * -1 : min, 1267 max: rtl ? min * -1 : max, 1268 step: step, 1269 slide: function( event, ui ) { 1270 tp_inst.control.value( tp_inst, $( this ), unit, rtl ? ui.value * -1 : ui.value ); 1271 tp_inst._onTimeChange(); 1272 }, 1273 stop: function() { 1274 tp_inst._onSelectHandler(); 1275 } 1276 } ); 1277 }, 1278 options: function( tp_inst, obj, unit, opts, val ) { 1279 var min; 1280 var max; 1281 if ( tp_inst._defaults.isRTL ) { 1282 if ( typeof opts === 'string' ) { 1283 if ( opts === 'min' || opts === 'max' ) { 1284 if ( val !== undefined ) { 1285 return obj.slider( opts, val * -1 ); 1286 } 1287 return Math.abs( obj.slider( opts ) ); 1288 } 1289 return obj.slider( opts ); 1290 } 1291 min = opts.min; 1292 max = opts.max; 1293 opts.max = null; 1294 opts.min = null; 1295 if ( min !== undefined ) { 1296 opts.max = min * -1; 1297 } 1298 if ( max !== undefined ) { 1299 opts.min = max * -1; 1300 } 1301 return obj.slider( opts ); 1302 } 1303 if ( typeof opts === 'string' && val !== undefined ) { 1304 return obj.slider( opts, val ); 1305 } 1306 return obj.slider( opts ); 1307 }, 1308 value: function( tp_inst, obj, unit, val ) { 1309 if ( tp_inst._defaults.isRTL ) { 1310 if ( val !== undefined ) { 1311 return obj.slider( 'value', val * -1 ); 1312 } 1313 return Math.abs( obj.slider( 'value' ) ); 1314 } 1315 if ( val !== undefined ) { 1316 return obj.slider( 'value', val ); 1317 } 1318 return obj.slider( 'value' ); 1319 } 1320 }, 1321 // select methods 1322 select: { 1323 create: function( tp_inst, obj, unit, val, min, max, step ) { 1324 var sel = '<select class="ui-tm-timepicker-select ui-state-default ui-corner-all" data-unit="' + unit + '" data-min="' + min + '" data-max="' + max + '" data-step="' + step + '">', 1325 format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat; 1326 var i; 1327 1328 for ( i = min; i <= max; i += step ) { 1329 sel += '<option value="' + i + '"' + ( i === val ? ' selected' : '' ) + '>'; 1330 if ( unit === 'hour' ) { 1331 sel += $.tm_datepicker.formatTime( $.epoAPI.util.trim( format.replace( /[^ht ]/gi, '' ) ), { hour: i }, tp_inst._defaults ); 1332 } else if ( unit === 'millisec' || unit === 'microsec' || i >= 10 ) { 1333 sel += i; 1334 } else { 1335 sel += '0' + i.toString(); 1336 } 1337 sel += '</option>'; 1338 } 1339 sel += '</select>'; 1340 1341 obj.children( 'select' ).remove(); 1342 1343 $( sel ) 1344 .appendTo( obj ) 1345 .on( 'change', function() { 1346 tp_inst._onTimeChange(); 1347 tp_inst._onSelectHandler(); 1348 tp_inst._afterInject(); 1349 } ); 1350 1351 return obj; 1352 }, 1353 options: function( tp_inst, obj, unit, opts, val ) { 1354 var o = {}, 1355 $t = obj.children( 'select' ); 1356 if ( typeof opts === 'string' ) { 1357 if ( val === undefined ) { 1358 return $t.data( opts ); 1359 } 1360 o[ opts ] = val; 1361 } else { 1362 o = opts; 1363 } 1364 return tp_inst.control.create( tp_inst, obj, $t.data( 'unit' ), $t.val(), o.min >= 0 ? o.min : $t.data( 'min' ), o.max || $t.data( 'max' ), o.step || $t.data( 'step' ) ); 1365 }, 1366 value: function( tp_inst, obj, unit, val ) { 1367 var $t = obj.children( 'select' ); 1368 if ( val !== undefined ) { 1369 return $t.val( val ); 1370 } 1371 return $t.val(); 1372 } 1373 } 1374 } // end _controls 1375 } ); 1376 1377 $.fn.extend( { 1378 /* 1379 * shorthand just to use tm_timepicker. 1380 */ 1381 tm_timepicker: function( o ) { 1382 var tmp_args = Array.prototype.slice.call( arguments ); 1383 o = o || {}; 1384 1385 if ( typeof o === 'object' ) { 1386 tmp_args[ 0 ] = $.extend( o, { 1387 timeOnly: true 1388 } ); 1389 } 1390 1391 return $( this ).each( function() { 1392 $.fn.tm_datetimepicker.apply( $( this ), tmp_args ); 1393 } ); 1394 }, 1395 1396 /* 1397 * extend tm_timepicker to tm_datepicker 1398 */ 1399 tm_datetimepicker: function( o ) { 1400 var tmp_args = arguments; 1401 o = o || {}; 1402 1403 if ( typeof o === 'string' ) { 1404 if ( o === 'getDate' || ( o === 'option' && tmp_args.length === 2 && typeof tmp_args[ 1 ] === 'string' ) ) { 1405 return $.fn.tm_datepicker.apply( $( this[ 0 ] ), tmp_args ); 1406 } 1407 return this.each( function() { 1408 var $t = $( this ); 1409 $t.tm_datepicker.apply( $t, tmp_args ); 1410 } ); 1411 } 1412 return this.each( function() { 1413 var $t = $( this ); 1414 $t.tm_datepicker( $.tm_timepicker._newInst( $t, o )._defaults ); 1415 } ); 1416 } 1417 } ); 1418 1419 /* 1420 * Public Utility to parse date and time 1421 */ 1422 $.tm_datepicker.parseDateTime = function( dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings ) { 1423 var parseRes = parseDateTimeInternal( dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings ); 1424 var t; 1425 if ( parseRes.timeObj ) { 1426 t = parseRes.timeObj; 1427 parseRes.date.setHours( t.hour, t.minute, t.second, t.millisec ); 1428 parseRes.date.setMicroseconds( t.microsec ); 1429 } 1430 1431 return parseRes.date; 1432 }; 1433 1434 /* 1435 * Public utility to parse time 1436 */ 1437 $.tm_datepicker.parseTime = function( timeFormat, timeString, options ) { 1438 var o = extendRemove( extendRemove( {}, $.tm_timepicker._defaults ), options || {} ); 1439 1440 // Strict parse requires the timeString to match the timeFormat exactly 1441 var strictParse = function( f, s, oo ) { 1442 // pattern for standard and localized AM/PM markers 1443 var getPatternAmpm = function( amNames, pmNames ) { 1444 var markers = []; 1445 if ( amNames ) { 1446 $.merge( markers, amNames ); 1447 } 1448 if ( pmNames ) { 1449 $.merge( markers, pmNames ); 1450 } 1451 markers = $.map( markers, function( val ) { 1452 return val.replace( /[.*+?|()[\]{}\\]/g, '\\$&' ); 1453 } ); 1454 return '(' + markers.join( '|' ) + ')?'; 1455 }; 1456 1457 // figure out position of time elements.. cause js cant do named captures 1458 var getFormatPositions = function( formatoftime ) { 1459 var finds = formatoftime.toLowerCase().match( /(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g ), 1460 orders = { 1461 h: -1, 1462 m: -1, 1463 s: -1, 1464 l: -1, 1465 c: -1, 1466 t: -1, 1467 z: -1 1468 }; 1469 var i; 1470 1471 if ( finds ) { 1472 for ( i = 0; i < finds.length; i += 1 ) { 1473 if ( orders[ finds[ i ].toString().charAt( 0 ) ] === -1 ) { 1474 orders[ finds[ i ].toString().charAt( 0 ) ] = i + 1; 1475 } 1476 } 1477 } 1478 return orders; 1479 }; 1480 1481 var regstr = 1482 '^' + 1483 f 1484 .toString() 1485 .replace( /([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function( match ) { 1486 var ml = match.length; 1487 switch ( match.charAt( 0 ).toLowerCase() ) { 1488 case 'h': 1489 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})'; 1490 case 'm': 1491 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})'; 1492 case 's': 1493 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})'; 1494 case 'l': 1495 return '(\\d?\\d?\\d)'; 1496 case 'c': 1497 return '(\\d?\\d?\\d)'; 1498 case 'z': 1499 return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?'; 1500 case 't': 1501 return getPatternAmpm( oo.amNames, oo.pmNames ); 1502 default: 1503 // literal escaped in quotes 1504 return ( 1505 '(' + 1506 match.replace( /'/g, '' ).replace( /(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function( m ) { 1507 return '\\' + m; 1508 } ) + 1509 ')?' 1510 ); 1511 } 1512 } ) 1513 .replace( /\s/g, '\\s?' ) + 1514 oo.timeSuffix + 1515 '$', 1516 order = getFormatPositions( f ), 1517 ampm = '', 1518 treg; 1519 1520 var resTime = { 1521 hour: 0, 1522 minute: 0, 1523 second: 0, 1524 millisec: 0, 1525 microsec: 0 1526 }; 1527 1528 treg = s.match( new RegExp( regstr, 'i' ) ); 1529 1530 if ( treg ) { 1531 if ( order.t !== -1 ) { 1532 if ( treg[ order.t ] === undefined || treg[ order.t ].length === 0 ) { 1533 ampm = ''; 1534 resTime.ampm = ''; 1535 } else { 1536 ampm = 1537 $.inArray( 1538 treg[ order.t ].toUpperCase(), 1539 $.map( oo.amNames, function( x ) { 1540 return x.toUpperCase(); 1541 } ) 1542 ) !== -1 1543 ? 'AM' 1544 : 'PM'; 1545 resTime.ampm = oo[ ampm === 'AM' ? 'amNames' : 'pmNames' ][ 0 ]; 1546 } 1547 } 1548 1549 if ( order.h !== -1 ) { 1550 if ( ampm === 'AM' && treg[ order.h ] === '12' ) { 1551 resTime.hour = 0; // 12am = 0 hour 1552 } else if ( ampm === 'PM' && treg[ order.h ] !== '12' ) { 1553 resTime.hour = parseInt( treg[ order.h ], 10 ) + 12; // 12pm = 12 hour, any other pm = hour + 12 1554 } else { 1555 resTime.hour = Number( treg[ order.h ] ); 1556 } 1557 } 1558 1559 if ( order.m !== -1 ) { 1560 resTime.minute = Number( treg[ order.m ] ); 1561 } 1562 if ( order.s !== -1 ) { 1563 resTime.second = Number( treg[ order.s ] ); 1564 } 1565 if ( order.l !== -1 ) { 1566 resTime.millisec = Number( treg[ order.l ] ); 1567 } 1568 if ( order.c !== -1 ) { 1569 resTime.microsec = Number( treg[ order.c ] ); 1570 } 1571 if ( order.z !== -1 && treg[ order.z ] !== undefined ) { 1572 resTime.timezone = $.tm_timepicker.timezoneOffsetNumber( treg[ order.z ] ); 1573 } 1574 1575 return resTime; 1576 } 1577 return false; 1578 }; // end strictParse 1579 1580 // First try JS Date, if that fails, use strictParse 1581 var looseParse = function( f, s, oo ) { 1582 var d; 1583 try { 1584 d = new Date( '2012-01-01 ' + s ); 1585 if ( isNaN( d.getTime() ) ) { 1586 d = new Date( '2012-01-01T' + s ); 1587 if ( isNaN( d.getTime() ) ) { 1588 d = new Date( '01/01/2012 ' + s ); 1589 if ( isNaN( d.getTime() ) ) { 1590 throw 'Unable to parse time with native Date: ' + s; 1591 } 1592 } 1593 } 1594 1595 return { 1596 hour: d.getHours(), 1597 minute: d.getMinutes(), 1598 second: d.getSeconds(), 1599 millisec: d.getMilliseconds(), 1600 microsec: d.getMicroseconds(), 1601 timezone: d.getTimezoneOffset() * -1 1602 }; 1603 } catch ( err ) { 1604 try { 1605 return strictParse( f, s, oo ); 1606 } catch ( err2 ) { 1607 $.tm_timepicker.log( 'Unable to parse \ntimeString: ' + s + '\ntimeFormat: ' + f ); 1608 } 1609 } 1610 return false; 1611 }; // end looseParse 1612 1613 if ( typeof o.parse === 'function' ) { 1614 return o.parse( timeFormat, timeString, o ); 1615 } 1616 if ( o.parse === 'loose' ) { 1617 return looseParse( timeFormat, timeString, o ); 1618 } 1619 return strictParse( timeFormat, timeString, o ); 1620 }; 1621 1622 /** 1623 * Public utility to format the time. 1624 * 1625 * @param {string} format format of the time 1626 * @param {Object} time Object not a Date for timezones 1627 * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm 1628 * @returns {string} the formatted time 1629 */ 1630 $.tm_datepicker.formatTime = function( format, time, options ) { 1631 var tmptime; 1632 var ampmName; 1633 var hour; 1634 1635 options = options || {}; 1636 options = $.extend( {}, $.tm_timepicker._defaults, options ); 1637 time = $.extend( 1638 { 1639 hour: 0, 1640 minute: 0, 1641 second: 0, 1642 millisec: 0, 1643 microsec: 0, 1644 timezone: null 1645 }, 1646 time 1647 ); 1648 1649 tmptime = format; 1650 ampmName = options.amNames[ 0 ]; 1651 hour = parseInt( time.hour, 10 ); 1652 1653 if ( hour > 11 ) { 1654 ampmName = options.pmNames[ 0 ]; 1655 } 1656 1657 tmptime = tmptime.replace( /(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function( match ) { 1658 switch ( match ) { 1659 case 'HH': 1660 return ( '0' + hour ).slice( -2 ); 1661 case 'H': 1662 return hour; 1663 case 'hh': 1664 return ( '0' + convert24to12( hour ) ).slice( -2 ); 1665 case 'h': 1666 return convert24to12( hour ); 1667 case 'mm': 1668 return ( '0' + time.minute ).slice( -2 ); 1669 case 'm': 1670 return time.minute; 1671 case 'ss': 1672 return ( '0' + time.second ).slice( -2 ); 1673 case 's': 1674 return time.second; 1675 case 'l': 1676 return ( '00' + time.millisec ).slice( -3 ); 1677 case 'c': 1678 return ( '00' + time.microsec ).slice( -3 ); 1679 case 'z': 1680 return $.tm_timepicker.timezoneOffsetString( time.timezone === null ? options.timezone : time.timezone, false ); 1681 case 'Z': 1682 return $.tm_timepicker.timezoneOffsetString( time.timezone === null ? options.timezone : time.timezone, true ); 1683 case 'T': 1684 return ampmName.charAt( 0 ).toUpperCase(); 1685 case 'TT': 1686 return ampmName.toUpperCase(); 1687 case 't': 1688 return ampmName.charAt( 0 ).toLowerCase(); 1689 case 'tt': 1690 return ampmName.toLowerCase(); 1691 default: 1692 return match.replace( /'/g, '' ); 1693 } 1694 } ); 1695 1696 return tmptime; 1697 }; 1698 1699 /* 1700 * the bad hack :/ override tm_datepicker so it doesn't close on select 1701 // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378 1702 */ 1703 $.tm_datepicker._base_selectDate = $.tm_datepicker._selectDate; 1704 $.tm_datepicker._selectDate = function( id, dateStr ) { 1705 var inst = this._getInst( $( id )[ 0 ] ), 1706 tp_inst = this._get( inst, 'tm_timepicker' ), 1707 was_inline; 1708 1709 if ( tp_inst && inst.settings.showTimepicker ) { 1710 tp_inst._limitMinMaxDateTime( inst, true ); 1711 was_inline = inst.inline; 1712 inst.stay_open = true; 1713 inst.inline = true; 1714 //This way the onSelect handler called from calendarpicker get the full dateTime
1715 this._base_selectDate( id, dateStr ); 1716 inst.inline = was_inline; 1717 inst.stay_open = false; 1718 this._notifyChange( inst ); 1719 this._updateDatepicker( inst ); 1720 } else { 1721 this._base_selectDate( id, dateStr ); 1722 } 1723 }; 1724 1725 /* 1726 * second bad hack :/ override tm_datepicker so it triggers an event when changing the input field 1727 * and does not redraw the tm_datepicker on every selectDate event 1728 */ 1729 $.tm_datepicker._base_updateDatepicker = $.tm_datepicker._updateDatepicker; 1730 $.tm_datepicker._updateDatepicker = function( inst ) { 1731 // don't popup the tm_datepicker if there is another instance already opened 1732 var input = inst.input[ 0 ]; 1733 var tp_inst; 1734 if ( $.tm_datepicker._curInst && $.tm_datepicker._curInst !== inst && $.tm_datepicker._datepickerShowing && $.tm_datepicker._lastInput !== input ) { 1735 return; 1736 } 1737 1738 if ( typeof inst.stay_open !== 'boolean' || inst.stay_open === false ) { 1739 this._base_updateDatepicker( inst ); 1740 1741 // Reload the time control when changing something in the input text field. 1742 tp_inst = this._get( inst, 'tm_timepicker' ); 1743 if ( tp_inst ) { 1744 tp_inst._addTimePicker( inst ); 1745 } 1746 } 1747 }; 1748 1749 /* 1750 * third bad hack :/ override tm_datepicker so it allows spaces and colon in the input field 1751 */ 1752 $.tm_datepicker._base_doKeyPress = $.tm_datepicker._doKeyPress; 1753 $.tm_datepicker._doKeyPress = function( event ) { 1754 var inst = $.tm_datepicker._getInst( event.target ), 1755 tp_inst = $.tm_datepicker._get( inst, 'tm_timepicker' ); 1756 var ampm; 1757 var tz; 1758 var dateChars; 1759 var datetimeChars; 1760 var chr; 1761 1762 if ( tp_inst ) { 1763 if ( $.tm_datepicker._get( inst, 'constrainInput' ) ) { 1764 ampm = tp_inst.support.ampm; 1765 tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone; 1766 dateChars = $.tm_datepicker._possibleChars( $.tm_datepicker._get( inst, 'dateFormat' ) ); 1767 datetimeChars = 1768 tp_inst._defaults.timeFormat 1769 .toString() 1770 .replace( /[hms]/g, '' ) 1771 .replace( /TT/g, ampm ? 'APM' : '' ) 1772 .replace( /Tt/g, ampm ? 'AaPpMm' : '' ) 1773 .replace( /tT/g, ampm ? 'AaPpMm' : '' ) 1774 .replace( /T/g, ampm ? 'AP' : '' ) 1775 .replace( /tt/g, ampm ? 'apm' : '' ) 1776 .replace( /t/g, ampm ? 'ap' : '' ) + 1777 ' ' + 1778 tp_inst._defaults.separator + 1779 tp_inst._defaults.timeSuffix + 1780 ( tz ? tp_inst._defaults.timezoneList.join( '' ) : '' ) + 1781 tp_inst._defaults.amNames.join( '' ) + 1782 tp_inst._defaults.pmNames.join( '' ) + 1783 dateChars; 1784 chr = String.fromCharCode( event.charCode === undefined ? event.keyCode : event.charCode ); 1785 return event.ctrlKey || chr < ' ' || ! dateChars || datetimeChars.indexOf( chr ) > -1; 1786 } 1787 } 1788 1789 return $.tm_datepicker._base_doKeyPress( event ); 1790 }; 1791 1792 /* 1793 * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField 1794 * Update any alternate field to synchronise with the main field. 1795 */ 1796 $.tm_datepicker._base_updateAlternate = $.tm_datepicker._updateAlternate; 1797 $.tm_datepicker._updateAlternate = function( inst ) { 1798 var tp_inst = this._get( inst, 'tm_timepicker' ); 1799 var altField; 1800 var date; 1801 var formatCfg; 1802 var altFormattedDateTime; 1803 var altSeparator; 1804 var altTimeSuffix; 1805 var altTimeFormat; 1806 if ( tp_inst ) { 1807 altField = tp_inst._defaults.altField; 1808 if ( altField ) { 1809 // update alternate field too 1810 date = this._getDate( inst ); 1811 formatCfg = $.tm_datepicker._getFormatConfig( inst ); 1812 altFormattedDateTime = ''; 1813 altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator; 1814 altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix; 1815 altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat; 1816 1817 altFormattedDateTime += $.tm_datepicker.formatTime( altTimeFormat, tp_inst, tp_inst._defaults ) + altTimeSuffix; 1818 if ( ! tp_inst._defaults.timeOnly && ! tp_inst._defaults.altFieldTimeOnly && date !== null ) { 1819 if ( tp_inst._defaults.altFormat ) { 1820 altFormattedDateTime = $.tm_datepicker.formatDate( tp_inst._defaults.altFormat, date, formatCfg ) + altSeparator + altFormattedDateTime; 1821 } else { 1822 altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime; 1823 } 1824 } 1825 $( altField ).val( inst.input.val() ? altFormattedDateTime : '' ); 1826 } 1827 } else { 1828 $.tm_datepicker._base_updateAlternate( inst ); 1829 } 1830 }; 1831 1832 /* 1833 * Override key up event to sync manual input changes. 1834 */ 1835 $.tm_datepicker._base_doKeyUp = $.tm_datepicker._doKeyUp; 1836 $.tm_datepicker._doKeyUp = function( event ) { 1837 var inst = $.tm_datepicker._getInst( event.target ), 1838 tp_inst = $.tm_datepicker._get( inst, 'tm_timepicker' ); 1839 1840 if ( tp_inst ) { 1841 if ( tp_inst._defaults.timeOnly && inst.input.val() !== inst.lastVal ) { 1842 try { 1843 $.tm_datepicker._updateDatepicker( inst ); 1844 } catch ( err ) { 1845 $.tm_timepicker.log( err ); 1846 } 1847 } 1848 } 1849 1850 return $.tm_datepicker._base_doKeyUp( event ); 1851 }; 1852 1853 /* 1854 * override "Today" button to also grab the time and set it to input field. 1855 */ 1856 $.tm_datepicker._base_gotoToday = $.tm_datepicker._gotoToday; 1857 $.tm_datepicker._gotoToday = function( id ) { 1858 var inst = this._getInst( $( id )[ 0 ] ); 1859 var tp_inst; 1860 var tzoffset; 1861 var now; 1862 this._base_gotoToday( id ); 1863 tp_inst = this._get( inst, 'timepicker' ); 1864 if ( ! tp_inst ) { 1865 return; 1866 } 1867 1868 tzoffset = $.tm_timepicker.timezoneOffsetNumber( tp_inst.timezone ); 1869 now = new Date(); 1870 now.setMinutes( now.getMinutes() + now.getTimezoneOffset() + parseInt( tzoffset, 10 ) ); 1871 this._setTime( inst, now ); 1872 this._setDate( inst, now ); 1873 tp_inst._onSelectHandler(); 1874 }; 1875 1876 /* 1877 * Disable & enable the Time in the datetimepicker 1878 */ 1879 $.tm_datepicker._disableTimepickerDatepicker = function( target ) { 1880 var inst = this._getInst( target ); 1881 var tp_inst; 1882 if ( ! inst ) { 1883 return; 1884 } 1885 1886 tp_inst = this._get( inst, 'tm_timepicker' ); 1887 $( target ).tm_datepicker( 'getDate' ); // Init selected[Year|Month|Day] 1888 if ( tp_inst ) { 1889 inst.settings.showTimepicker = false;
1890 tp_inst._defaults.showTimepicker = false; 1891 tp_inst._updateDateTime( inst ); 1892 } 1893 }; 1894 1895 $.tm_datepicker._enableTimepickerDatepicker = function( target ) { 1896 var inst = this._getInst( target ); 1897 var tp_inst; 1898 if ( ! inst ) { 1899 return; 1900 } 1901 1902 tp_inst = this._get( inst, 'tm_timepicker' ); 1903 $( target ).tm_datepicker( 'getDate' ); // Init selected[Year|Month|Day] 1904 if ( tp_inst ) { 1905 inst.settings.showTimepicker = true; 1906 tp_inst._defaults.showTimepicker = true; 1907 tp_inst._addTimePicker( inst ); // Could be disabled on page load 1908 tp_inst._updateDateTime( inst ); 1909 } 1910 }; 1911 1912 /* 1913 * Create our own set time function 1914 */ 1915 $.tm_datepicker._setTime = function( inst, date ) { 1916 var tp_inst = this._get( inst, 'tm_timepicker' ); 1917 var defaults; 1918 if ( tp_inst ) { 1919 defaults = tp_inst._defaults; 1920 1921 // calling _setTime with no date sets time to defaults 1922 tp_inst.hour = date ? date.getHours() : defaults.hour; 1923 tp_inst.minute = date ? date.getMinutes() : defaults.minute; 1924 tp_inst.second = date ? date.getSeconds() : defaults.second; 1925 tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec; 1926 tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec; 1927 1928 //check if within min/max times.. 1929 tp_inst._limitMinMaxDateTime( inst, true ); 1930 1931 tp_inst._onTimeChange(); 1932 tp_inst._updateDateTime( inst ); 1933 } 1934 }; 1935 1936 /* 1937 * Create new public method to set only time, callable as $().tm_datepicker('setTime', date) 1938 */ 1939 $.tm_datepicker._setTimeDatepicker = function( target, date, withDate ) { 1940 var inst = this._getInst( target ); 1941 var tp_inst; 1942 var tp_date; 1943 1944 if ( ! inst ) { 1945 return; 1946 } 1947 1948 tp_inst = this._get( inst, 'tm_timepicker' ); 1949 1950 if ( tp_inst ) { 1951 this._setDateFromField( inst ); 1952 1953 if ( date ) { 1954 if ( typeof date === 'string' ) { 1955 tp_inst._parseTime( date, withDate ); 1956 tp_date = new Date(); 1957 tp_date.setHours( tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec ); 1958 tp_date.setMicroseconds( tp_inst.microsec ); 1959 } else { 1960 tp_date = new Date( date.getTime() ); 1961 tp_date.setMicroseconds( date.getMicroseconds() ); 1962 } 1963 if ( tp_date.toString() === 'Invalid Date' ) { 1964 tp_date = undefined; 1965 } 1966 this._setTime( inst, tp_date ); 1967 } 1968 } 1969 }; 1970 1971 /* 1972 * override setDate() to allow setting time too within Date object 1973 */ 1974 $.tm_datepicker._base_setDateDatepicker = $.tm_datepicker._setDateDatepicker; 1975 $.tm_datepicker._setDateDatepicker = function( target, _date ) { 1976 var inst = this._getInst( target ); 1977 var date = _date; 1978 var tp_inst; 1979 var tp_date; 1980 if ( ! inst ) { 1981 return; 1982 } 1983 1984 if ( typeof _date === 'string' ) { 1985 date = new Date( _date ); 1986 if ( ! date.getTime() ) { 1987 this._base_setDateDatepicker.apply( this, arguments ); 1988 date = $( target ).tm_datepicker( 'getDate' ); 1989 } 1990 } 1991 1992 tp_inst = this._get( inst, 'tm_timepicker' ); 1993 if ( date instanceof Date ) { 1994 tp_date = new Date( date.getTime() ); 1995 tp_date.setMicroseconds( date.getMicroseconds() ); 1996 } else { 1997 tp_date = date; 1998 } 1999 2000 // This is important if you are using the timezone option, javascript's Date 2001 // object will only return the timezone offset for the current locale, so we 2002 // adjust it accordingly. If not using timezone option this won't matter.. 2003 // If a timezone is different in tp, keep the timezone as is 2004 if ( tp_inst && tp_date ) { 2005 // look out for DST if tz wasn't specified 2006 if ( ! tp_inst.support.timezone && tp_inst._defaults.timezone === null ) { 2007 tp_inst.timezone = tp_date.getTimezoneOffset() * -1; 2008 } 2009 date = $.tm_timepicker.timezoneAdjust( date, $.tm_timepicker.timezoneOffsetString( -date.getTimezoneOffset() ), tp_inst.timezone ); 2010 tp_date = $.tm_timepicker.timezoneAdjust( tp_date, $.tm_timepicker.timezoneOffsetString( -tp_date.getTimezoneOffset() ), tp_inst.timezone ); 2011 } 2012 2013 this._updateDatepicker( inst ); 2014 this._base_setDateDatepicker.apply( this, arguments ); 2015 this._setTimeDatepicker( target, tp_date, true ); 2016 }; 2017 2018 /* 2019 * override getDate() to allow getting time too within Date object 2020 */ 2021 $.tm_datepicker._base_getDateDatepicker = $.tm_datepicker._getDateDatepicker; 2022 $.tm_datepicker._getDateDatepicker = function( target, noDefault ) { 2023 var inst = this._getInst( target ); 2024 var tp_inst; 2025 var date; 2026 var currDT; 2027 2028 if ( ! inst ) { 2029 return; 2030 } 2031 2032 tp_inst = this._get( inst, 'tm_timepicker' ); 2033 2034 if ( tp_inst ) { 2035 // if it hasn't yet been defined, grab from field 2036 if ( inst.lastVal === undefined ) { 2037 this._setDateFromField( inst, noDefault ); 2038 } 2039 2040 date = this._getDate( inst ); 2041 2042 currDT = null; 2043 2044 if ( tp_inst.$altInput && tp_inst._defaults.altFieldTimeOnly ) { 2045 currDT = tp_inst.$input.val() + ' ' + tp_inst.$altInput.val(); 2046 } else if ( tp_inst.$input.get( 0 ).tagName !== 'INPUT' && tp_inst.$altInput ) { 2047 /** 2048 * in case the datetimepicker has been applied to a non-input tag for inline UI, 2049 * and the user has not configured the plugin to display only time in altInput, 2050 * pick current date time from the altInput (and hope for the best, for now, until "ER1" is applied) 2051 * 2052 * @todo ER1. Since altInput can have a totally difference format, convert it to standard format by reading input format from "altFormat" and "altTimeFormat" option values 2053 */ 2054 currDT = tp_inst.$altInput.val(); 2055 } else { 2056 currDT = tp_inst.$input.val(); 2057 } 2058 2059 if ( date && tp_inst._parseTime( currDT, ! inst.settings.timeOnly ) ) {
vendor: 7,140 bytes, lines 2060-2277
2060 date.setHours( tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec ); 2061 date.setMicroseconds( tp_inst.microsec ); 2062 2063 // This is important if you are using the timezone option, javascript's Date 2064 // object will only return the timezone offset for the current locale, so we 2065 // adjust it accordingly. If not using timezone option this won't matter.. 2066 if ( tp_inst.timezone !== null ) { 2067 // look out for DST if tz wasn't specified 2068 if ( ! tp_inst.support.timezone && tp_inst._defaults.timezone === null ) { 2069 tp_inst.timezone = date.getTimezoneOffset() * -1; 2070 } 2071 date = $.tm_timepicker.timezoneAdjust( date, tp_inst.timezone, $.tm_timepicker.timezoneOffsetString( -date.getTimezoneOffset() ) ); 2072 } 2073 } 2074 return date; 2075 } 2076 return this._base_getDateDatepicker( target, noDefault ); 2077 }; 2078 2079 /* 2080 * override parseDate() because UI 1.8.14 throws an error about "Extra characters" 2081 * An option in datapicker to ignore extra format characters would be nicer. 2082 */ 2083 $.tm_datepicker._base_parseDate = $.tm_datepicker.parseDate; 2084 $.tm_datepicker.parseDate = function( format, value, settings ) { 2085 var date; 2086 try { 2087 date = this._base_parseDate( format, value, settings ); 2088 } catch ( err ) { 2089 // Hack! The error message ends with a colon, a space, and 2090 // the "extra" characters. We rely on that instead of 2091 // attempting to perfectly reproduce the parsing algorithm. 2092 if ( err.indexOf( ':' ) >= 0 ) { 2093 date = this._base_parseDate( format, value.substring( 0, value.length - ( err.length - err.indexOf( ':' ) - 2 ) ), settings ); 2094 $.tm_timepicker.log( 'Error parsing the date string: ' + err + '\ndate string = ' + value + '\ndate format = ' + format ); 2095 } else { 2096 throw err; 2097 } 2098 } 2099 return date; 2100 }; 2101 2102 /* 2103 * override formatDate to set date with time to the input 2104 */ 2105 $.tm_datepicker._base_formatDate = $.tm_datepicker._formatDate; 2106 $.tm_datepicker._formatDate = function( inst ) { 2107 var tp_inst = this._get( inst, 'tm_timepicker' ); 2108 if ( tp_inst ) { 2109 tp_inst._updateDateTime( inst ); 2110 return tp_inst.$input.val(); 2111 } 2112 return this._base_formatDate( inst ); 2113 }; 2114 2115 /* 2116 * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate 2117 */ 2118 $.tm_datepicker._base_optionDatepicker = $.tm_datepicker._optionDatepicker; 2119 $.tm_datepicker._optionDatepicker = function( target, name, value ) { 2120 var inst = this._getInst( target ), 2121 name_clone; 2122 var tp_inst; 2123 var min, max, onselect, overrides, fns, prop, ret, oldVal, $target; 2124 2125 if ( ! inst ) { 2126 return null; 2127 } 2128 2129 tp_inst = this._get( inst, 'tm_timepicker' ); 2130 if ( tp_inst ) { 2131 min = null; 2132 max = null; 2133 onselect = null; 2134 overrides = tp_inst._defaults.evnts; 2135 fns = {}; 2136 2137 if ( typeof name === 'string' ) { 2138 // if min/max was set with the string 2139 if ( name === 'minDate' || name === 'minDateTime' ) { 2140 min = value; 2141 } else if ( name === 'maxDate' || name === 'maxDateTime' ) { 2142 max = value; 2143 } else if ( name === 'onSelect' ) { 2144 onselect = value; 2145 } else if ( Object.prototype.hasOwnProperty.call( overrides, name ) ) { 2146 if ( typeof value === 'undefined' ) { 2147 return overrides[ name ]; 2148 } 2149 fns[ name ] = value; 2150 name_clone = {}; //empty results in exiting function after overrides updated 2151 } 2152 } else if ( typeof name === 'object' ) { 2153 //if min/max was set with the JSON 2154 if ( name.minDate ) { 2155 min = name.minDate; 2156 } else if ( name.minDateTime ) { 2157 min = name.minDateTime; 2158 } else if ( name.maxDate ) { 2159 max = name.maxDate; 2160 } else if ( name.maxDateTime ) { 2161 max = name.maxDateTime; 2162 } 2163 for ( prop in overrides ) { 2164 if ( Object.prototype.hasOwnProperty.call( overrides, prop ) && name[ prop ] ) { 2165 fns[ prop ] = name[ prop ]; 2166 } 2167 } 2168 } 2169 for ( prop in fns ) { 2170 if ( Object.prototype.hasOwnProperty.call( fns, prop ) ) { 2171 overrides[ prop ] = fns[ prop ]; 2172 if ( ! name_clone ) { 2173 name_clone = $.extend( {}, name ); 2174 } 2175 delete name_clone[ prop ]; 2176 } 2177 } 2178 if ( name_clone && isEmptyObject( name_clone ) ) { 2179 return; 2180 } 2181 if ( min ) { 2182 //if min was set 2183 if ( min === 0 ) { 2184 min = new Date(); 2185 } else { 2186 min = new Date( min ); 2187 } 2188 tp_inst._defaults.minDate = min; 2189 tp_inst._defaults.minDateTime = min; 2190 } else if ( max ) { 2191 //if max was set 2192 if ( max === 0 ) { 2193 max = new Date(); 2194 } else { 2195 max = new Date( max ); 2196 } 2197 tp_inst._defaults.maxDate = max; 2198 tp_inst._defaults.maxDateTime = max; 2199 } else if ( onselect ) { 2200 tp_inst._defaults.onSelect = onselect; 2201 } 2202 2203 // Datepicker will override our date when we call _base_optionDatepicker when 2204 // calling minDate/maxDate, so we will first grab the value, call 2205 // _base_optionDatepicker, then set our value back. 2206 if ( min || max ) { 2207 $target = $( target ); 2208 oldVal = $target.tm_datetimepicker( 'getDate' ); 2209 ret = this._base_optionDatepicker.call( $.tm_datepicker, target, name_clone || name, value ); 2210 $target.tm_datetimepicker( 'setDate', oldVal ); 2211 return ret; 2212 } 2213 } 2214 if ( value === undefined ) { 2215 return this._base_optionDatepicker.call( $.tm_datepicker, target, name ); 2216 } 2217 return this._base_optionDatepicker.call( $.tm_datepicker, target, name_clone || name, value ); 2218 }; 2219 2220 /* 2221 * Create a Singleton Instance 2222 */ 2223 $.tm_timepicker = new Timepicker(); 2224 2225 /** 2226 * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5) 2227 * 2228 * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned 2229 * @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45" 2230 * @return {string} timezone Offset 2231 */ 2232 $.tm_timepicker.timezoneOffsetString = function( tzMinutes, iso8601 ) { 2233 var off, minutes, hours, iso, tz; 2234 2235 if ( isNaN( tzMinutes ) || tzMinutes > 840 || tzMinutes < -720 ) { 2236 return tzMinutes; 2237 } 2238 2239 off = tzMinutes; 2240 minutes = off % 60; 2241 hours = ( off - minutes ) / 60; 2242 iso = iso8601 ? ':' : ''; 2243 tz = ( off >= 0 ? '+' : '-' ) + ( '0' + Math.abs( hours ) ).slice( -2 ) + iso + ( '0' + Math.abs( minutes ) ).slice( -2 ); 2244 2245 if ( tz === '+00:00' ) { 2246 return 'Z'; 2247 } 2248 return tz; 2249 }; 2250 2251 /** 2252 * Get the number in minutes that represents a timezone string 2253 * 2254 * @param {string} tzString formatted like "+0500", "-1245", "Z" 2255 * @return {number} the offset minutes or the original string if it doesn't match expectations 2256 */ 2257 $.tm_timepicker.timezoneOffsetNumber = function( tzString ) { 2258 var normalized = tzString.toString().replace( ':', '' ); // excuse any iso8601, end up with "+1245" 2259 2260 if ( normalized.toUpperCase() === 'Z' ) { 2261 // if iso8601 with Z, its 0 minute offset 2262 return 0; 2263 } 2264 2265 if ( ! /^(-|\+)\d{4}$/.test( normalized ) ) { 2266 // possibly a user defined tz, so just give it back 2267 return parseInt( tzString, 10 ); 2268 } 2269 2270 return ( 2271 ( normalized.substring( 0, 1 ) === '-' ? -1 : 1 ) * // plus or minus 2272 ( ( parseInt( normalized.substring( 1, 3 ), 10 ) * 60 ) + // hours (converted to minutes) 2273 parseInt( normalized.substring( 3, 5 ), 10 ) ) 2274 ); // minutes 2275 }; 2276 2277 /**
2278 * No way to set timezone in js Date, so we must adjust the minutes to compensate. 2279 * (think setDate, getDate) 2280 * 2281 * @param {Date} date 2282 * @param {string} fromTimezone formatted like "+0500", "-1245" 2283 * @param {string} toTimezone formatted like "+0500", "-1245" 2284 * @return {Date} Date 2285 */ 2286 $.tm_timepicker.timezoneAdjust = function( date, fromTimezone, toTimezone ) { 2287 var fromTz = $.timepicker.timezoneOffsetNumber( fromTimezone ); 2288 var toTz = $.tm_timepicker.timezoneOffsetNumber( toTimezone ); 2289 if ( ! isNaN( toTz ) ) { 2290 date.setMinutes( date.getMinutes() + -fromTz - -toTz ); 2291 } 2292 return date; 2293 }; 2294 2295 /** 2296 * Calls `tm_timepicker()` on the `startTime` and `endTime` elements, and configures them to 2297 * enforce date range limits. 2298 * n.b. The input value must be correctly formatted (reformatting is not supported) 2299 * 2300 * @param {Element} startTime 2301 * @param {Element} endTime 2302 * @param {Object} options Options for the tm_timepicker() call 2303 * @return {jQuery} time range 2304 */ 2305 $.tm_timepicker.timeRange = function( startTime, endTime, options ) { 2306 return $.tm_timepicker.handleRange( 'tm_timepicker', startTime, endTime, options ); 2307 }; 2308 2309 /** 2310 * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to 2311 * enforce date range limits. 2312 * 2313 * @param {Element} startTime 2314 * @param {Element} endTime 2315 * @param {Object} options Options for the `tm_timepicker()` call. Also supports `reformat`, 2316 * a boolean value that can be used to reformat the input values to the `dateFormat`. 2317 */ 2318 $.tm_timepicker.datetimeRange = function( startTime, endTime, options ) { 2319 $.tm_timepicker.handleRange( 'tm_datetimepicker', startTime, endTime, options ); 2320 }; 2321 2322 /** 2323 * Calls `tm_datepicker` on the `startTime` and `endTime` elements, and configures them to 2324 * enforce date range limits. 2325 * 2326 * @param {Element} startTime 2327 * @param {Element} endTime 2328 * @param {Object} options Options for the `tm_timepicker()` call. Also supports `reformat`, 2329 * a boolean value that can be used to reformat the input values to the `dateFormat`. 2330 */ 2331 $.tm_timepicker.dateRange = function( startTime, endTime, options ) { 2332 $.tm_timepicker.handleRange( 'tm_datepicker', startTime, endTime, options ); 2333 }; 2334 2335 /** 2336 * Calls `method` on the `startTime` and `endTime` elements, and configures them to 2337 * enforce date range limits. 2338 * 2339 * @param {string} method Can be used to specify the type of picker to be added 2340 * @param {Element} startTime 2341 * @param {Element} endTime 2342 * @param {Object} options Options for the `tm_timepicker()` call. Also supports `reformat`, 2343 * a boolean value that can be used to reformat the input values to the `dateFormat`. 2344 * @return {jQuery} range 2345 */ 2346 $.tm_timepicker.handleRange = function( method, startTime, endTime, options ) { 2347 var timeOnly = false; 2348 options = $.extend( 2349 {}, 2350 { 2351 minInterval: 0, // min allowed interval in milliseconds 2352 maxInterval: 0, // max allowed interval in milliseconds 2353 start: {}, // options for start picker 2354 end: {} // options for end picker 2355 }, 2356 options 2357 ); 2358 2359 // for the mean time this fixes an issue with calling getDate with tm_timepicker() 2360 2361 if ( method === 'tm_timepicker' ) { 2362 timeOnly = true; 2363 method = 'tm_datetimepicker'; 2364 } 2365 2366 function checkDates( changed, other ) { 2367 var startdt = startTime[ method ]( 'getDate' ), 2368 enddt = endTime[ method ]( 'getDate' ), 2369 changeddt = changed[ method ]( 'getDate' ); 2370 var minDate; 2371 var maxDate; 2372 2373 if ( startdt !== null ) { 2374 minDate = new Date( startdt.getTime() ); 2375 maxDate = new Date( startdt.getTime() ); 2376 2377 minDate.setMilliseconds( minDate.getMilliseconds() + options.minInterval ); 2378 maxDate.setMilliseconds( maxDate.getMilliseconds() + options.maxInterval ); 2379 2380 if ( options.minInterval > 0 && minDate > enddt ) { 2381 // minInterval check 2382 endTime[ method ]( 'setDate', minDate ); 2383 } else if ( options.maxInterval > 0 && maxDate < enddt ) { 2384 // max interval check 2385 endTime[ method ]( 'setDate', maxDate ); 2386 } else if ( startdt > enddt ) { 2387 other[ method ]( 'setDate', changeddt ); 2388 } 2389 } 2390 } 2391 2392 function selected( changed, other, option ) { 2393 var date; 2394 if ( ! changed.val() ) { 2395 return; 2396 } 2397 date = changed[ method ].call( changed, 'getDate' ); 2398 if ( date !== null && options.minInterval > 0 ) { 2399 if ( option === 'minDate' ) { 2400 date.setMilliseconds( date.getMilliseconds() + options.minInterval ); 2401 } 2402 if ( option === 'maxDate' ) { 2403 date.setMilliseconds( date.getMilliseconds() - options.minInterval ); 2404 } 2405 } 2406 2407 if ( date.getTime ) { 2408 other[ method ].call( other, 'option', option, date ); 2409 } 2410 } 2411 2412 $.fn[ method ].call( 2413 startTime, 2414 $.extend( 2415 { 2416 timeOnly: timeOnly, 2417 onClose: function() { 2418 checkDates( $( this ), endTime ); 2419 }, 2420 onSelect: function() { 2421 selected( $( this ), endTime, 'minDate' ); 2422 } 2423 }, 2424 options, 2425 options.start 2426 ) 2427 ); 2428 $.fn[ method ].call( 2429 endTime, 2430 $.extend( 2431 { 2432 timeOnly: timeOnly, 2433 onClose: function() { 2434 checkDates( $( this ), startTime ); 2435 }, 2436 onSelect: function() { 2437 selected( $( this ), startTime, 'maxDate' ); 2438 } 2439 }, 2440 options, 2441 options.end 2442 ) 2443 ); 2444 2445 checkDates( startTime, endTime ); 2446 2447 selected( startTime, endTime, 'minDate' ); 2448 selected( endTime, startTime, 'maxDate' ); 2449 2450 return $( [ startTime.get( 0 ), endTime.get( 0 ) ] ); 2451 }; 2452 2453 /** 2454 * Log error or data to the console during error or debugging 2455 * 2456 * @return {void} 2457 */ 2458 $.tm_timepicker.log = function() { 2459 // Older IE (9, maybe 10) throw error on accessing `window.console.log.apply`, so check first. 2460 if ( window.console && window.console.log && window.console.log.apply ) { 2461 window.console.log.apply( window.console, Array.prototype.slice.call( arguments ) ); 2462 } 2463 }; 2464 2465 /* 2466 * Add util object to allow access to private methods for testability. 2467 */ 2468 $.tm_timepicker._util = { 2469 _extendRemove: extendRemove, 2470 _isEmptyObject: isEmptyObject, 2471 _convert24to12: convert24to12, 2472 _detectSupport: detectSupport, 2473 _selectLocalTimezone: selectLocalTimezone, 2474 _computeEffectiveSetting: computeEffectiveSetting, 2475 _splitDateTime: splitDateTime, 2476 _parseDateTimeInternal: parseDateTimeInternal 2477 }; 2478 2479 /* 2480 * Microsecond support 2481 */ 2482 if ( ! Date.prototype.getMicroseconds ) { 2483 Object.defineProperty( Date.prototype, 'microseconds', { 2484 value: 0, 2485 writable: true 2486 } ); 2487 2488 Object.defineProperty( Date.prototype, 'getMicroseconds', { 2489 value: function() { 2490 return this.microseconds; 2491 } 2492 } ); 2493 2494 Object.defineProperty( Date.prototype, 'setMicroseconds', { 2495 value: function( m ) { 2496 this.setMilliseconds( this.getMilliseconds() + Math.floor( m / 1000 ) ); 2497 this.microseconds = m % 1000; 2498 return this; 2499 } 2500 } ); 2501 } 2502 2503 /* 2504 * Keep up with the version 2505 */ 2506 $.tm_timepicker.version = '1.6.3'; 2507} ) );
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.