kendo.datetimepicker.js 29.7 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
/** 
 * Kendo UI v2016.1.112 (http://www.telerik.com/kendo-ui)                                                                                                                                               
 * Copyright 2016 Telerik AD. All rights reserved.                                                                                                                                                      
 *                                                                                                                                                                                                      
 * Kendo UI commercial licenses may be obtained at                                                                                                                                                      
 * http://www.telerik.com/purchase/license-agreement/kendo-ui-complete                                                                                                                                  
 * If you do not own a commercial license, this file shall be governed by the trial license terms.                                                                                                      
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       

*/
(function (f, define) {
    define('kendo.datetimepicker', [
        'kendo.datepicker',
        'kendo.timepicker'
    ], f);
}(function () {
    var __meta__ = {
        id: 'datetimepicker',
        name: 'DateTimePicker',
        category: 'web',
        description: 'The DateTimePicker allows the end user to select a value from a calendar or a time drop-down list.',
        depends: [
            'datepicker',
            'timepicker'
        ]
    };
    (function ($, undefined) {
        var kendo = window.kendo, TimeView = kendo.TimeView, parse = kendo.parseDate, activeElement = kendo._activeElement, extractFormat = kendo._extractFormat, calendar = kendo.calendar, isInRange = calendar.isInRange, restrictValue = calendar.restrictValue, isEqualDatePart = calendar.isEqualDatePart, getMilliseconds = TimeView.getMilliseconds, ui = kendo.ui, Widget = ui.Widget, OPEN = 'open', CLOSE = 'close', CHANGE = 'change', ns = '.kendoDateTimePicker', CLICK = 'click' + ns, DISABLED = 'disabled', READONLY = 'readonly', DEFAULT = 'k-state-default', FOCUSED = 'k-state-focused', HOVER = 'k-state-hover', STATEDISABLED = 'k-state-disabled', HOVEREVENTS = 'mouseenter' + ns + ' mouseleave' + ns, MOUSEDOWN = 'mousedown' + ns, MONTH = 'month', SPAN = '<span/>', ARIA_ACTIVEDESCENDANT = 'aria-activedescendant', ARIA_EXPANDED = 'aria-expanded', ARIA_HIDDEN = 'aria-hidden', ARIA_OWNS = 'aria-owns', ARIA_DISABLED = 'aria-disabled', ARIA_READONLY = 'aria-readonly', DATE = Date, MIN = new DATE(1800, 0, 1), MAX = new DATE(2099, 11, 31), dateViewParams = { view: 'date' }, timeViewParams = { view: 'time' }, extend = $.extend;
        var DateTimePicker = Widget.extend({
            init: function (element, options) {
                var that = this, disabled;
                Widget.fn.init.call(that, element, options);
                element = that.element;
                options = that.options;
                options.disableDates = kendo.calendar.disabled(options.disableDates);
                options.min = parse(element.attr('min')) || parse(options.min);
                options.max = parse(element.attr('max')) || parse(options.max);
                normalize(options);
                that._initialOptions = extend({}, options);
                that._wrapper();
                that._views();
                that._icons();
                that._reset();
                that._template();
                try {
                    element[0].setAttribute('type', 'text');
                } catch (e) {
                    element[0].type = 'text';
                }
                element.addClass('k-input').attr({
                    'role': 'combobox',
                    'aria-expanded': false
                });
                that._midnight = that._calculateMidnight(options.min, options.max);
                disabled = element.is('[disabled]') || $(that.element).parents('fieldset').is(':disabled');
                if (disabled) {
                    that.enable(false);
                } else {
                    that.readonly(element.is('[readonly]'));
                }
                that._old = that._update(options.value || that.element.val());
                that._oldText = element.val();
                kendo.notify(that);
            },
            options: {
                name: 'DateTimePicker',
                value: null,
                format: '',
                timeFormat: '',
                culture: '',
                parseFormats: [],
                dates: [],
                min: new DATE(MIN),
                max: new DATE(MAX),
                interval: 30,
                height: 200,
                footer: '',
                start: MONTH,
                depth: MONTH,
                animation: {},
                month: {},
                ARIATemplate: 'Current focused date is #=kendo.toString(data.current, "d")#'
            },
            events: [
                OPEN,
                CLOSE,
                CHANGE
            ],
            setOptions: function (options) {
                var that = this, value = that._value, min, max, currentValue;
                Widget.fn.setOptions.call(that, options);
                options = that.options;
                options.min = min = parse(options.min);
                options.max = max = parse(options.max);
                normalize(options);
                that._midnight = that._calculateMidnight(options.min, options.max);
                currentValue = options.value || that._value || that.dateView._current;
                if (min && !isEqualDatePart(min, currentValue)) {
                    min = new DATE(MIN);
                }
                if (max && !isEqualDatePart(max, currentValue)) {
                    max = new DATE(MAX);
                }
                that.dateView.setOptions(options);
                that.timeView.setOptions(extend({}, options, {
                    format: options.timeFormat,
                    min: min,
                    max: max
                }));
                if (value) {
                    that.element.val(kendo.toString(value, options.format, options.culture));
                    that._updateARIA(value);
                }
            },
            _editable: function (options) {
                var that = this, element = that.element.off(ns), dateIcon = that._dateIcon.off(ns), timeIcon = that._timeIcon.off(ns), wrapper = that._inputWrapper.off(ns), readonly = options.readonly, disable = options.disable;
                if (!readonly && !disable) {
                    wrapper.addClass(DEFAULT).removeClass(STATEDISABLED).on(HOVEREVENTS, that._toggleHover);
                    element.removeAttr(DISABLED).removeAttr(READONLY).attr(ARIA_DISABLED, false).attr(ARIA_READONLY, false).on('keydown' + ns, $.proxy(that._keydown, that)).on('focus' + ns, function () {
                        that._inputWrapper.addClass(FOCUSED);
                    }).on('focusout' + ns, function () {
                        that._inputWrapper.removeClass(FOCUSED);
                        if (element.val() !== that._oldText) {
                            that._change(element.val());
                        }
                        that.close('date');
                        that.close('time');
                    });
                    dateIcon.on(MOUSEDOWN, preventDefault).on(CLICK, function () {
                        that.toggle('date');
                        if (!kendo.support.touch && element[0] !== activeElement()) {
                            element.focus();
                        }
                    });
                    timeIcon.on(MOUSEDOWN, preventDefault).on(CLICK, function () {
                        that.toggle('time');
                        if (!kendo.support.touch && element[0] !== activeElement()) {
                            element.focus();
                        }
                    });
                } else {
                    wrapper.addClass(disable ? STATEDISABLED : DEFAULT).removeClass(disable ? DEFAULT : STATEDISABLED);
                    element.attr(DISABLED, disable).attr(READONLY, readonly).attr(ARIA_DISABLED, disable).attr(ARIA_READONLY, readonly);
                }
            },
            readonly: function (readonly) {
                this._editable({
                    readonly: readonly === undefined ? true : readonly,
                    disable: false
                });
            },
            enable: function (enable) {
                this._editable({
                    readonly: false,
                    disable: !(enable = enable === undefined ? true : enable)
                });
            },
            destroy: function () {
                var that = this;
                Widget.fn.destroy.call(that);
                that.dateView.destroy();
                that.timeView.destroy();
                that.element.off(ns);
                that._dateIcon.off(ns);
                that._timeIcon.off(ns);
                that._inputWrapper.off(ns);
                if (that._form) {
                    that._form.off('reset', that._resetHandler);
                }
            },
            close: function (view) {
                if (view !== 'time') {
                    view = 'date';
                }
                this[view + 'View'].close();
            },
            open: function (view) {
                if (view !== 'time') {
                    view = 'date';
                }
                this[view + 'View'].open();
            },
            min: function (value) {
                return this._option('min', value);
            },
            max: function (value) {
                return this._option('max', value);
            },
            toggle: function (view) {
                var secondView = 'timeView';
                if (view !== 'time') {
                    view = 'date';
                } else {
                    secondView = 'dateView';
                }
                this[view + 'View'].toggle();
                this[secondView].close();
            },
            value: function (value) {
                var that = this;
                if (value === undefined) {
                    return that._value;
                }
                that._old = that._update(value);
                if (that._old === null) {
                    that.element.val('');
                }
                that._oldText = that.element.val();
            },
            _change: function (value) {
                var that = this, oldValue = that.element.val(), dateChanged;
                value = that._update(value);
                dateChanged = +that._old != +value;
                var valueUpdated = dateChanged && !that._typing;
                var textFormatted = oldValue !== that.element.val();
                if (valueUpdated || textFormatted) {
                    that.element.trigger(CHANGE);
                }
                if (dateChanged) {
                    that._old = value;
                    that._oldText = that.element.val();
                    that.trigger(CHANGE);
                }
                that._typing = false;
            },
            _option: function (option, value) {
                var that = this;
                var options = that.options;
                var timeView = that.timeView;
                var timeViewOptions = timeView.options;
                var current = that._value || that._old;
                var minDateEqual;
                var maxDateEqual;
                if (value === undefined) {
                    return options[option];
                }
                value = parse(value, options.parseFormats, options.culture);
                if (!value) {
                    return;
                }
                if (options.min.getTime() === options.max.getTime()) {
                    timeViewOptions.dates = [];
                }
                options[option] = new DATE(value.getTime());
                that.dateView[option](value);
                that._midnight = that._calculateMidnight(options.min, options.max);
                if (current) {
                    minDateEqual = isEqualDatePart(options.min, current);
                    maxDateEqual = isEqualDatePart(options.max, current);
                }
                if (minDateEqual || maxDateEqual) {
                    timeViewOptions[option] = value;
                    if (minDateEqual && !maxDateEqual) {
                        timeViewOptions.max = lastTimeOption(options.interval);
                    }
                    if (maxDateEqual) {
                        if (that._midnight) {
                            timeView.dataBind([MAX]);
                            return;
                        } else if (!minDateEqual) {
                            timeViewOptions.min = MIN;
                        }
                    }
                } else {
                    timeViewOptions.max = MAX;
                    timeViewOptions.min = MIN;
                }
                timeView.bind();
            },
            _toggleHover: function (e) {
                $(e.currentTarget).toggleClass(HOVER, e.type === 'mouseenter');
            },
            _update: function (value) {
                var that = this, options = that.options, min = options.min, max = options.max, dates = options.dates, timeView = that.timeView, current = that._value, date = parse(value, options.parseFormats, options.culture), isSameType = date === null && current === null || date instanceof Date && current instanceof Date, rebind, timeViewOptions, old, skip, formattedValue;
                if (options.disableDates && options.disableDates(date)) {
                    date = null;
                    if (!that._old) {
                        value = null;
                    }
                }
                if (+date === +current && isSameType) {
                    formattedValue = kendo.toString(date, options.format, options.culture);
                    if (formattedValue !== value) {
                        that.element.val(date === null ? value : formattedValue);
                        that.element.trigger(CHANGE);
                    }
                    return date;
                }
                if (date !== null && isEqualDatePart(date, min)) {
                    date = restrictValue(date, min, max);
                } else if (!isInRange(date, min, max)) {
                    date = null;
                }
                that._value = date;
                timeView.value(date);
                that.dateView.value(date);
                if (date) {
                    old = that._old;
                    timeViewOptions = timeView.options;
                    if (dates[0]) {
                        dates = $.grep(dates, function (d) {
                            return isEqualDatePart(date, d);
                        });
                        if (dates[0]) {
                            timeView.dataBind(dates);
                            skip = true;
                        }
                    }
                    if (!skip) {
                        if (isEqualDatePart(date, min)) {
                            timeViewOptions.min = min;
                            timeViewOptions.max = lastTimeOption(options.interval);
                            rebind = true;
                        }
                        if (isEqualDatePart(date, max)) {
                            if (that._midnight) {
                                timeView.dataBind([MAX]);
                                skip = true;
                            } else {
                                timeViewOptions.max = max;
                                if (!rebind) {
                                    timeViewOptions.min = MIN;
                                }
                                rebind = true;
                            }
                        }
                    }
                    if (!skip && (!old && rebind || old && !isEqualDatePart(old, date))) {
                        if (!rebind) {
                            timeViewOptions.max = MAX;
                            timeViewOptions.min = MIN;
                        }
                        timeView.bind();
                    }
                }
                that.element.val(date ? kendo.toString(date, options.format, options.culture) : value);
                that._updateARIA(date);
                return date;
            },
            _keydown: function (e) {
                var that = this, dateView = that.dateView, timeView = that.timeView, value = that.element.val(), isDateViewVisible = dateView.popup.visible();
                if (e.altKey && e.keyCode === kendo.keys.DOWN) {
                    that.toggle(isDateViewVisible ? 'time' : 'date');
                } else if (isDateViewVisible) {
                    dateView.move(e);
                    that._updateARIA(dateView._current);
                } else if (timeView.popup.visible()) {
                    timeView.move(e);
                } else if (e.keyCode === kendo.keys.ENTER && value !== that._oldText) {
                    that._change(value);
                } else {
                    that._typing = true;
                }
            },
            _views: function () {
                var that = this, element = that.element, options = that.options, id = element.attr('id'), dateView, timeView, div, ul, msMin, date;
                that.dateView = dateView = new kendo.DateView(extend({}, options, {
                    id: id,
                    anchor: that.wrapper,
                    change: function () {
                        var value = dateView.calendar.value(), msValue = +value, msMin = +options.min, msMax = +options.max, current;
                        if (msValue === msMin || msValue === msMax) {
                            current = new DATE(+that._value);
                            current.setFullYear(value.getFullYear(), value.getMonth(), value.getDate());
                            if (isInRange(current, msMin, msMax)) {
                                value = current;
                            }
                        }
                        if (that._value) {
                            value = kendo.date.setHours(new Date(value), that._value);
                        }
                        that._change(value);
                        that.close('date');
                    },
                    close: function (e) {
                        if (that.trigger(CLOSE, dateViewParams)) {
                            e.preventDefault();
                        } else {
                            element.attr(ARIA_EXPANDED, false);
                            div.attr(ARIA_HIDDEN, true);
                            if (!timeView.popup.visible()) {
                                element.removeAttr(ARIA_OWNS);
                            }
                        }
                    },
                    open: function (e) {
                        if (that.trigger(OPEN, dateViewParams)) {
                            e.preventDefault();
                        } else {
                            if (element.val() !== that._oldText) {
                                date = parse(element.val(), options.parseFormats, options.culture);
                                that.dateView[date ? 'current' : 'value'](date);
                            }
                            div.attr(ARIA_HIDDEN, false);
                            element.attr(ARIA_EXPANDED, true).attr(ARIA_OWNS, dateView._dateViewID);
                            that._updateARIA(date);
                        }
                    }
                }));
                div = dateView.div;
                msMin = options.min.getTime();
                that.timeView = timeView = new TimeView({
                    id: id,
                    value: options.value,
                    anchor: that.wrapper,
                    animation: options.animation,
                    format: options.timeFormat,
                    culture: options.culture,
                    height: options.height,
                    interval: options.interval,
                    min: new DATE(MIN),
                    max: new DATE(MAX),
                    dates: msMin === options.max.getTime() ? [new Date(msMin)] : [],
                    parseFormats: options.parseFormats,
                    change: function (value, trigger) {
                        value = timeView._parse(value);
                        if (value < options.min) {
                            value = new DATE(+options.min);
                            timeView.options.min = value;
                        } else if (value > options.max) {
                            value = new DATE(+options.max);
                            timeView.options.max = value;
                        }
                        if (trigger) {
                            that._timeSelected = true;
                            that._change(value);
                        } else {
                            element.val(kendo.toString(value, options.format, options.culture));
                            dateView.value(value);
                            that._updateARIA(value);
                        }
                    },
                    close: function (e) {
                        if (that.trigger(CLOSE, timeViewParams)) {
                            e.preventDefault();
                        } else {
                            ul.attr(ARIA_HIDDEN, true);
                            element.attr(ARIA_EXPANDED, false);
                            if (!dateView.popup.visible()) {
                                element.removeAttr(ARIA_OWNS);
                            }
                        }
                    },
                    open: function (e) {
                        timeView._adjustListWidth();
                        if (that.trigger(OPEN, timeViewParams)) {
                            e.preventDefault();
                        } else {
                            if (element.val() !== that._oldText) {
                                date = parse(element.val(), options.parseFormats, options.culture);
                                that.timeView.value(date);
                            }
                            ul.attr(ARIA_HIDDEN, false);
                            element.attr(ARIA_EXPANDED, true).attr(ARIA_OWNS, timeView._timeViewID);
                            timeView.options.active(timeView.current());
                        }
                    },
                    active: function (current) {
                        element.removeAttr(ARIA_ACTIVEDESCENDANT);
                        if (current) {
                            element.attr(ARIA_ACTIVEDESCENDANT, timeView._optionID);
                        }
                    }
                });
                ul = timeView.ul;
            },
            _icons: function () {
                var that = this, element = that.element, icons;
                icons = element.next('span.k-select');
                if (!icons[0]) {
                    icons = $('<span unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-calendar">select</span><span unselectable="on" class="k-icon k-i-clock">select</span></span>').insertAfter(element);
                }
                icons = icons.children();
                that._dateIcon = icons.eq(0).attr({
                    'role': 'button',
                    'aria-controls': that.dateView._dateViewID
                });
                that._timeIcon = icons.eq(1).attr({
                    'role': 'button',
                    'aria-controls': that.timeView._timeViewID
                });
            },
            _wrapper: function () {
                var that = this, element = that.element, wrapper;
                wrapper = element.parents('.k-datetimepicker');
                if (!wrapper[0]) {
                    wrapper = element.wrap(SPAN).parent().addClass('k-picker-wrap k-state-default');
                    wrapper = wrapper.wrap(SPAN).parent();
                }
                wrapper[0].style.cssText = element[0].style.cssText;
                element.css({
                    width: '100%',
                    height: element[0].style.height
                });
                that.wrapper = wrapper.addClass('k-widget k-datetimepicker k-header').addClass(element[0].className);
                that._inputWrapper = $(wrapper[0].firstChild);
            },
            _reset: function () {
                var that = this, element = that.element, formId = element.attr('form'), form = formId ? $('#' + formId) : element.closest('form');
                if (form[0]) {
                    that._resetHandler = function () {
                        that.value(element[0].defaultValue);
                        that.max(that._initialOptions.max);
                        that.min(that._initialOptions.min);
                    };
                    that._form = form.on('reset', that._resetHandler);
                }
            },
            _template: function () {
                this._ariaTemplate = kendo.template(this.options.ARIATemplate);
            },
            _calculateMidnight: function (min, max) {
                return getMilliseconds(min) + getMilliseconds(max) === 0;
            },
            _updateARIA: function (date) {
                var cell;
                var that = this;
                var calendar = that.dateView.calendar;
                that.element.removeAttr(ARIA_ACTIVEDESCENDANT);
                if (calendar) {
                    cell = calendar._cell;
                    cell.attr('aria-label', that._ariaTemplate({ current: date || calendar.current() }));
                    that.element.attr(ARIA_ACTIVEDESCENDANT, cell.attr('id'));
                }
            }
        });
        function lastTimeOption(interval) {
            var date = new Date(2100, 0, 1);
            date.setMinutes(-interval);
            return date;
        }
        function preventDefault(e) {
            e.preventDefault();
        }
        function normalize(options) {
            var patterns = kendo.getCulture(options.culture).calendars.standard.patterns, parseFormats = !options.parseFormats.length, timeFormat;
            options.format = extractFormat(options.format || patterns.g);
            options.timeFormat = timeFormat = extractFormat(options.timeFormat || patterns.t);
            kendo.DateView.normalize(options);
            if (parseFormats) {
                options.parseFormats.unshift('yyyy-MM-ddTHH:mm:ss');
            }
            if ($.inArray(timeFormat, options.parseFormats) === -1) {
                options.parseFormats.splice(1, 0, timeFormat);
            }
        }
        ui.plugin(DateTimePicker);
    }(window.kendo.jQuery));
    return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
    (a3 || a2)();
}));