1/* ========================================================= 2 * bootstrap-datetimepicker.js 3 * ========================================================= 4 * Copyright 2012 Stefan Petre 5 * Improvements by Andrew Rowls 6 * Improvements by Sébastien Malot 7 * Improvements by Yun Lai 8 * Project URL : http://www.malot.fr/bootstrap-datetimepicker 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * ========================================================= */ 22 23/* 24 * Improvement by CuGBabyBeaR @ 2013-09-12 25 * 26 * Make it work in bootstrap v3 27 */ 28 29!function ($) { 30 31 function UTCDate() { 32 return new Date(Date.UTC.apply(Date, arguments)); 33 } 34 35 function UTCToday() { 36 var today = new Date(); 37 return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), today.getUTCHours(), today.getUTCMinutes(), today.getUTCSeconds(), 0); 38 } 39 40 // Picker object 41 42 var Datetimepicker = function (element, options) { 43 var that = this; 44 45 this.element = $(element); 46 47 this.language = options.language || this.element.data('date-language') || "en"; 48 this.language = this.language in dates ? this.language : "en"; 49 this.isRTL = dates[this.language].rtl || false; 50 this.formatType = options.formatType || this.element.data('format-type') || 'standard'; 51 this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType); 52 this.isInline = false; 53 this.isVisible = false; 54 this.isInput = this.element.is('input'); 55 56 this.bootcssVer = this.isInput ? (this.element.is('.form-control') ? 3 : 2) : ( this.bootcssVer = this.element.is('.input-group') ? 3 : 2 ); 57 58 this.component = this.element.is('.date') ? ( this.bootcssVer == 3 ? this.element.find('.input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-calendar').parent() : this.element.find('.add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar').parent()) : false; 59 this.componentReset = this.element.is('.date') ? ( this.bootcssVer == 3 ? this.element.find('.input-group-addon .glyphicon-remove').parent() : this.element.find('.add-on .icon-remove').parent()) : false; 60 this.hasInput = this.component && this.element.find('input').length; 61 if (this.component && this.component.length === 0) { 62 this.component = false; 63 } 64 this.linkField = options.linkField || this.element.data('link-field') || false; 65 this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType); 66 this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5; 67 this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right'; 68 this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false; 69 this.initialDate = options.initialDate || new Date(); 70 71 this._attachEvents(); 72 73 this.formatViewType = "datetime"; 74 if ('formatViewType' in options) { 75 this.formatViewType = options.formatViewType; 76 } else if ('formatViewType' in this.element.data()) { 77 this.formatViewType = this.element.data('formatViewType'); 78 } 79 80 this.minView = 0; 81 if ('minView' in options) { 82 this.minView = options.minView; 83 } else if ('minView' in this.element.data()) { 84 this.minView = this.element.data('min-view'); 85 } 86 this.minView = DPGlobal.convertViewMode(this.minView); 87 88 this.maxView = DPGlobal.modes.length - 1; 89 if ('maxView' in options) { 90 this.maxView = options.maxView; 91 } else if ('maxView' in this.element.data()) { 92 this.maxView = this.element.data('max-view'); 93 } 94 this.maxView = DPGlobal.convertViewMode(this.maxView); 95 96 this.wheelViewModeNavigation = false;
97 if ('wheelViewModeNavigation' in options) { 98 this.wheelViewModeNavigation = options.wheelViewModeNavigation; 99 } else if ('wheelViewModeNavigation' in this.element.data()) { 100 this.wheelViewModeNavigation = this.element.data('view-mode-wheel-navigation'); 101 } 102 103 this.wheelViewModeNavigationInverseDirection = false; 104 105 if ('wheelViewModeNavigationInverseDirection' in options) { 106 this.wheelViewModeNavigationInverseDirection = options.wheelViewModeNavigationInverseDirection; 107 } else if ('wheelViewModeNavigationInverseDirection' in this.element.data()) { 108 this.wheelViewModeNavigationInverseDirection = this.element.data('view-mode-wheel-navigation-inverse-dir'); 109 } 110 111 this.wheelViewModeNavigationDelay = 100; 112 if ('wheelViewModeNavigationDelay' in options) { 113 this.wheelViewModeNavigationDelay = options.wheelViewModeNavigationDelay; 114 } else if ('wheelViewModeNavigationDelay' in this.element.data()) { 115 this.wheelViewModeNavigationDelay = this.element.data('view-mode-wheel-navigation-delay'); 116 } 117 118 this.startViewMode = 2; 119 if ('startView' in options) { 120 this.startViewMode = options.startView; 121 } else if ('startView' in this.element.data()) { 122 this.startViewMode = this.element.data('start-view'); 123 } 124 this.startViewMode = DPGlobal.convertViewMode(this.startViewMode); 125 this.viewMode = this.startViewMode; 126 127 this.viewSelect = this.minView; 128 if ('viewSelect' in options) { 129 this.viewSelect = options.viewSelect; 130 } else if ('viewSelect' in this.element.data()) { 131 this.viewSelect = this.element.data('view-select'); 132 } 133 this.viewSelect = DPGlobal.convertViewMode(this.viewSelect); 134 135 this.forceParse = true; 136 if ('forceParse' in options) { 137 this.forceParse = options.forceParse; 138 } else if ('dateForceParse' in this.element.data()) { 139 this.forceParse = this.element.data('date-force-parse'); 140 } 141 142 this.picker = $((this.bootcssVer == 3) ? DPGlobal.templateV3 : DPGlobal.template) 143 .appendTo(this.isInline ? this.element : 'body') 144 .on({ 145 click: $.proxy(this.click, this), 146 mousedown: $.proxy(this.mousedown, this) 147 }); 148 149 if (this.wheelViewModeNavigation) { 150 if ($.fn.mousewheel) { 151 this.picker.on({mousewheel: $.proxy(this.mousewheel, this)}); 152 } else { 153 console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option"); 154 } 155 } 156 157 if (this.isInline) { 158 this.picker.addClass('datetimepicker-inline'); 159 } else { 160 this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu'); 161 } 162 if (this.isRTL) { 163 this.picker.addClass('datetimepicker-rtl'); 164 if (this.bootcssVer == 3) { 165 this.picker.find('.prev span, .next span') 166 .toggleClass('glyphicon-arrow-left glyphicon-arrow-right'); 167 } else { 168 this.picker.find('.prev i, .next i') 169 .toggleClass('icon-arrow-left icon-arrow-right'); 170 } 171 ; 172 173 } 174 $(document).on('mousedown', function (e) { 175 // Clicked outside the datetimepicker, hide it 176 if ($(e.target).closest('.datetimepicker').length === 0) { 177 that.hide(); 178 } 179 }); 180 181 this.autoclose = false; 182 if ('autoclose' in options) { 183 this.autoclose = options.autoclose; 184 } else if ('dateAutoclose' in this.element.data()) { 185 this.autoclose = this.element.data('date-autoclose'); 186 } 187 188 this.keyboardNavigation = true; 189 if ('keyboardNavigation' in options) { 190 this.keyboardNavigation = options.keyboardNavigation; 191 } else if ('dateKeyboardNavigation' in this.element.data()) { 192 this.keyboardNavigation = this.element.data('date-keyboard-navigation'); 193 } 194 195 this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false); 196 this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false); 197 198 this.weekStart = ((options.weekStart || this.element.data('date-weekstart') || dates[this.language].weekStart || 0) % 7); 199 this.weekEnd = ((this.weekStart + 6) % 7); 200 this.startDate = -Infinity; 201 this.endDate = Infinity; 202 this.daysOfWeekDisabled = []; 203 this.setStartDate(options.startDate || this.element.data('date-startdate')); 204 this.setEndDate(options.endDate || this.element.data('date-enddate')); 205 this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled')); 206 this.fillDow(); 207 this.fillMonths(); 208 this.update(); 209 this.showMode(); 210 211 if (this.isInline) { 212 this.show(); 213 } 214 }; 215 216 Datetimepicker.prototype = { 217 constructor: Datetimepicker, 218 219 _events: [], 220 _attachEvents: function () { 221 this._detachEvents(); 222 if (this.isInput) { // single input 223 this._events = [ 224 [this.element, { 225 focus: $.proxy(this.show, this), 226 keyup: $.proxy(this.update, this), 227 keydown: $.proxy(this.keydown, this) 228 }] 229 ]; 230 } 231 else if (this.component && this.hasInput) { // component: input + button 232 this._events = [ 233 // For components that are not readonly, allow keyboard nav 234 [this.element.find('input'), { 235 focus: $.proxy(this.show, this), 236 keyup: $.proxy(this.update, this), 237 keydown: $.proxy(this.keydown, this) 238 }], 239 [this.component, { 240 click: $.proxy(this.show, this) 241 }] 242 ]; 243 if (this.componentReset) { 244 this._events.push([ 245 this.componentReset, 246 {click: $.proxy(this.reset, this)} 247 ]); 248 } 249 } 250 else if (this.element.is('div')) { // inline datetimepicker 251 this.isInline = true; 252 } 253 else { 254 this._events = [ 255 [this.element, { 256 click: $.proxy(this.show, this) 257 }] 258 ]; 259 } 260 for (var i = 0, el, ev; i < this._events.length; i++) { 261 el = this._events[i][0]; 262 ev = this._events[i][1]; 263 el.on(ev); 264 } 265 }, 266 267 _detachEvents: function () { 268 for (var i = 0, el, ev; i < this._events.length; i++) { 269 el = this._events[i][0]; 270 ev = this._events[i][1]; 271 el.off(ev); 272 } 273 this._events = []; 274 }, 275 276 show: function (e) { 277 this.picker.show(); 278 this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); 279 if (this.forceParse) { 280 this.update(); 281 } 282 this.place(); 283 $(window).on('resize', $.proxy(this.place, this)); 284 if (e) { 285 e.stopPropagation(); 286 e.preventDefault(); 287 } 288 this.isVisible = true; 289 this.element.trigger({ 290 type: 'show', 291 date: this.date 292 }); 293 }, 294 295 hide: function (e) { 296 if (!this.isVisible) return; 297 if (this.isInline) return; 298 this.picker.hide(); 299 $(window).off('resize', this.place); 300 this.viewMode = this.startViewMode; 301 this.showMode(); 302 if (!this.isInput) { 303 $(document).off('mousedown', this.hide); 304 } 305 306 if ( 307 this.forceParse && 308 ( 309 this.isInput && this.element.val() || 310 this.hasInput && this.element.find('input').val() 311 ) 312 ) 313 this.setValue(); 314 this.isVisible = false;
315 this.element.trigger({ 316 type: 'hide', 317 date: this.date 318 }); 319 }, 320 321 remove: function () { 322 this._detachEvents(); 323 this.picker.remove(); 324 delete this.picker; 325 delete this.element.data().datetimepicker; 326 }, 327 328 getDate: function () { 329 var d = this.getUTCDate(); 330 return new Date(d.getTime() + (d.getTimezoneOffset() * 60000)); 331 }, 332 333 getUTCDate: function () { 334 return this.date; 335 }, 336 337 setDate: function (d) { 338 this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000))); 339 }, 340 341 setUTCDate: function (d) { 342 if (d >= this.startDate && d <= this.endDate) { 343 this.date = d; 344 this.setValue(); 345 this.viewDate = this.date; 346 this.fill(); 347 } else { 348 this.element.trigger({ 349 type: 'outOfRange', 350 date: d, 351 startDate: this.startDate, 352 endDate: this.endDate 353 }); 354 } 355 }, 356 357 setFormat: function (format) { 358 this.format = DPGlobal.parseFormat(format, this.formatType); 359 var element; 360 if (this.isInput) { 361 element = this.element; 362 } else if (this.component) { 363 element = this.element.find('input'); 364 } 365 if (element && element.val()) { 366 this.setValue(); 367 } 368 }, 369 370 setValue: function () { 371 var formatted = this.getFormattedDate(); 372 if (!this.isInput) { 373 if (this.component) { 374 this.element.find('input').val(formatted); 375 } 376 this.element.data('date', formatted); 377 } else { 378 this.element.val(formatted); 379 } 380 if (this.linkField) { 381 $('#' + this.linkField).val(this.getFormattedDate(this.linkFormat)); 382 } 383 }, 384 385 getFormattedDate: function (format) { 386 if (format == undefined) format = this.format; 387 return DPGlobal.formatDate(this.date, format, this.language, this.formatType); 388 }, 389 390 setStartDate: function (startDate) { 391 this.startDate = startDate || -Infinity; 392 if (this.startDate !== -Infinity) { 393 this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType); 394 } 395 this.update(); 396 this.updateNavArrows(); 397 }, 398 399 setEndDate: function (endDate) { 400 this.endDate = endDate || Infinity; 401 if (this.endDate !== Infinity) { 402 this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType); 403 } 404 this.update(); 405 this.updateNavArrows(); 406 }, 407 408 setDaysOfWeekDisabled: function (daysOfWeekDisabled) { 409 this.daysOfWeekDisabled = daysOfWeekDisabled || []; 410 if (!$.isArray(this.daysOfWeekDisabled)) { 411 this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/); 412 } 413 this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) { 414 return parseInt(d, 10); 415 }); 416 this.update(); 417 this.updateNavArrows(); 418 }, 419 420 place: function () { 421 if (this.isInline) return; 422 423 var index_highest = 0; 424 $('div').each(function () { 425 var index_current = parseInt($(this).css("zIndex"), 10); 426 if (index_current > index_highest) { 427 index_highest = index_current; 428 } 429 }); 430 var zIndex = index_highest + 10; 431 432 var offset, top, left; 433 if (this.component) { 434 offset = this.component.offset(); 435 left = offset.left; 436 if (this.pickerPosition == 'bottom-left' || this.pickerPosition == 'top-left') { 437 left += this.component.outerWidth() - this.picker.outerWidth(); 438 } 439 } else { 440 offset = this.element.offset(); 441 left = offset.left; 442 } 443 if (this.pickerPosition == 'top-left' || this.pickerPosition == 'top-right') { 444 top = offset.top - this.picker.outerHeight(); 445 } else { 446 top = offset.top + this.height; 447 } 448 this.picker.css({ 449 top: top, 450 left: left, 451 zIndex: zIndex 452 }); 453 }, 454 455 update: function () { 456 var date, fromArgs = false; 457 if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { 458 date = arguments[0]; 459 fromArgs = true; 460 } else { 461 date = this.element.data('date') || (this.isInput ? this.element.val() : this.element.find('input').val()) || this.initialDate; 462 if (typeof date == 'string' || date instanceof String) { 463 date = date.replace(/^\s+|\s+$/g,''); 464 } 465 } 466 467 if (!date) { 468 date = new Date(); 469 fromArgs = false;
470 } 471 472 this.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType); 473 474 if (fromArgs) this.setValue(); 475 476 if (this.date < this.startDate) { 477 this.viewDate = new Date(this.startDate); 478 } else if (this.date > this.endDate) { 479 this.viewDate = new Date(this.endDate); 480 } else { 481 this.viewDate = new Date(this.date); 482 } 483 this.fill(); 484 }, 485 486 fillDow: function () { 487 var dowCnt = this.weekStart, 488 html = '<tr>'; 489 while (dowCnt < this.weekStart + 7) { 490 html += '<th class="dow">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>'; 491 } 492 html += '</tr>'; 493 this.picker.find('.datetimepicker-days thead').append(html); 494 }, 495 496 fillMonths: function () { 497 var html = '', 498 i = 0; 499 while (i < 12) { 500 html += '<span class="month">' + dates[this.language].monthsShort[i++] + '</span>'; 501 } 502 this.picker.find('.datetimepicker-months td').html(html); 503 }, 504 505 fill: function () { 506 if (this.date == null || this.viewDate == null) { 507 return; 508 } 509 var d = new Date(this.viewDate), 510 year = d.getUTCFullYear(), 511 month = d.getUTCMonth(), 512 dayMonth = d.getUTCDate(), 513 hours = d.getUTCHours(), 514 minutes = d.getUTCMinutes(), 515 startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity, 516 startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity, 517 endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity, 518 endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity, 519 currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(), 520 today = new Date(); 521 this.picker.find('.datetimepicker-days thead th:eq(1)') 522 .text(dates[this.language].months[month] + ' ' + year); 523 if (this.formatViewType == "time") { 524 var hourConverted = hours % 12 ? hours % 12 : 12; 525 var hoursDisplay = (hourConverted < 10 ? '0' : '') + hourConverted; 526 var minutesDisplay = (minutes < 10 ? '0' : '') + minutes; 527 var meridianDisplay = dates[this.language].meridiem[hours < 12 ? 0 : 1]; 528 this.picker.find('.datetimepicker-hours thead th:eq(1)') 529 .text(hoursDisplay + ':' + minutesDisplay + ' ' + meridianDisplay.toUpperCase()); 530 this.picker.find('.datetimepicker-minutes thead th:eq(1)') 531 .text(hoursDisplay + ':' + minutesDisplay + ' ' + meridianDisplay.toUpperCase()); 532 } else { 533 this.picker.find('.datetimepicker-hours thead th:eq(1)') 534 .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year); 535 this.picker.find('.datetimepicker-minutes thead th:eq(1)') 536 .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year); 537 } 538 this.picker.find('tfoot th.today') 539 .text(dates[this.language].today) 540 .toggle(this.todayBtn !== false); 541 this.updateNavArrows(); 542 this.fillMonths(); 543 /*var prevMonth = UTCDate(year, month, 0,0,0,0,0); 544 prevMonth.setUTCDate(prevMonth.getDate() - (prevMonth.getUTCDay() - this.weekStart + 7)%7);*/ 545 var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0), 546 day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); 547 prevMonth.setUTCDate(day); 548 prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7); 549 var nextMonth = new Date(prevMonth); 550 nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); 551 nextMonth = nextMonth.valueOf(); 552 var html = []; 553 var clsName; 554 while (prevMonth.valueOf() < nextMonth) { 555 if (prevMonth.getUTCDay() == this.weekStart) { 556 html.push('<tr>'); 557 } 558 clsName = ''; 559 if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) { 560 clsName += ' old'; 561 } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) { 562 clsName += ' new'; 563 } 564 // Compare internal UTC date with local today, not UTC today 565 if (this.todayHighlight && 566 prevMonth.getUTCFullYear() == today.getFullYear() && 567 prevMonth.getUTCMonth() == today.getMonth() && 568 prevMonth.getUTCDate() == today.getDate()) { 569 clsName += ' today'; 570 } 571 if (prevMonth.valueOf() == currentDate) { 572 clsName += ' active'; 573 } 574 if ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate || 575 $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) { 576 clsName += ' disabled'; 577 } 578 html.push('<td class="day' + clsName + '">' + prevMonth.getUTCDate() + '</td>'); 579 if (prevMonth.getUTCDay() == this.weekEnd) { 580 html.push('</tr>'); 581 } 582 prevMonth.setUTCDate(prevMonth.getUTCDate() + 1); 583 } 584 this.picker.find('.datetimepicker-days tbody').empty().append(html.join('')); 585 586 html = []; 587 var txt = '', meridian = '', meridianOld = ''; 588 for (var i = 0; i < 24; i++) { 589 var actual = UTCDate(year, month, dayMonth, i); 590 clsName = ''; 591 // We want the previous hour for the startDate 592 if ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) { 593 clsName += ' disabled'; 594 } else if (hours == i) { 595 clsName += ' active'; 596 } 597 if (this.showMeridian && dates[this.language].meridiem.length == 2) { 598 meridian = (i < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]); 599 if (meridian != meridianOld) { 600 if (meridianOld != '') { 601 html.push('</fieldset>'); 602 } 603 html.push('<fieldset class="hour"><legend>' + meridian.toUpperCase() + '</legend>'); 604 } 605 meridianOld = meridian; 606 txt = (i % 12 ? i % 12 : 12); 607 html.push('<span class="hour' + clsName + ' hour_' + (i < 12 ? 'am' : 'pm') + '">' + txt + '</span>'); 608 if (i == 23) { 609 html.push('</fieldset>'); 610 } 611 } else { 612 txt = i + ':00'; 613 html.push('<span class="hour' + clsName + '">' + txt + '</span>'); 614 } 615 } 616 this.picker.find('.datetimepicker-hours td').html(html.join('')); 617 618 html = []; 619 txt = '', meridian = '', meridianOld = ''; 620 for (var i = 0; i < 60; i += this.minuteStep) { 621 var actual = UTCDate(year, month, dayMonth, hours, i, 0); 622 clsName = ''; 623 if (actual.valueOf() < this.startDate || actual.valueOf() > this.endDate) { 624 clsName += ' disabled'; 625 } else if (Math.floor(minutes / this.minuteStep) == Math.floor(i / this.minuteStep)) { 626 clsName += ' active'; 627 } 628 if (this.showMeridian && dates[this.language].meridiem.length == 2) { 629 meridian = (hours < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]); 630 if (meridian != meridianOld) { 631 if (meridianOld != '') { 632 html.push('</fieldset>'); 633 } 634 html.push('<fieldset class="minute"><legend>' + meridian.toUpperCase() + '</legend>'); 635 } 636 meridianOld = meridian; 637 txt = (hours % 12 ? hours % 12 : 12); 638 //html.push('<span class="minute'+clsName+' minute_'+(hours<12?'am':'pm')+'">'+txt+'</span>'); 639 html.push('<span class="minute' + clsName + '">' + txt + ':' + (i < 10 ? '0' + i : i) + '</span>'); 640 if (i == 59) { 641 html.push('</fieldset>'); 642 } 643 } else { 644 txt = i + ':00'; 645 //html.push('<span class="hour'+clsName+'">'+txt+'</span>'); 646 html.push('<span class="minute' + clsName + '">' + hours + ':' + (i < 10 ? '0' + i : i) + '</span>'); 647 } 648 } 649 this.picker.find('.datetimepicker-minutes td').html(html.join('')); 650 651 var currentYear = this.date.getUTCFullYear(); 652 var months = this.picker.find('.datetimepicker-months') 653 .find('th:eq(1)') 654 .text(year) 655 .end() 656 .find('span').removeClass('active'); 657 if (currentYear == year) { 658 months.eq(this.date.getUTCMonth()).addClass('active'); 659 } 660 if (year < startYear || year > endYear) { 661 months.addClass('disabled'); 662 } 663 if (year == startYear) { 664 months.slice(0, startMonth).addClass('disabled'); 665 } 666 if (year == endYear) { 667 months.slice(endMonth + 1).addClass('disabled'); 668 } 669 670 html = ''; 671 year = parseInt(year / 10, 10) * 10; 672 var yearCont = this.picker.find('.datetimepicker-years') 673 .find('th:eq(1)') 674 .text(year + '-' + (year + 9)) 675 .end() 676 .find('td'); 677 year -= 1;
678 for (var i = -1; i < 11; i++) { 679 html += '<span class="year' + (i == -1 || i == 10 ? ' old' : '') + (currentYear == year ? ' active' : '') + (year < startYear || year > endYear ? ' disabled' : '') + '">' + year + '</span>'; 680 year += 1; 681 } 682 yearCont.html(html); 683 this.place(); 684 }, 685 686 updateNavArrows: function () { 687 var d = new Date(this.viewDate), 688 year = d.getUTCFullYear(), 689 month = d.getUTCMonth(), 690 day = d.getUTCDate(), 691 hour = d.getUTCHours(); 692 switch (this.viewMode) { 693 case 0: 694 if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() 695 && month <= this.startDate.getUTCMonth() 696 && day <= this.startDate.getUTCDate() 697 && hour <= this.startDate.getUTCHours()) { 698 this.picker.find('.prev').css({visibility: 'hidden'}); 699 } else { 700 this.picker.find('.prev').css({visibility: 'visible'}); 701 } 702 if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() 703 && month >= this.endDate.getUTCMonth() 704 && day >= this.endDate.getUTCDate() 705 && hour >= this.endDate.getUTCHours()) { 706 this.picker.find('.next').css({visibility: 'hidden'}); 707 } else { 708 this.picker.find('.next').css({visibility: 'visible'}); 709 } 710 break; 711 case 1: 712 if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() 713 && month <= this.startDate.getUTCMonth() 714 && day <= this.startDate.getUTCDate()) { 715 this.picker.find('.prev').css({visibility: 'hidden'}); 716 } else { 717 this.picker.find('.prev').css({visibility: 'visible'}); 718 } 719 if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() 720 && month >= this.endDate.getUTCMonth() 721 && day >= this.endDate.getUTCDate()) { 722 this.picker.find('.next').css({visibility: 'hidden'}); 723 } else { 724 this.picker.find('.next').css({visibility: 'visible'}); 725 } 726 break; 727 case 2: 728 if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() 729 && month <= this.startDate.getUTCMonth()) { 730 this.picker.find('.prev').css({visibility: 'hidden'}); 731 } else { 732 this.picker.find('.prev').css({visibility: 'visible'}); 733 } 734 if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() 735 && month >= this.endDate.getUTCMonth()) { 736 this.picker.find('.next').css({visibility: 'hidden'}); 737 } else { 738 this.picker.find('.next').css({visibility: 'visible'}); 739 } 740 break; 741 case 3: 742 case 4: 743 if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) { 744 this.picker.find('.prev').css({visibility: 'hidden'}); 745 } else { 746 this.picker.find('.prev').css({visibility: 'visible'}); 747 } 748 if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) { 749 this.picker.find('.next').css({visibility: 'hidden'}); 750 } else { 751 this.picker.find('.next').css({visibility: 'visible'}); 752 } 753 break; 754 } 755 }, 756 757 mousewheel: function (e) { 758 759 e.preventDefault(); 760 e.stopPropagation(); 761 762 if (this.wheelPause) { 763 return; 764 } 765 766 this.wheelPause = true; 767 768 var originalEvent = e.originalEvent; 769 770 var delta = originalEvent.wheelDelta; 771 772 var mode = delta > 0 ? 1 : (delta === 0) ? 0 : -1; 773 774 if (this.wheelViewModeNavigationInverseDirection) { 775 mode = -mode; 776 } 777 778 this.showMode(mode); 779 780 setTimeout($.proxy(function () { 781 782 this.wheelPause = false 783 784 }, this), this.wheelViewModeNavigationDelay); 785 786 }, 787 788 click: function (e) { 789 e.stopPropagation(); 790 e.preventDefault(); 791 var target = $(e.target).closest('span, td, th, legend'); 792 if (target.length == 1) { 793 if (target.is('.disabled')) { 794 this.element.trigger({ 795 type: 'outOfRange', 796 date: this.viewDate, 797 startDate: this.startDate, 798 endDate: this.endDate 799 }); 800 return; 801 } 802 switch (target[0].nodeName.toLowerCase()) { 803 case 'th': 804 switch (target[0].className) { 805 case 'switch': 806 this.showMode(1); 807 break; 808 case 'prev': 809 case 'next': 810 var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1); 811 switch (this.viewMode) { 812 case 0: 813 this.viewDate = this.moveHour(this.viewDate, dir); 814 break; 815 case 1: 816 this.viewDate = this.moveDate(this.viewDate, dir); 817 break; 818 case 2: 819 this.viewDate = this.moveMonth(this.viewDate, dir); 820 break; 821 case 3: 822 case 4: 823 this.viewDate = this.moveYear(this.viewDate, dir); 824 break; 825 } 826 this.fill(); 827 break; 828 case 'today': 829 var date = new Date(); 830 date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0); 831 832 // Respect startDate and endDate. 833 if (date < this.startDate) date = this.startDate; 834 else if (date > this.endDate) date = this.endDate; 835 836 this.viewMode = this.startViewMode; 837 this.showMode(0); 838 this._setDate(date); 839 this.fill(); 840 if (this.autoclose) { 841 this.hide(); 842 } 843 break; 844 } 845 break; 846 case 'span': 847 if (!target.is('.disabled')) { 848 var year = this.viewDate.getUTCFullYear(),
849 month = this.viewDate.getUTCMonth(), 850 day = this.viewDate.getUTCDate(), 851 hours = this.viewDate.getUTCHours(), 852 minutes = this.viewDate.getUTCMinutes(), 853 seconds = this.viewDate.getUTCSeconds(); 854 855 if (target.is('.month')) { 856 this.viewDate.setUTCDate(1); 857 month = target.parent().find('span').index(target); 858 day = this.viewDate.getUTCDate(); 859 this.viewDate.setUTCMonth(month); 860 this.element.trigger({ 861 type: 'changeMonth', 862 date: this.viewDate 863 }); 864 if (this.viewSelect >= 3) { 865 this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); 866 } 867 } else if (target.is('.year')) { 868 this.viewDate.setUTCDate(1); 869 year = parseInt(target.text(), 10) || 0; 870 this.viewDate.setUTCFullYear(year); 871 this.element.trigger({ 872 type: 'changeYear', 873 date: this.viewDate 874 }); 875 if (this.viewSelect >= 4) { 876 this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); 877 } 878 } else if (target.is('.hour')) { 879 hours = parseInt(target.text(), 10) || 0; 880 if (target.hasClass('hour_am') || target.hasClass('hour_pm')) { 881 if (hours == 12 && target.hasClass('hour_am')) { 882 hours = 0; 883 } else if (hours != 12 && target.hasClass('hour_pm')) { 884 hours += 12; 885 } 886 } 887 this.viewDate.setUTCHours(hours); 888 this.element.trigger({ 889 type: 'changeHour', 890 date: this.viewDate 891 }); 892 if (this.viewSelect >= 1) { 893 this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); 894 } 895 } else if (target.is('.minute')) { 896 minutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0; 897 this.viewDate.setUTCMinutes(minutes); 898 this.element.trigger({ 899 type: 'changeMinute', 900 date: this.viewDate 901 }); 902 if (this.viewSelect >= 0) { 903 this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); 904 } 905 } 906 if (this.viewMode != 0) { 907 var oldViewMode = this.viewMode; 908 this.showMode(-1); 909 this.fill(); 910 if (oldViewMode == this.viewMode && this.autoclose) { 911 this.hide(); 912 } 913 } else { 914 this.fill(); 915 if (this.autoclose) { 916 this.hide(); 917 } 918 } 919 } 920 break; 921 case 'td': 922 if (target.is('.day') && !target.is('.disabled')) { 923 var day = parseInt(target.text(), 10) || 1; 924 var year = this.viewDate.getUTCFullYear(), 925 month = this.viewDate.getUTCMonth(), 926 hours = this.viewDate.getUTCHours(), 927 minutes = this.viewDate.getUTCMinutes(), 928 seconds = this.viewDate.getUTCSeconds(); 929 if (target.is('.old')) { 930 if (month === 0) { 931 month = 11; 932 year -= 1; 933 } else { 934 month -= 1; 935 } 936 } else if (target.is('.new')) { 937 if (month == 11) { 938 month = 0; 939 year += 1; 940 } else { 941 month += 1; 942 } 943 } 944 this.viewDate.setUTCFullYear(year); 945 this.viewDate.setUTCMonth(month, day); 946 this.element.trigger({ 947 type: 'changeDay', 948 date: this.viewDate 949 }); 950 if (this.viewSelect >= 2) { 951 this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); 952 } 953 } 954 var oldViewMode = this.viewMode; 955 this.showMode(-1); 956 this.fill(); 957 if (oldViewMode == this.viewMode && this.autoclose) { 958 this.hide(); 959 } 960 break; 961 } 962 } 963 }, 964 965 _setDate: function (date, which) { 966 if (!which || which == 'date') 967 this.date = date; 968 if (!which || which == 'view') 969 this.viewDate = date; 970 this.fill(); 971 this.setValue(); 972 var element; 973 if (this.isInput) { 974 element = this.element; 975 } else if (this.component) { 976 element = this.element.find('input'); 977 } 978 if (element) { 979 element.change(); 980 if (this.autoclose && (!which || which == 'date')) { 981 //this.hide(); 982 } 983 } 984 this.element.trigger({ 985 type: 'changeDate', 986 date: this.date 987 }); 988 }, 989 990 moveMinute: function (date, dir) { 991 if (!dir) return date; 992 var new_date = new Date(date.valueOf()); 993 //dir = dir > 0 ? 1 : -1; 994 new_date.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep)); 995 return new_date; 996 }, 997 998 moveHour: function (date, dir) { 999 if (!dir) return date; 1000 var new_date = new Date(date.valueOf()); 1001 //dir = dir > 0 ? 1 : -1; 1002 new_date.setUTCHours(new_date.getUTCHours() + dir); 1003 return new_date; 1004 }, 1005 1006 moveDate: function (date, dir) { 1007 if (!dir) return date; 1008 var new_date = new Date(date.valueOf()); 1009 //dir = dir > 0 ? 1 : -1; 1010 new_date.setUTCDate(new_date.getUTCDate() + dir); 1011 return new_date; 1012 }, 1013 1014 moveMonth: function (date, dir) { 1015 if (!dir) return date; 1016 var new_date = new Date(date.valueOf()), 1017 day = new_date.getUTCDate(),
1018 month = new_date.getUTCMonth(), 1019 mag = Math.abs(dir), 1020 new_month, test; 1021 dir = dir > 0 ? 1 : -1; 1022 if (mag == 1) { 1023 test = dir == -1 1024 // If going back one month, make sure month is not current month 1025 // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) 1026 ? function () { 1027 return new_date.getUTCMonth() == month; 1028 } 1029 // If going forward one month, make sure month is as expected 1030 // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) 1031 : function () { 1032 return new_date.getUTCMonth() != new_month; 1033 }; 1034 new_month = month + dir; 1035 new_date.setUTCMonth(new_month); 1036 // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 1037 if (new_month < 0 || new_month > 11) 1038 new_month = (new_month + 12) % 12; 1039 } else { 1040 // For magnitudes >1, move one month at a time... 1041 for (var i = 0; i < mag; i++) 1042 // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... 1043 new_date = this.moveMonth(new_date, dir); 1044 // ...then reset the day, keeping it in the new month 1045 new_month = new_date.getUTCMonth(); 1046 new_date.setUTCDate(day); 1047 test = function () { 1048 return new_month != new_date.getUTCMonth(); 1049 }; 1050 } 1051 // Common date-resetting loop -- if date is beyond end of month, make it 1052 // end of month 1053 while (test()) { 1054 new_date.setUTCDate(--day); 1055 new_date.setUTCMonth(new_month); 1056 } 1057 return new_date; 1058 }, 1059 1060 moveYear: function (date, dir) { 1061 return this.moveMonth(date, dir * 12); 1062 }, 1063 1064 dateWithinRange: function (date) { 1065 return date >= this.startDate && date <= this.endDate; 1066 }, 1067 1068 keydown: function (e) { 1069 if (this.picker.is(':not(:visible)')) { 1070 if (e.keyCode == 27) // allow escape to hide and re-show picker 1071 this.show(); 1072 return; 1073 } 1074 var dateChanged = false, 1075 dir, day, month, 1076 newDate, newViewDate; 1077 switch (e.keyCode) { 1078 case 27: // escape 1079 this.hide(); 1080 e.preventDefault(); 1081 break; 1082 case 37: // left 1083 case 39: // right 1084 if (!this.keyboardNavigation) break; 1085 dir = e.keyCode == 37 ? -1 : 1; 1086 viewMode = this.viewMode; 1087 if (e.ctrlKey) { 1088 viewMode += 2; 1089 } else if (e.shiftKey) { 1090 viewMode += 1; 1091 } 1092 if (viewMode == 4) { 1093 newDate = this.moveYear(this.date, dir); 1094 newViewDate = this.moveYear(this.viewDate, dir); 1095 } else if (viewMode == 3) { 1096 newDate = this.moveMonth(this.date, dir); 1097 newViewDate = this.moveMonth(this.viewDate, dir); 1098 } else if (viewMode == 2) { 1099 newDate = this.moveDate(this.date, dir); 1100 newViewDate = this.moveDate(this.viewDate, dir); 1101 } else if (viewMode == 1) { 1102 newDate = this.moveHour(this.date, dir); 1103 newViewDate = this.moveHour(this.viewDate, dir); 1104 } else if (viewMode == 0) { 1105 newDate = this.moveMinute(this.date, dir); 1106 newViewDate = this.moveMinute(this.viewDate, dir); 1107 } 1108 if (this.dateWithinRange(newDate)) { 1109 this.date = newDate; 1110 this.viewDate = newViewDate; 1111 this.setValue(); 1112 this.update(); 1113 e.preventDefault(); 1114 dateChanged = true; 1115 } 1116 break; 1117 case 38: // up 1118 case 40: // down 1119 if (!this.keyboardNavigation) break; 1120 dir = e.keyCode == 38 ? -1 : 1; 1121 viewMode = this.viewMode; 1122 if (e.ctrlKey) { 1123 viewMode += 2; 1124 } else if (e.shiftKey) { 1125 viewMode += 1; 1126 } 1127 if (viewMode == 4) { 1128 newDate = this.moveYear(this.date, dir); 1129 newViewDate = this.moveYear(this.viewDate, dir); 1130 } else if (viewMode == 3) { 1131 newDate = this.moveMonth(this.date, dir); 1132 newViewDate = this.moveMonth(this.viewDate, dir); 1133 } else if (viewMode == 2) { 1134 newDate = this.moveDate(this.date, dir * 7); 1135 newViewDate = this.moveDate(this.viewDate, dir * 7); 1136 } else if (viewMode == 1) { 1137 if (this.showMeridian) { 1138 newDate = this.moveHour(this.date, dir * 6); 1139 newViewDate = this.moveHour(this.viewDate, dir * 6); 1140 } else { 1141 newDate = this.moveHour(this.date, dir * 4); 1142 newViewDate = this.moveHour(this.viewDate, dir * 4); 1143 } 1144 } else if (viewMode == 0) { 1145 newDate = this.moveMinute(this.date, dir * 4); 1146 newViewDate = this.moveMinute(this.viewDate, dir * 4); 1147 } 1148 if (this.dateWithinRange(newDate)) { 1149 this.date = newDate; 1150 this.viewDate = newViewDate; 1151 this.setValue(); 1152 this.update(); 1153 e.preventDefault(); 1154 dateChanged = true; 1155 } 1156 break; 1157 case 13: // enter 1158 if (this.viewMode != 0) { 1159 var oldViewMode = this.viewMode; 1160 this.showMode(-1); 1161 this.fill(); 1162 if (oldViewMode == this.viewMode && this.autoclose) { 1163 this.hide(); 1164 } 1165 } else { 1166 this.fill(); 1167 if (this.autoclose) { 1168 this.hide(); 1169 } 1170 } 1171 e.preventDefault(); 1172 break; 1173 case 9: // tab 1174 this.hide(); 1175 break; 1176 } 1177 if (dateChanged) { 1178 var element; 1179 if (this.isInput) { 1180 element = this.element; 1181 } else if (this.component) { 1182 element = this.element.find('input'); 1183 } 1184 if (element) { 1185 element.change(); 1186 } 1187 this.element.trigger({ 1188 type: 'changeDate', 1189 date: this.date 1190 }); 1191 } 1192 }, 1193 1194 showMode: function (dir) { 1195 if (dir) { 1196 var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir)); 1197 if (newViewMode >= this.minView && newViewMode <= this.maxView) { 1198 this.element.trigger({ 1199 type: 'changeMode', 1200 date: this.viewDate, 1201 oldViewMode: this.viewMode, 1202 newViewMode: newViewMode 1203 }); 1204 1205 this.viewMode = newViewMode; 1206 } 1207 } 1208 /* 1209 vitalets: fixing bug of very special conditions: 1210 jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover. 1211 Method show() does not set display css correctly and datetimepicker is not shown. 1212 Changed to .css('display', 'block') solve the problem. 1213 See https://github.com/vitalets/x-editable/issues/37 1214 1215 In jquery 1.7.2+ everything works fine. 1216 */ 1217 //this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); 1218 this.picker.find('>div').hide().filter('.datetimepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); 1219 this.updateNavArrows(); 1220 }, 1221 1222 reset: function (e) { 1223 this._setDate(null, 'date'); 1224 } 1225 }; 1226 1227 $.fn.datetimepicker = function (option) { 1228 var args = Array.apply(null, arguments); 1229 args.shift(); 1230 return this.each(function () { 1231 var $this = $(this), 1232 data = $this.data('datetimepicker'), 1233 options = typeof option == 'object' && option; 1234 if (!data) { 1235 $this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults, options)))); 1236 } 1237 if (typeof option == 'string' && typeof data[option] == 'function') { 1238 data[option].apply(data, args); 1239 } 1240 }); 1241 }; 1242 1243 $.fn.datetimepicker.defaults = { 1244 }; 1245 $.fn.datetimepicker.Constructor = Datetimepicker; 1246 var dates = $.fn.datetimepicker.dates = { 1247 en: { 1248 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], 1249 daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], 1250 daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], 1251 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
1251November", "December"], 1252 monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], 1253 meridiem: ["am", "pm"], 1254 suffix: ["st", "nd", "rd", "th"], 1255 today: "Today" 1256 } 1257 }; 1258 1259 var DPGlobal = { 1260 modes: [ 1261 { 1262 clsName: 'minutes', 1263 navFnc: 'Hours', 1264 navStep: 1 1265 }, 1266 { 1267 clsName: 'hours', 1268 navFnc: 'Date', 1269 navStep: 1 1270 }, 1271 { 1272 clsName: 'days', 1273 navFnc: 'Month', 1274 navStep: 1 1275 }, 1276 { 1277 clsName: 'months', 1278 navFnc: 'FullYear', 1279 navStep: 1 1280 }, 1281 { 1282 clsName: 'years', 1283 navFnc: 'FullYear', 1284 navStep: 10 1285 } 1286 ], 1287 isLeapYear: function (year) { 1288 return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) 1289 }, 1290 getDaysInMonth: function (year, month) { 1291 return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] 1292 }, 1293 getDefaultFormat: function (type, field) { 1294 if (type == "standard") { 1295 if (field == 'input') 1296 return 'yyyy-mm-dd hh:ii'; 1297 else 1298 return 'yyyy-mm-dd hh:ii:ss'; 1299 } else if (type == "php") { 1300 if (field == 'input') 1301 return 'Y-m-d H:i'; 1302 else 1303 return 'Y-m-d H:i:s'; 1304 } else { 1305 throw new Error("Invalid format type."); 1306 } 1307 }, 1308 validParts: function (type) { 1309 if (type == "standard") { 1310 return /hh?|HH?|p|P|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g; 1311 } else if (type == "php") { 1312 return /[dDjlNwzFmMnStyYaABgGhHis]/g; 1313 } else { 1314 throw new Error("Invalid format type."); 1315 } 1316 }, 1317 nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g, 1318 parseFormat: function (format, type) { 1319 // IE treats \0 as a string end in inputs (truncating the value), 1320 // so it's a bad format delimiter, anyway 1321 var separators = format.replace(this.validParts(type), '\0').split('\0'), 1322 parts = format.match(this.validParts(type)); 1323 if (!separators || !separators.length || !parts || parts.length == 0) { 1324 throw new Error("Invalid date format."); 1325 } 1326 return {separators: separators, parts: parts}; 1327 }, 1328 parseDate: function (date, format, language, type) { 1329 if (date instanceof Date) { 1330 var dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000); 1331 dateUTC.setMilliseconds(0); 1332 return dateUTC; 1333 } 1334 if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) { 1335 format = this.parseFormat('yyyy-mm-dd', type); 1336 } 1337 if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) { 1338 format = this.parseFormat('yyyy-mm-dd hh:ii', type); 1339 } 1340 if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) { 1341 format = this.parseFormat('yyyy-mm-dd hh:ii:ss', type); 1342 } 1343 if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) { 1344 var part_re = /([-+]\d+)([dmwy])/, 1345 parts = date.match(/([-+]\d+)([dmwy])/g), 1346 part, dir; 1347 date = new Date(); 1348 for (var i = 0; i < parts.length; i++) { 1349 part = part_re.exec(parts[i]); 1350 dir = parseInt(part[1]); 1351 switch (part[2]) { 1352 case 'd': 1353 date.setUTCDate(date.getUTCDate() + dir); 1354 break; 1355 case 'm': 1356 date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir); 1357 break; 1358 case 'w': 1359 date.setUTCDate(date.getUTCDate() + dir * 7); 1360 break; 1361 case 'y': 1362 date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir); 1363 break; 1364 } 1365 } 1366 return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0); 1367 } 1368 var parts = date && date.match(this.nonpunctuation) || [], 1369 date = new Date(0, 0, 0, 0, 0, 0, 0), 1370 parsed = {}, 1371 setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P'], 1372 setters_map = { 1373 hh: function (d, v) { 1374 return d.setUTCHours(v); 1375 }, 1376 h: function (d, v) { 1377 return d.setUTCHours(v); 1378 }, 1379 HH: function (d, v) { 1380 return d.setUTCHours(v == 12 ? 0 : v); 1381 }, 1382 H: function (d, v) { 1383 return d.setUTCHours(v == 12 ? 0 : v); 1384 }, 1385 ii: function (d, v) { 1386 return d.setUTCMinutes(v); 1387 }, 1388 i: function (d, v) { 1389 return d.setUTCMinutes(v); 1390 }, 1391 ss: function (d, v) { 1392 return d.setUTCSeconds(v); 1393 }, 1394 s: function (d, v) { 1395 return d.setUTCSeconds(v); 1396 }, 1397 yyyy: function (d, v) { 1398 return d.setUTCFullYear(v); 1399 }, 1400 yy: function (d, v) { 1401 return d.setUTCFullYear(2000 + v); 1402 }, 1403 m: function (d, v) { 1404 v -= 1; 1405 while (v < 0) v += 12; 1406 v %= 12; 1407 d.setUTCMonth(v); 1408 while (d.getUTCMonth() != v) 1409 d.setUTCDate(d.getUTCDate() - 1); 1410 return d; 1411 }, 1412 d: function (d, v) { 1413 return d.setUTCDate(v); 1414 }, 1415 p: function (d, v) { 1416 return d.setUTCHours(v == 1 ? d.getUTCHours() + 12 : d.getUTCHours()); 1417 } 1418 }, 1419 val, filtered, part; 1420 setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; 1421 setters_map['dd'] = setters_map['d']; 1422 setters_map['P'] = setters_map['p']; 1423 date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); 1424 if (parts.length == format.parts.length) { 1425 for (var i = 0, cnt = format.parts.length; i < cnt; i++) { 1426 val = parseInt(parts[i], 10); 1427 part = format.parts[i]; 1428 if (isNaN(val)) { 1429 switch (part) { 1430 case 'MM': 1431 filtered = $(dates[language].months).filter(function () { 1432 var m = this.slice(0, parts[i].length), 1433 p = parts[i].slice(0, m.length); 1434 return m == p; 1435 }); 1436 val = $.inArray(filtered[0], dates[language].months) + 1; 1437 break; 1438 case 'M': 1439 filtered = $(dates[language].monthsShort).filter(function () { 1440 var m = this.slice(0, parts[i].length), 1441 p = parts[i].slice(0, m.length); 1442 return m == p; 1443 }); 1444 val = $.inArray(filtered[0], dates[language].monthsShort) + 1; 1445 break; 1446 case 'p': 1447 case 'P': 1448 val = $.inArray(parts[i].toLowerCase(), dates[language].meridiem); 1449 break; 1450 } 1451 } 1452 parsed[part] = val; 1453 } 1454 for (var i = 0, s; i < setters_order.length; i++) { 1455 s = setters_order[i]; 1456 if (s in parsed && !isNaN(parsed[s])) 1457 setters_map[s](date, parsed[s]) 1458 } 1459 } 1460 return date; 1461 }, 1462 formatDate: function (date, format, language, type) { 1463 if (date == null) { 1464 return ''; 1465 } 1466 var val; 1467 if (type == 'standard') { 1468 val = { 1469 // year 1470 yy: date.getUTCFullYear().toString().substring(2), 1471 yyyy: date.getUTCFullYear(), 1472 // month 1473 m: date.getUTCMonth() + 1, 1474 M: dates[language].monthsShort[date.getUTCMonth()], 1475 MM: dates[language].months[date.getUTCMonth()], 1476 // day 1477 d: date.getUTCDate(), 1478 D: dates[language].daysShort[date.getUTCDay()], 1479 DD: dates[language].days[date.getUTCDay()], 1480 p: (dates[language].meridiem.length == 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''), 1481 // hour 1482 h: date.getUTCHours(), 1483 // minute 1484 i: date.getUTCMinutes(), 1485 // second 1486 s: date.getUTCSeconds() 1487 }; 1488 1489 if (dates[language].meridiem.length == 2) { 1490 val.H = (val.h % 12 == 0 ? 12 : val.h % 12); 1491 } 1492 else { 1493 val.H = val.h; 1494 } 1495 val.HH = (val.H < 10 ? '0' : '') + val.H; 1496 val.P = val.p.toUpperCase(); 1497 val.hh = (val.h < 10 ? '0' : '') + val.h; 1498 val.ii = (val.i < 10 ? '0' : '') + val.i; 1499 val.ss = (val.s < 10 ? '0' : '') + val.s; 1500 val.dd = (val.d < 10 ? '0' : '') + val.d; 1501 val.mm = (val.m < 10 ? '0' : '') + val.m; 1502 } else if (type == 'php') { 1503 // php format 1504 val = { 1505 // year 1506 y: date.getUTCFullYear().toString().substring(2), 1507 Y: date.getUTCFullYear(), 1508 // month 1509 F: dates[language].months[date.getUTCMonth()], 1510 M: dates[language].monthsShort[date.getUTCMonth()], 1511 n: date.getUTCMonth() + 1, 1512 t: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()), 1513 // day 1514 j: date.getUTCDate(), 1515 l: dates[language].days[date.getUTCDay()], 1516 D: dates[language].daysShort[date.getUTCDay()], 1517 w: date.getUTCDay(), // 0 -> 6 1518 N: (date.getUTCDay() == 0 ? 7 : date.getUTCDay()), // 1 -> 7 1519 S: (date.getUTCDate() % 10 <= dates[language].suffix.length ? dates[language].suffix[date.getUTCDate() % 10 - 1] : ''), 1520 // hour 1521 a: (dates[language].meridiem.length == 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''), 1522 g: (date.getUTCHours() % 12 == 0 ? 12 : date.getUTCHours() % 12), 1523 G: date.getUTCHours(), 1524 // minute 1525 i: date.getUTCMinutes(), 1526 // second 1527 s: date.getUTCSeconds() 1528 }; 1529 val.m = (val.n < 10 ? '0' : '') + val.n; 1530 val.d = (val.j < 10 ? '0' : '') + val.j; 1531 val.A = val.a.toString().toUpperCase(); 1532 val.h = (val.g < 10 ? '0' : '') + val.g; 1533 val.H = (val.G < 10 ? '0' : '') + val.G; 1534 val.i = (val.i < 10 ? '0' : '') + val.i; 1535 val.s = (val.s < 10 ? '0' : '') + val.s; 1536 } else { 1537 throw new Error("Invalid format type."); 1538 } 1539 var date = [], 1540 seps = $.extend([], format.separators); 1541 for (var i = 0, cnt = format.parts.length; i < cnt; i++) { 1542 if (seps.length) { 1543 date.push(seps.shift()); 1544 } 1545 date.push(val[format.parts[i]]); 1546 } 1547 if (seps.length) { 1548 date.push(seps.shift()); 1549 } 1550 return date.join(''); 1551 }, 1552 convertViewMode: function (viewMode) { 1553 switch (viewMode) { 1554 case 4: 1555 case 'decade': 1556 viewMode = 4; 1557 break; 1558 case 3:
1559 case 'year': 1560 viewMode = 3; 1561 break; 1562 case 2: 1563 case 'month': 1564 viewMode = 2; 1565 break; 1566 case 1: 1567 case 'day': 1568 viewMode = 1; 1569 break; 1570 case 0: 1571 case 'hour': 1572 viewMode = 0; 1573 break; 1574 } 1575 1576 return viewMode; 1577 }, 1578 headTemplate: '<thead>' + 1579 '<tr>' + 1580 '<th class="prev"><i class="icon-arrow-left"/></th>' + 1581 '<th colspan="5" class="switch"></th>' + 1582 '<th class="next"><i class="icon-arrow-right"/></th>' + 1583 '</tr>' + 1584 '</thead>', 1585 headTemplateV3: '<thead>' + 1586 '<tr>' + 1587 '<th class="prev"><i class="glyphicon glyphicon-arrow-left"></i> </th>' + 1588 '<th colspan="5" class="switch"></th>' + 1589 '<th class="next"><i class="glyphicon glyphicon-arrow-right"></i> </th>' + 1590 '</tr>' + 1591 '</thead>', 1592 contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>', 1593 footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>' 1594 }; 1595 DPGlobal.template = '<div class="datetimepicker">' + 1596 '<div class="datetimepicker-minutes">' + 1597 '<table class=" table-condensed">' + 1598 DPGlobal.headTemplate + 1599 DPGlobal.contTemplate + 1600 DPGlobal.footTemplate + 1601 '</table>' + 1602 '</div>' + 1603 '<div class="datetimepicker-hours">' + 1604 '<table class=" table-condensed">' + 1605 DPGlobal.headTemplate + 1606 DPGlobal.contTemplate + 1607 DPGlobal.footTemplate + 1608 '</table>' + 1609 '</div>' + 1610 '<div class="datetimepicker-days">' + 1611 '<table class=" table-condensed">' + 1612 DPGlobal.headTemplate + 1613 '<tbody></tbody>' + 1614 DPGlobal.footTemplate + 1615 '</table>' + 1616 '</div>' + 1617 '<div class="datetimepicker-months">' + 1618 '<table class="table-condensed">' + 1619 DPGlobal.headTemplate + 1620 DPGlobal.contTemplate + 1621 DPGlobal.footTemplate + 1622 '</table>' + 1623 '</div>' + 1624 '<div class="datetimepicker-years">' + 1625 '<table class="table-condensed">' + 1626 DPGlobal.headTemplate + 1627 DPGlobal.contTemplate + 1628 DPGlobal.footTemplate + 1629 '</table>' + 1630 '</div>' + 1631 '</div>'; 1632 DPGlobal.templateV3 = '<div class="datetimepicker">' + 1633 '<div class="datetimepicker-minutes">' + 1634 '<table class=" table-condensed">' + 1635 DPGlobal.headTemplateV3 + 1636 DPGlobal.contTemplate + 1637 DPGlobal.footTemplate + 1638 '</table>' + 1639 '</div>' + 1640 '<div class="datetimepicker-hours">' + 1641 '<table class=" table-condensed">' + 1642 DPGlobal.headTemplateV3 + 1643 DPGlobal.contTemplate + 1644 DPGlobal.footTemplate + 1645 '</table>' + 1646 '</div>' + 1647 '<div class="datetimepicker-days">' + 1648 '<table class=" table-condensed">' + 1649 DPGlobal.headTemplateV3 + 1650 '<tbody></tbody>' + 1651 DPGlobal.footTemplate + 1652 '</table>' + 1653 '</div>' + 1654 '<div class="datetimepicker-months">' + 1655 '<table class="table-condensed">' + 1656 DPGlobal.headTemplateV3 + 1657 DPGlobal.contTemplate + 1658 DPGlobal.footTemplate + 1659 '</table>' + 1660 '</div>' + 1661 '<div class="datetimepicker-years">' + 1662 '<table class="table-condensed">' + 1663 DPGlobal.headTemplateV3 + 1664 DPGlobal.contTemplate + 1665 DPGlobal.footTemplate + 1666 '</table>' + 1667 '</div>' + 1668 '</div>'; 1669 $.fn.datetimepicker.DPGlobal = DPGlobal; 1670 1671 /* DATETIMEPICKER NO CONFLICT 1672 * =================== */ 1673 1674 $.fn.datetimepicker.noConflict = function () { 1675 $.fn.datetimepicker = old; 1676 return this; 1677 }; 1678 1679 /* DATETIMEPICKER DATA-API 1680 * ================== */ 1681 1682 $(document).on( 1683 'focus.datetimepicker.data-api click.datetimepicker.data-api', 1684 '[data-provide="datetimepicker"]', 1685 function (e) { 1686 var $this = $(this); 1687 if ($this.data('datetimepicker')) return; 1688 e.preventDefault(); 1689 // component click requires us to explicitly show it 1690 $this.datetimepicker('show'); 1691 } 1692 ); 1693 $(function () { 1694 $('[data-provide="datetimepicker-inline"]').datetimepicker(); 1695 }); 1696 1697}(window.jQuery);
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.