/*! * TOAST UI Date Picker * @version 4.3.1 * @author NHN. FE Development Lab * @license MIT */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("tui-time-picker")); else if(typeof define === 'function' && define.amd) define(["tui-time-picker"], factory); else if(typeof exports === 'object') exports["DatePicker"] = factory(require("tui-time-picker")); else root["tui"] = root["tui"] || {}, root["tui"]["DatePicker"] = factory(root["tui"]["TimePicker"]); })(window, function(__WEBPACK_EXTERNAL_MODULE__43__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "dist"; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 34); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview * This module provides a function to make a constructor * that can inherit from the other constructors like the CLASS easily. * @author NHN FE Development Lab */ var inherit = __webpack_require__(35); var extend = __webpack_require__(7); /** * @module defineClass */ /** * Help a constructor to be defined and to inherit from the other constructors * @param {*} [parent] Parent constructor * @param {Object} props Members of constructor * @param {Function} props.init Initialization method * @param {Object} [props.static] Static members of constructor * @returns {*} Constructor * @memberof module:defineClass * @example * var defineClass = require('tui-code-snippet/defineClass/defineClass'); // node, commonjs * * //-- #2. Use property --// * var Parent = defineClass({ * init: function() { // constuructor * this.name = 'made by def'; * }, * method: function() { * // ... * }, * static: { * staticMethod: function() { * // ... * } * } * }); * * var Child = defineClass(Parent, { * childMethod: function() {} * }); * * Parent.staticMethod(); * * var parentInstance = new Parent(); * console.log(parentInstance.name); //made by def * parentInstance.staticMethod(); // Error * * var childInstance = new Child(); * childInstance.method(); * childInstance.childMethod(); */ function defineClass(parent, props) { var obj; if (!props) { props = parent; parent = null; } obj = props.init || function() {}; if (parent) { inherit(obj, parent); } if (props.hasOwnProperty('static')) { extend(obj, props['static']); delete props['static']; } extend(obj.prototype, props); return obj; } module.exports = defineClass; /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Constants of date-picker * @author NHN. FE Development Lab */ module.exports = { TYPE_DATE: 'date', TYPE_MONTH: 'month', TYPE_YEAR: 'year', TYPE_HOUR: 'hour', TYPE_MINUTE: 'minute', TYPE_MERIDIEM: 'meridiem', MIN_DATE: new Date(1900, 0, 1), MAX_DATE: new Date(2999, 11, 31), DEFAULT_LANGUAGE_TYPE: 'en', CLASS_NAME_SELECTED: 'tui-is-selected', CLASS_NAME_PREV_MONTH_BTN: 'tui-calendar-btn-prev-month', CLASS_NAME_PREV_YEAR_BTN: 'tui-calendar-btn-prev-year', CLASS_NAME_NEXT_YEAR_BTN: 'tui-calendar-btn-next-year', CLASS_NAME_NEXT_MONTH_BTN: 'tui-calendar-btn-next-month', CLASS_NAME_TITLE_TODAY: 'tui-calendar-title-today', DEFAULT_WEEK_START_DAY: 'Sun', WEEK_START_DAY_MAP: { sun: 0, mon: 1, tue: 2, wed: 3, thu: 4, fri: 5, sat: 6 } }; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Execute the provided callback once for each element present in the array(or Array-like object) in ascending order. * @author NHN FE Development Lab */ /** * Execute the provided callback once for each element present * in the array(or Array-like object) in ascending order. * If the callback function returns false, the loop will be stopped. * Callback function(iteratee) is invoked with three arguments: * 1) The value of the element * 2) The index of the element * 3) The array(or Array-like object) being traversed * @param {Array|Arguments|NodeList} arr The array(or Array-like object) that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @memberof module:collection * @example * var forEachArray = require('tui-code-snippet/collection/forEachArray'); // node, commonjs * * var sum = 0; * * forEachArray([1,2,3], function(value){ * sum += value; * }); * alert(sum); // 6 */ function forEachArray(arr, iteratee, context) { var index = 0; var len = arr.length; context = context || null; for (; index < len; index += 1) { if (iteratee.call(context, arr[index], index, arr) === false) { break; } } } module.exports = forEachArray; /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* eslint-disable complexity */ /** * @fileoverview Returns the first index at which a given element can be found in the array. * @author NHN FE Development Lab */ var isArray = __webpack_require__(6); /** * @module array */ /** * Returns the first index at which a given element can be found in the array * from start index(default 0), or -1 if it is not present. * It compares searchElement to elements of the Array using strict equality * (the same method used by the ===, or triple-equals, operator). * @param {*} searchElement Element to locate in the array * @param {Array} array Array that will be traversed. * @param {number} startIndex Start index in array for searching (default 0) * @returns {number} the First index at which a given element, or -1 if it is not present * @memberof module:array * @example * var inArray = require('tui-code-snippet/array/inArray'); // node, commonjs * * var arr = ['one', 'two', 'three', 'four']; * var idx1 = inArray('one', arr, 3); // -1 * var idx2 = inArray('one', arr); // 0 */ function inArray(searchElement, array, startIndex) { var i; var length; startIndex = startIndex || 0; if (!isArray(array)) { return -1; } if (Array.prototype.indexOf) { return Array.prototype.indexOf.call(array, searchElement, startIndex); } length = array.length; for (i = startIndex; startIndex >= 0 && i < length; i += 1) { if (array[i] === searchElement) { return i; } } return -1; } module.exports = inArray; /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Utils for Datepicker component * @author NHN. FE Development Lab */ var forEachArray = __webpack_require__(2); var isHTMLNode = __webpack_require__(46); var sendHostname = __webpack_require__(47); var currentId = 0; var utils = { /** * Get a target element * @param {Event} ev Event object * @returns {HTMLElement} An event target element */ getTarget: function(ev) { return ev.target || ev.srcElement; }, /** * Return the same element with an element or a matched element searched by a selector. * @param {HTMLElement|string} param HTMLElement or selector * @returns {HTMLElement} A matched element */ getElement: function(param) { return isHTMLNode(param) ? param : document.querySelector(param); }, /** * Get a selector of the element. * @param {HTMLElement} elem An element * @returns {string} */ getSelector: function(elem) { var selector = ''; if (elem.id) { selector = '#' + elem.id; } else if (elem.className) { selector = '.' + elem.className.split(' ')[0]; } return selector; }, /** * Create an unique id. * @returns {number} */ generateId: function() { currentId += 1; return currentId; }, /** * Create a new array with all elements that pass the test implemented by the provided function. * @param {Array} arr - Array that will be traversed * @param {function} iteratee - iteratee callback function * @returns {Array} */ filter: function(arr, iteratee) { var result = []; forEachArray(arr, function(item) { if (iteratee(item)) { result.push(item); } }); return result; }, /** * Send hostname for GA * @ignore */ sendHostName: function() { sendHostname('date-picker', 'UA-129987462-1'); } }; module.exports = utils; /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Utils for DatePicker component * @author NHN. FE dev Lab. */ var isDate = __webpack_require__(28); var isNumber = __webpack_require__(15); var constants = __webpack_require__(1); var TYPE_DATE = constants.TYPE_DATE; var TYPE_MONTH = constants.TYPE_MONTH; var TYPE_YEAR = constants.TYPE_YEAR; /** * Utils of calendar * @namespace dateUtil * @ignore */ var utils = { /** * Get weeks count by paramenter * @param {number} year A year * @param {number} month A month * @returns {number} Weeks count (4~6) **/ getWeeksCount: function(year, month) { var firstDay = utils.getFirstDay(year, month), lastDate = utils.getLastDayInMonth(year, month); return Math.ceil((firstDay + lastDate) / 7); }, /** * @param {Date} date - Date instance * @returns {boolean} */ isValidDate: function(date) { return isDate(date) && !isNaN(date.getTime()); }, /** * Get which day is first by parameters that include year and month information. * @param {number} year A year * @param {number} month A month * @returns {number} (0~6) */ getFirstDay: function(year, month) { return new Date(year, month - 1, 1).getDay(); }, /** * Get timestamp of the first day. * @param {number} year A year * @param {number} month A month * @returns {number} timestamp */ getFirstDayTimestamp: function(year, month) { return new Date(year, month, 1).getTime(); }, /** * Get last date by parameters that include year and month information. * @param {number} year A year * @param {number} month A month * @returns {number} (1~31) */ getLastDayInMonth: function(year, month) { return new Date(year, month, 0).getDate(); }, /** * Chagne number 0~9 to '00~09' * @param {number} number number * @returns {string} * @example * dateUtil.prependLeadingZero(0); // '00' * dateUtil.prependLeadingZero(9); // '09' * dateUtil.prependLeadingZero(12); // '12' */ prependLeadingZero: function(number) { var prefix = ''; if (number < 10) { prefix = '0'; } return prefix + number; }, /** * Get meridiem hour * @param {number} hour - Original hour * @returns {number} Converted meridiem hour */ getMeridiemHour: function(hour) { hour %= 12; if (hour === 0) { hour = 12; } return hour; }, /** * Returns number or default * @param {*} any - Any value * @param {number} defaultNumber - Default number * @throws Will throw an error if the defaultNumber is invalid. * @returns {number} */ getSafeNumber: function(any, defaultNumber) { if (isNaN(defaultNumber) || !isNumber(defaultNumber)) { throw Error('The defaultNumber must be a valid number.'); } if (isNaN(any)) { return defaultNumber; } return Number(any); }, /** * Return date of the week * @param {number} year - Year * @param {number} month - Month * @param {number} weekNumber - Week number (0~5) * @param {number} dayNumber - Day number (0: sunday, 1: monday, ....) * @returns {number} */ getDateOfWeek: function(year, month, weekNumber, dayNumber) { var firstDayOfMonth = new Date(year, month - 1).getDay(); var dateOffset = firstDayOfMonth - dayNumber - 1; return new Date(year, month - 1, weekNumber * 7 - dateOffset); }, /** * Returns range arr * @param {number} start - Start value * @param {number} end - End value * @returns {Array} */ getRangeArr: function(start, end) { var arr = []; var i; if (start > end) { for (i = end; i >= start; i -= 1) { arr.push(i); } } else { for (i = start; i <= end; i += 1) { arr.push(i); } } return arr; }, /** * Returns cloned date with the start of a unit of time * @param {Date|number} date - Original date * @param {string} [type = TYPE_DATE] - Unit type * @throws {Error} * @returns {Date} */ cloneWithStartOf: function(date, type) { type = type || TYPE_DATE; date = new Date(date); // Does not consider time-level yet. date.setHours(0, 0, 0, 0); switch (type) { case TYPE_DATE: break; case TYPE_MONTH: date.setDate(1); break; case TYPE_YEAR: date.setMonth(0, 1); break; default: throw Error('Unsupported type: ' + type); } return date; }, /** * Returns cloned date with the end of a unit of time * @param {Date|number} date - Original date * @param {string} [type = TYPE_DATE] - Unit type * @throws {Error} * @returns {Date} */ cloneWithEndOf: function(date, type) { type = type || TYPE_DATE; date = new Date(date); // Does not consider time-level yet. date.setHours(23, 59, 59, 999); switch (type) { case TYPE_DATE: break; case TYPE_MONTH: date.setMonth(date.getMonth() + 1, 0); break; case TYPE_YEAR: date.setMonth(11, 31); break; default: throw Error('Unsupported type: ' + type); } return date; }, /** * Compare two dates * @param {Date|number} dateA - Date * @param {Date|number} dateB - Date * @param {string} [cmpLevel] - Comparing level * @returns {number} */ compare: function(dateA, dateB, cmpLevel) { var aTimestamp, bTimestamp; if (!(utils.isValidDate(dateA) && utils.isValidDate(dateB))) { return NaN; } if (!cmpLevel) { aTimestamp = dateA.getTime(); bTimestamp = dateB.getTime(); } else { aTimestamp = utils.cloneWithStartOf(dateA, cmpLevel).getTime(); bTimestamp = utils.cloneWithStartOf(dateB, cmpLevel).getTime(); } if (aTimestamp > bTimestamp) { return 1; } return aTimestamp === bTimestamp ? 0 : -1; }, /** * Returns whether two dates are same * @param {Date|number} dateA - Date * @param {Date|number} dateB - Date * @param {string} [cmpLevel] - Comparing level * @returns {boolean} */ isSame: function(dateA, dateB, cmpLevel) { return utils.compare(dateA, dateB, cmpLevel) === 0; }, /** * Returns whether the target is in range * @param {Date|number} start - Range start * @param {Date|number} end - Range end * @param {Date|number} target - Target * @param {string} [cmpLevel = TYPE_DATE] - Comparing level * @returns {boolean} */ inRange: function(start, end, target, cmpLevel) { return utils.compare(start, target, cmpLevel) < 1 && utils.compare(end, target, cmpLevel) > -1; } }; module.exports = utils; /***/ }), /* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is an instance of Array or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is an instance of Array or not. * If the given variable is an instance of Array, return true. * @param {*} obj - Target for checking * @returns {boolean} Is array instance? * @memberof module:type */ function isArray(obj) { return obj instanceof Array; } module.exports = isArray; /***/ }), /* 7 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Extend the target object from other objects. * @author NHN FE Development Lab */ /** * @module object */ /** * Extend the target object from other objects. * @param {object} target - Object that will be extended * @param {...object} objects - Objects as sources * @returns {object} Extended object * @memberof module:object */ function extend(target, objects) { // eslint-disable-line no-unused-vars var hasOwnProp = Object.prototype.hasOwnProperty; var source, prop, i, len; for (i = 1, len = arguments.length; i < len; i += 1) { source = arguments[i]; for (prop in source) { if (hasOwnProp.call(source, prop)) { target[prop] = source[prop]; } } } return target; } module.exports = extend; /***/ }), /* 8 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview This module provides some functions for custom events. And it is implemented in the observer design pattern. * @author NHN FE Development Lab */ var extend = __webpack_require__(7); var isExisty = __webpack_require__(37); var isString = __webpack_require__(13); var isObject = __webpack_require__(22); var isArray = __webpack_require__(6); var isFunction = __webpack_require__(39); var forEach = __webpack_require__(9); var R_EVENTNAME_SPLIT = /\s+/g; /** * @class * @example * // node, commonjs * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); */ function CustomEvents() { /** * @type {HandlerItem[]} */ this.events = null; /** * only for checking specific context event was binded * @type {object[]} */ this.contexts = null; } /** * Mixin custom events feature to specific constructor * @param {function} func - constructor * @example * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); // node, commonjs * * var model; * function Model() { * this.name = ''; * } * CustomEvents.mixin(Model); * * model = new Model(); * model.on('change', function() { this.name = 'model'; }, this); * model.fire('change'); * alert(model.name); // 'model'; */ CustomEvents.mixin = function(func) { extend(func.prototype, CustomEvents.prototype); }; /** * Get HandlerItem object * @param {function} handler - handler function * @param {object} [context] - context for handler * @returns {HandlerItem} HandlerItem object * @private */ CustomEvents.prototype._getHandlerItem = function(handler, context) { var item = {handler: handler}; if (context) { item.context = context; } return item; }; /** * Get event object safely * @param {string} [eventName] - create sub event map if not exist. * @returns {(object|array)} event object. if you supplied `eventName` * parameter then make new array and return it * @private */ CustomEvents.prototype._safeEvent = function(eventName) { var events = this.events; var byName; if (!events) { events = this.events = {}; } if (eventName) { byName = events[eventName]; if (!byName) { byName = []; events[eventName] = byName; } events = byName; } return events; }; /** * Get context array safely * @returns {array} context array * @private */ CustomEvents.prototype._safeContext = function() { var context = this.contexts; if (!context) { context = this.contexts = []; } return context; }; /** * Get index of context * @param {object} ctx - context that used for bind custom event * @returns {number} index of context * @private */ CustomEvents.prototype._indexOfContext = function(ctx) { var context = this._safeContext(); var index = 0; while (context[index]) { if (ctx === context[index][0]) { return index; } index += 1; } return -1; }; /** * Memorize supplied context for recognize supplied object is context or * name: handler pair object when off() * @param {object} ctx - context object to memorize * @private */ CustomEvents.prototype._memorizeContext = function(ctx) { var context, index; if (!isExisty(ctx)) { return; } context = this._safeContext(); index = this._indexOfContext(ctx); if (index > -1) { context[index][1] += 1; } else { context.push([ctx, 1]); } }; /** * Forget supplied context object * @param {object} ctx - context object to forget * @private */ CustomEvents.prototype._forgetContext = function(ctx) { var context, contextIndex; if (!isExisty(ctx)) { return; } context = this._safeContext(); contextIndex = this._indexOfContext(ctx); if (contextIndex > -1) { context[contextIndex][1] -= 1; if (context[contextIndex][1] <= 0) { context.splice(contextIndex, 1); } } }; /** * Bind event handler * @param {(string|{name:string, handler:function})} eventName - custom * event name or an object {eventName: handler} * @param {(function|object)} [handler] - handler function or context * @param {object} [context] - context for binding * @private */ CustomEvents.prototype._bindEvent = function(eventName, handler, context) { var events = this._safeEvent(eventName); this._memorizeContext(context); events.push(this._getHandlerItem(handler, context)); }; /** * Bind event handlers * @param {(string|{name:string, handler:function})} eventName - custom * event name or an object {eventName: handler} * @param {(function|object)} [handler] - handler function or context * @param {object} [context] - context for binding * //-- #1. Get Module --// * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); // node, commonjs * * //-- #2. Use method --// * // # 2.1 Basic Usage * CustomEvents.on('onload', handler); * * // # 2.2 With context * CustomEvents.on('onload', handler, myObj); * * // # 2.3 Bind by object that name, handler pairs * CustomEvents.on({ * 'play': handler, * 'pause': handler2 * }); * * // # 2.4 Bind by object that name, handler pairs with context object * CustomEvents.on({ * 'play': handler * }, myObj); */ CustomEvents.prototype.on = function(eventName, handler, context) { var self = this; if (isString(eventName)) { // [syntax 1, 2] eventName = eventName.split(R_EVENTNAME_SPLIT); forEach(eventName, function(name) { self._bindEvent(name, handler, context); }); } else if (isObject(eventName)) { // [syntax 3, 4] context = handler; forEach(eventName, function(func, name) { self.on(name, func, context); }); } }; /** * Bind one-shot event handlers * @param {(string|{name:string,handler:function})} eventName - custom * event name or an object {eventName: handler} * @param {function|object} [handler] - handler function or context * @param {object} [context] - context for binding */ CustomEvents.prototype.once = function(eventName, handler, context) { var self = this; if (isObject(eventName)) { context = handler; forEach(eventName, function(func, name) { self.once(name, func, context); }); return; } function onceHandler() { // eslint-disable-line require-jsdoc handler.apply(context, arguments); self.off(eventName, onceHandler, context); } this.on(eventName, onceHandler, context); }; /** * Splice supplied array by callback result * @param {array} arr - array to splice * @param {function} predicate - function return boolean * @private */ CustomEvents.prototype._spliceMatches = function(arr, predicate) { var i = 0; var len; if (!isArray(arr)) { return; } for (len = arr.length; i < len; i += 1) { if (predicate(arr[i]) === true) { arr.splice(i, 1); len -= 1; i -= 1; } } }; /** * Get matcher for unbind specific handler events * @param {function} handler - handler function * @returns {function} handler matcher * @private */ CustomEvents.prototype._matchHandler = function(handler) { var self = this; return function(item) { var needRemove = handler === item.handler; if (needRemove) { self._forgetContext(item.context); } return needRemove; }; }; /** * Get matcher for unbind specific context events * @param {object} context - context * @returns {function} object matcher * @private */ CustomEvents.prototype._matchContext = function(context) { var self = this; return function(item) { var needRemove = context === item.context; if (needRemove) { self._forgetContext(item.context); } return needRemove; }; }; /** * Get matcher for unbind specific hander, context pair events * @param {function} handler - handler function * @param {object} context - context * @returns {function} handler, context matcher * @private */ CustomEvents.prototype._matchHandlerAndContext = function(handler, context) { var self = this; return function(item) { var matchHandler = (handler === item.handler); var matchContext = (context === item.context); var needRemove = (matchHandler && matchContext); if (needRemove) { self._forgetContext(item.context); } return needRemove; }; }; /** * Unbind event by event name * @param {string} eventName - custom event name to unbind * @param {function} [handler] - handler function * @private */ CustomEvents.prototype._offByEventName = function(eventName, handler) { var self = this; var andByHandler = isFunction(handler); var matchHandler = self._matchHandler(handler); eventName = eventName.split(R_EVENTNAME_SPLIT); forEach(eventName, function(name) { var handlerItems = self._safeEvent(name); if (andByHandler) { self._spliceMatches(handlerItems, matchHandler); } else { forEach(handlerItems, function(item) { self._forgetContext(item.context); }); self.events[name] = []; } }); }; /** * Unbind event by handler function * @param {function} handler - handler function * @private */ CustomEvents.prototype._offByHandler = function(handler) { var self = this; var matchHandler = this._matchHandler(handler); forEach(this._safeEvent(), function(handlerItems) { self._spliceMatches(handlerItems, matchHandler); }); }; /** * Unbind event by object(name: handler pair object or context object) * @param {object} obj - context or {name: handler} pair object * @param {function} handler - handler function * @private */ CustomEvents.prototype._offByObject = function(obj, handler) { var self = this; var matchFunc; if (this._indexOfContext(obj) < 0) { forEach(obj, function(func, name) { self.off(name, func); }); } else if (isString(handler)) { matchFunc = this._matchContext(obj); self._spliceMatches(this._safeEvent(handler), matchFunc); } else if (isFunction(handler)) { matchFunc = this._matchHandlerAndContext(handler, obj); forEach(this._safeEvent(), function(handlerItems) { self._spliceMatches(handlerItems, matchFunc); }); } else { matchFunc = this._matchContext(obj); forEach(this._safeEvent(), function(handlerItems) { self._spliceMatches(handlerItems, matchFunc); }); } }; /** * Unbind custom events * @param {(string|object|function)} eventName - event name or context or * {name: handler} pair object or handler function * @param {(function)} handler - handler function * @example * //-- #1. Get Module --// * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); // node, commonjs * * //-- #2. Use method --// * // # 2.1 off by event name * CustomEvents.off('onload'); * * // # 2.2 off by event name and handler * CustomEvents.off('play', handler); * * // # 2.3 off by handler * CustomEvents.off(handler); * * // # 2.4 off by context * CustomEvents.off(myObj); * * // # 2.5 off by context and handler * CustomEvents.off(myObj, handler); * * // # 2.6 off by context and event name * CustomEvents.off(myObj, 'onload'); * * // # 2.7 off by an Object. that is {eventName: handler} * CustomEvents.off({ * 'play': handler, * 'pause': handler2 * }); * * // # 2.8 off the all events * CustomEvents.off(); */ CustomEvents.prototype.off = function(eventName, handler) { if (isString(eventName)) { // [syntax 1, 2] this._offByEventName(eventName, handler); } else if (!arguments.length) { // [syntax 8] this.events = {}; this.contexts = []; } else if (isFunction(eventName)) { // [syntax 3] this._offByHandler(eventName); } else if (isObject(eventName)) { // [syntax 4, 5, 6] this._offByObject(eventName, handler); } }; /** * Fire custom event * @param {string} eventName - name of custom event */ CustomEvents.prototype.fire = function(eventName) { // eslint-disable-line this.invoke.apply(this, arguments); }; /** * Fire a event and returns the result of operation 'boolean AND' with all * listener's results. * * So, It is different from {@link CustomEvents#fire}. * * In service code, use this as a before event in component level usually * for notifying that the event is cancelable. * @param {string} eventName - Custom event name * @param {...*} data - Data for event * @returns {boolean} The result of operation 'boolean AND' * @example * var map = new Map(); * map.on({ * 'beforeZoom': function() { * // It should cancel the 'zoom' event by some conditions. * if (that.disabled && this.getState()) { * return false; * } * return true; * } * }); * * if (this.invoke('beforeZoom')) { // check the result of 'beforeZoom' * // if true, * // doSomething * } */ CustomEvents.prototype.invoke = function(eventName) { var events, args, index, item; if (!this.hasListener(eventName)) { return true; } events = this._safeEvent(eventName); args = Array.prototype.slice.call(arguments, 1); index = 0; while (events[index]) { item = events[index]; if (item.handler.apply(item.context, args) === false) { return false; } index += 1; } return true; }; /** * Return whether at least one of the handlers is registered in the given * event name. * @param {string} eventName - Custom event name * @returns {boolean} Is there at least one handler in event name? */ CustomEvents.prototype.hasListener = function(eventName) { return this.getListenerLength(eventName) > 0; }; /** * Return a count of events registered. * @param {string} eventName - Custom event name * @returns {number} number of event */ CustomEvents.prototype.getListenerLength = function(eventName) { var events = this._safeEvent(eventName); return events.length; }; module.exports = CustomEvents; /***/ }), /* 9 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Execute the provided callback once for each property of object(or element of array) which actually exist. * @author NHN FE Development Lab */ var isArray = __webpack_require__(6); var forEachArray = __webpack_require__(2); var forEachOwnProperties = __webpack_require__(23); /** * @module collection */ /** * Execute the provided callback once for each property of object(or element of array) which actually exist. * If the object is Array-like object(ex-arguments object), It needs to transform to Array.(see 'ex2' of example). * If the callback function returns false, the loop will be stopped. * Callback function(iteratee) is invoked with three arguments: * 1) The value of the property(or The value of the element) * 2) The name of the property(or The index of the element) * 3) The object being traversed * @param {Object} obj The object that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @memberof module:collection * @example * var forEach = require('tui-code-snippet/collection/forEach'); // node, commonjs * * var sum = 0; * * forEach([1,2,3], function(value){ * sum += value; * }); * alert(sum); // 6 * * // In case of Array-like object * var array = Array.prototype.slice.call(arrayLike); // change to array * forEach(array, function(value){ * sum += value; * }); */ function forEach(obj, iteratee, context) { if (isArray(obj)) { forEachArray(obj, iteratee, context); } else { forEachOwnProperties(obj, iteratee, context); } } module.exports = forEach; /***/ }), /* 10 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Default locale texts * @author NHN. FE Development Lab */ module.exports = { en: { titles: { DD: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], D: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], MMM: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], MMMM: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] }, titleFormat: 'MMMM yyyy', todayFormat: 'To\\d\\ay: DD, MMMM d, yyyy', time: 'Time', date: 'Date' }, ko: { titles: { DD: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'], D: ['일', '월', '화', '수', '목', '금', '토'], MMM: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'], MMMM: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'] }, titleFormat: 'yyyy.MM', todayFormat: '오늘: yyyy.MM.dd (D)', date: '날짜', time: '시간' } }; /***/ }), /* 11 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Convert text by binding expressions with context. * @author NHN FE Development Lab */ var inArray = __webpack_require__(3); var forEach = __webpack_require__(9); var isArray = __webpack_require__(6); var isString = __webpack_require__(13); var extend = __webpack_require__(7); // IE8 does not support capture groups. var EXPRESSION_REGEXP = /{{\s?|\s?}}/g; var BRACKET_NOTATION_REGEXP = /^[a-zA-Z0-9_@]+\[[a-zA-Z0-9_@"']+\]$/; var BRACKET_REGEXP = /\[\s?|\s?\]/; var DOT_NOTATION_REGEXP = /^[a-zA-Z_]+\.[a-zA-Z_]+$/; var DOT_REGEXP = /\./; var STRING_NOTATION_REGEXP = /^["']\w+["']$/; var STRING_REGEXP = /"|'/g; var NUMBER_REGEXP = /^-?\d+\.?\d*$/; var EXPRESSION_INTERVAL = 2; var BLOCK_HELPERS = { 'if': handleIf, 'each': handleEach, 'with': handleWith }; var isValidSplit = 'a'.split(/a/).length === 3; /** * Split by RegExp. (Polyfill for IE8) * @param {string} text - text to be splitted\ * @param {RegExp} regexp - regular expression * @returns {Array.} */ var splitByRegExp = (function() { if (isValidSplit) { return function(text, regexp) { return text.split(regexp); }; } return function(text, regexp) { var result = []; var prevIndex = 0; var match, index; if (!regexp.global) { regexp = new RegExp(regexp, 'g'); } match = regexp.exec(text); while (match !== null) { index = match.index; result.push(text.slice(prevIndex, index)); prevIndex = index + match[0].length; match = regexp.exec(text); } result.push(text.slice(prevIndex)); return result; }; })(); /** * Find value in the context by an expression. * @param {string} exp - an expression * @param {object} context - context * @returns {*} * @private */ // eslint-disable-next-line complexity function getValueFromContext(exp, context) { var splitedExps; var value = context[exp]; if (exp === 'true') { value = true; } else if (exp === 'false') { value = false; } else if (STRING_NOTATION_REGEXP.test(exp)) { value = exp.replace(STRING_REGEXP, ''); } else if (BRACKET_NOTATION_REGEXP.test(exp)) { splitedExps = exp.split(BRACKET_REGEXP); value = getValueFromContext(splitedExps[0], context)[getValueFromContext(splitedExps[1], context)]; } else if (DOT_NOTATION_REGEXP.test(exp)) { splitedExps = exp.split(DOT_REGEXP); value = getValueFromContext(splitedExps[0], context)[splitedExps[1]]; } else if (NUMBER_REGEXP.test(exp)) { value = parseFloat(exp); } return value; } /** * Extract elseif and else expressions. * @param {Array.} ifExps - args of if expression * @param {Array.} sourcesInsideBlock - sources inside if block * @returns {object} - exps: expressions of if, elseif, and else / sourcesInsideIf: sources inside if, elseif, and else block. * @private */ function extractElseif(ifExps, sourcesInsideBlock) { var exps = [ifExps]; var sourcesInsideIf = []; var otherIfCount = 0; var start = 0; // eslint-disable-next-line complexity forEach(sourcesInsideBlock, function(source, index) { if (source.indexOf('if') === 0) { otherIfCount += 1; } else if (source === '/if') { otherIfCount -= 1; } else if (!otherIfCount && (source.indexOf('elseif') === 0 || source === 'else')) { exps.push(source === 'else' ? ['true'] : source.split(' ').slice(1)); sourcesInsideIf.push(sourcesInsideBlock.slice(start, index)); start = index + 1; } }); sourcesInsideIf.push(sourcesInsideBlock.slice(start)); return { exps: exps, sourcesInsideIf: sourcesInsideIf }; } /** * Helper function for "if". * @param {Array.} exps - array of expressions split by spaces * @param {Array.} sourcesInsideBlock - array of sources inside the if block * @param {object} context - context * @returns {string} * @private */ function handleIf(exps, sourcesInsideBlock, context) { var analyzed = extractElseif(exps, sourcesInsideBlock); var result = false; var compiledSource = ''; forEach(analyzed.exps, function(exp, index) { result = handleExpression(exp, context); if (result) { compiledSource = compile(analyzed.sourcesInsideIf[index], context); } return !result; }); return compiledSource; } /** * Helper function for "each". * @param {Array.} exps - array of expressions split by spaces * @param {Array.} sourcesInsideBlock - array of sources inside the each block * @param {object} context - context * @returns {string} * @private */ function handleEach(exps, sourcesInsideBlock, context) { var collection = handleExpression(exps, context); var additionalKey = isArray(collection) ? '@index' : '@key'; var additionalContext = {}; var result = ''; forEach(collection, function(item, key) { additionalContext[additionalKey] = key; additionalContext['@this'] = item; extend(context, additionalContext); result += compile(sourcesInsideBlock.slice(), context); }); return result; } /** * Helper function for "with ... as" * @param {Array.} exps - array of expressions split by spaces * @param {Array.} sourcesInsideBlock - array of sources inside the with block * @param {object} context - context * @returns {string} * @private */ function handleWith(exps, sourcesInsideBlock, context) { var asIndex = inArray('as', exps); var alias = exps[asIndex + 1]; var result = handleExpression(exps.slice(0, asIndex), context); var additionalContext = {}; additionalContext[alias] = result; return compile(sourcesInsideBlock, extend(context, additionalContext)) || ''; } /** * Extract sources inside block in place. * @param {Array.} sources - array of sources * @param {number} start - index of start block * @param {number} end - index of end block * @returns {Array.} * @private */ function extractSourcesInsideBlock(sources, start, end) { var sourcesInsideBlock = sources.splice(start + 1, end - start); sourcesInsideBlock.pop(); return sourcesInsideBlock; } /** * Handle block helper function * @param {string} helperKeyword - helper keyword (ex. if, each, with) * @param {Array.} sourcesToEnd - array of sources after the starting block * @param {object} context - context * @returns {Array.} * @private */ function handleBlockHelper(helperKeyword, sourcesToEnd, context) { var executeBlockHelper = BLOCK_HELPERS[helperKeyword]; var helperCount = 1; var startBlockIndex = 0; var endBlockIndex; var index = startBlockIndex + EXPRESSION_INTERVAL; var expression = sourcesToEnd[index]; while (helperCount && isString(expression)) { if (expression.indexOf(helperKeyword) === 0) { helperCount += 1; } else if (expression.indexOf('/' + helperKeyword) === 0) { helperCount -= 1; endBlockIndex = index; } index += EXPRESSION_INTERVAL; expression = sourcesToEnd[index]; } if (helperCount) { throw Error(helperKeyword + ' needs {{/' + helperKeyword + '}} expression.'); } sourcesToEnd[startBlockIndex] = executeBlockHelper( sourcesToEnd[startBlockIndex].split(' ').slice(1), extractSourcesInsideBlock(sourcesToEnd, startBlockIndex, endBlockIndex), context ); return sourcesToEnd; } /** * Helper function for "custom helper". * If helper is not a function, return helper itself. * @param {Array.} exps - array of expressions split by spaces (first element: helper) * @param {object} context - context * @returns {string} * @private */ function handleExpression(exps, context) { var result = getValueFromContext(exps[0], context); if (result instanceof Function) { return executeFunction(result, exps.slice(1), context); } return result; } /** * Execute a helper function. * @param {Function} helper - helper function * @param {Array.} argExps - expressions of arguments * @param {object} context - context * @returns {string} - result of executing the function with arguments * @private */ function executeFunction(helper, argExps, context) { var args = []; forEach(argExps, function(exp) { args.push(getValueFromContext(exp, context)); }); return helper.apply(null, args); } /** * Get a result of compiling an expression with the context. * @param {Array.} sources - array of sources split by regexp of expression. * @param {object} context - context * @returns {Array.} - array of sources that bind with its context * @private */ function compile(sources, context) { var index = 1; var expression = sources[index]; var exps, firstExp, result; while (isString(expression)) { exps = expression.split(' '); firstExp = exps[0]; if (BLOCK_HELPERS[firstExp]) { result = handleBlockHelper(firstExp, sources.splice(index, sources.length - index), context); sources = sources.concat(result); } else { sources[index] = handleExpression(exps, context); } index += EXPRESSION_INTERVAL; expression = sources[index]; } return sources.join(''); } /** * Convert text by binding expressions with context. *
* If expression exists in the context, it will be replaced. * ex) '{{title}}' with context {title: 'Hello!'} is converted to 'Hello!'. * An array or object can be accessed using bracket and dot notation. * ex) '{{odds\[2\]}}' with context {odds: \[1, 3, 5\]} is converted to '5'. * ex) '{{evens\[first\]}}' with context {evens: \[2, 4\], first: 0} is converted to '2'. * ex) '{{project\["name"\]}}' and '{{project.name}}' with context {project: {name: 'CodeSnippet'}} is converted to 'CodeSnippet'. *
* If replaced expression is a function, next expressions will be arguments of the function. * ex) '{{add 1 2}}' with context {add: function(a, b) {return a + b;}} is converted to '3'. *
* It has 3 predefined block helpers '{{helper ...}} ... {{/helper}}': 'if', 'each', 'with ... as ...'. * 1) 'if' evaluates conditional statements. It can use with 'elseif' and 'else'. * 2) 'each' iterates an array or object. It provides '@index'(array), '@key'(object), and '@this'(current element). * 3) 'with ... as ...' provides an alias. * @param {string} text - text with expressions * @param {object} context - context * @returns {string} - text that bind with its context * @memberof module:domUtil * @example * var template = require('tui-code-snippet/domUtil/template'); * * var source = * '

' * + '{{if isValidNumber title}}' * + '{{title}}th' * + '{{elseif isValidDate title}}' * + 'Date: {{title}}' * + '{{/if}}' * + '

' * + '{{each list}}' * + '{{with addOne @index as idx}}' * + '

{{idx}}: {{@this}}

' * + '{{/with}}' * + '{{/each}}'; * * var context = { * isValidDate: function(text) { * return /^\d{4}-(0|1)\d-(0|1|2|3)\d$/.test(text); * }, * isValidNumber: function(text) { * return /^\d+$/.test(text); * } * title: '2019-11-25', * list: ['Clean the room', 'Wash the dishes'], * addOne: function(num) { * return num + 1; * } * }; * * var result = template(source, context); * console.log(result); //

Date: 2019-11-25

1: Clean the room

2: Wash the dishes

*/ function template(text, context) { return compile(splitByRegExp(text, EXPRESSION_REGEXP), context); } module.exports = template; /***/ }), /* 12 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is undefined or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is undefined or not. * If the given variable is undefined, returns true. * @param {*} obj - Target for checking * @returns {boolean} Is undefined? * @memberof module:type */ function isUndefined(obj) { return obj === undefined; // eslint-disable-line no-undefined } module.exports = isUndefined; /***/ }), /* 13 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is a string or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is a string or not. * If the given variable is a string, return true. * @param {*} obj - Target for checking * @returns {boolean} Is string? * @memberof module:type */ function isString(obj) { return typeof obj === 'string' || obj instanceof String; } module.exports = isString; /***/ }), /* 14 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Remove element from parent node. * @author NHN FE Development Lab */ /** * Remove element from parent node. * @param {HTMLElement} element - element to remove. * @memberof module:domUtil */ function removeElement(element) { if (element && element.parentNode) { element.parentNode.removeChild(element); } } module.exports = removeElement; /***/ }), /* 15 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is a number or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is a number or not. * If the given variable is a number, return true. * @param {*} obj - Target for checking * @returns {boolean} Is number? * @memberof module:type */ function isNumber(obj) { return typeof obj === 'number' || obj instanceof Number; } module.exports = isNumber; /***/ }), /* 16 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Add css class to element * @author NHN FE Development Lab */ var forEach = __webpack_require__(9); var inArray = __webpack_require__(3); var getClass = __webpack_require__(17); var setClassName = __webpack_require__(24); /** * domUtil module * @module domUtil */ /** * Add css class to element * @param {(HTMLElement|SVGElement)} element - target element * @param {...string} cssClass - css classes to add * @memberof module:domUtil */ function addClass(element) { var cssClass = Array.prototype.slice.call(arguments, 1); var classList = element.classList; var newClass = []; var origin; if (classList) { forEach(cssClass, function(name) { element.classList.add(name); }); return; } origin = getClass(element); if (origin) { cssClass = [].concat(origin.split(/\s+/), cssClass); } forEach(cssClass, function(cls) { if (inArray(cls, newClass) < 0) { newClass.push(cls); } }); setClassName(element, newClass); } module.exports = addClass; /***/ }), /* 17 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Get HTML element's design classes. * @author NHN FE Development Lab */ var isUndefined = __webpack_require__(12); /** * Get HTML element's design classes. * @param {(HTMLElement|SVGElement)} element target element * @returns {string} element css class name * @memberof module:domUtil */ function getClass(element) { if (!element || !element.className) { return ''; } if (isUndefined(element.className.baseVal)) { return element.className; } return element.className.baseVal; } module.exports = getClass; /***/ }), /* 18 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Remove css class from element * @author NHN FE Development Lab */ var forEachArray = __webpack_require__(2); var inArray = __webpack_require__(3); var getClass = __webpack_require__(17); var setClassName = __webpack_require__(24); /** * Remove css class from element * @param {(HTMLElement|SVGElement)} element - target element * @param {...string} cssClass - css classes to remove * @memberof module:domUtil */ function removeClass(element) { var cssClass = Array.prototype.slice.call(arguments, 1); var classList = element.classList; var origin, newClass; if (classList) { forEachArray(cssClass, function(name) { classList.remove(name); }); return; } origin = getClass(element).split(/\s+/); newClass = []; forEachArray(origin, function(name) { if (inArray(name, cssClass) < 0) { newClass.push(name); } }); setClassName(element, newClass); } module.exports = removeClass; /***/ }), /* 19 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Set mouse-touch event * @author NHN. FE Development Lab */ var on = __webpack_require__(31); var off = __webpack_require__(33); var mouseTouchEvent = { /** * Detect mobile browser * @type {boolean} Whether using Mobile browser * @private */ _isMobile: (function() { return /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test( navigator.userAgent ); })(), /** * Return a matched event type by a mouse event type * @param {string} type A mouse event type - mousedown, click * @returns {string} * @private */ _getEventType: function(type) { if (this._isMobile) { if (type === 'mousedown') { type = 'touchstart'; } else if (type === 'click') { type = 'touchend'; } } return type; }, /** * Bind touch or mouse events * @param {HTMLElement} element An element to bind * @param {string} type A mouse event type - mousedown, click * @param {Function} handler A handler function * @param {object} [context] A context for handler. */ on: function(element, type, handler, context) { on(element, this._getEventType(type), handler, context); }, /** * Unbind touch or mouse events * @param {HTMLElement} element - Target element * @param {string} type A mouse event type - mousedown, click * @param {Function} handler - Handler */ off: function(element, type, handler) { off(element, this._getEventType(type), handler); } }; module.exports = mouseTouchEvent; /***/ }), /* 20 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Layer base * @author NHN. FE Development Lab */ var defineClass = __webpack_require__(0); var removeElement = __webpack_require__(14); var localeText = __webpack_require__(10); var DEFAULT_LANGUAGE_TYPE = __webpack_require__(1).DEFAULT_LANGUAGE_TYPE; /** * @abstract * @class * @ignore * @param {string} language - Initial language * Layer base */ var LayerBase = defineClass( /** @lends LayerBase.prototype */ { init: function(language) { language = language || DEFAULT_LANGUAGE_TYPE; /** * Layer element * @type {HTMLElement} * @private */ this._element = null; /** * Language type * @type {string} * @private */ this._localeText = localeText[language]; /** * Layer type * @type {string} * @private */ this._type = 'base'; }, /** * Make context * @abstract * @throws {Error} * @returns {object} * @private */ _makeContext: function() { throwOverrideError(this.getType(), '_makeContext'); }, /** * Render the layer element * @abstract * @throws {Error} */ render: function() { throwOverrideError(this.getType(), 'render'); }, /** * Returns date elements * @abstract * @throws {Error} * @returns {HTMLElement[]} */ getDateElements: function() { throwOverrideError(this.getType(), 'getDateElements'); }, /** * Returns layer type * @returns {string} */ getType: function() { return this._type; }, /** * Set language * @param {string} language - Language name */ changeLanguage: function(language) { this._localeText = localeText[language]; }, /** * Remove elements */ remove: function() { if (this._element) { removeElement(this._element); } this._element = null; } } ); /** * Throw - method override error * @ignore * @param {string} layerType - Layer type * @param {string} methodName - Method name * @throws {Error} */ function throwOverrideError(layerType, methodName) { throw new Error(layerType + ' layer does not have the "' + methodName + '" method.'); } module.exports = LayerBase; /***/ }), /* 21 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview DatePicker component * @author NHN. FE dev Lab */ var inArray = __webpack_require__(3); var forEachArray = __webpack_require__(2); var defineClass = __webpack_require__(0); var CustomEvents = __webpack_require__(8); var addClass = __webpack_require__(16); var closest = __webpack_require__(25); var getData = __webpack_require__(26); var hasClass = __webpack_require__(27); var removeClass = __webpack_require__(18); var removeElement = __webpack_require__(14); var extend = __webpack_require__(7); var isArray = __webpack_require__(6); var isDate = __webpack_require__(28); var isNumber = __webpack_require__(15); var isObject = __webpack_require__(22); var TimePicker = __webpack_require__(43); var Calendar = __webpack_require__(29); var RangeModel = __webpack_require__(56); var constants = __webpack_require__(1); var localeTexts = __webpack_require__(10); var dateUtil = __webpack_require__(5); var util = __webpack_require__(4); var mouseTouchEvent = __webpack_require__(19); var tmpl = __webpack_require__(58); var DatePickerInput = __webpack_require__(59); var DEFAULT_WEEK_START_DAY = constants.DEFAULT_WEEK_START_DAY; var DEFAULT_LANGUAGE_TYPE = constants.DEFAULT_LANGUAGE_TYPE; var TYPE_DATE = constants.TYPE_DATE; var TYPE_MONTH = constants.TYPE_MONTH; var TYPE_YEAR = constants.TYPE_YEAR; var CLASS_NAME_NEXT_YEAR_BTN = constants.CLASS_NAME_NEXT_YEAR_BTN; var CLASS_NAME_NEXT_MONTH_BTN = constants.CLASS_NAME_NEXT_MONTH_BTN; var CLASS_NAME_PREV_YEAR_BTN = constants.CLASS_NAME_PREV_YEAR_BTN; var CLASS_NAME_PREV_MONTH_BTN = constants.CLASS_NAME_PREV_MONTH_BTN; var CLASS_NAME_SELECTED = constants.CLASS_NAME_SELECTED; var CLASS_NAME_TITLE_TODAY = constants.CLASS_NAME_TITLE_TODAY; var CLASS_NAME_SELECTABLE = 'tui-is-selectable'; var CLASS_NAME_BLOCKED = 'tui-is-blocked'; var CLASS_NAME_CHECKED = 'tui-is-checked'; var CLASS_NAME_SELECTOR_BUTTON = 'tui-datepicker-selector-button'; var CLASS_NAME_TODAY = 'tui-calendar-today'; var CLASS_NAME_HIDDEN = 'tui-hidden'; var SELECTOR_BODY = '.tui-datepicker-body'; var SELECTOR_DATE_ICO = '.tui-ico-date'; var SELECTOR_CALENDAR_TITLE = '.tui-calendar-title'; var SELECTOR_CALENDAR_CONTAINER = '.tui-calendar-container'; var SELECTOR_TIMEPICKER_CONTAINER = '.tui-timepicker-container'; /** * Merge default option * @ignore * @param {object} option - DatePicker option * @returns {object} */ var mergeDefaultOption = function(option) { option = extend( { language: DEFAULT_LANGUAGE_TYPE, calendar: {}, input: { element: null, format: null }, timePicker: null, date: null, showAlways: false, type: TYPE_DATE, selectableRanges: null, openers: [], autoClose: true, usageStatistics: true, weekStartDay: DEFAULT_WEEK_START_DAY }, option ); option.selectableRanges = option.selectableRanges || [[constants.MIN_DATE, constants.MAX_DATE]]; if (!isObject(option.calendar)) { throw new Error('Calendar option must be an object'); } if (!isObject(option.input)) { throw new Error('Input option must be an object'); } if (!isArray(option.selectableRanges)) { throw new Error('Selectable-ranges must be a 2d-array'); } option.localeText = localeTexts[option.language]; // override calendar option option.calendar.language = option.language; option.calendar.type = option.type; // @TODO: after v5.0.0, remove option.timepicker option.timePicker = option.timePicker || option.timepicker; return option; }; /** * @class * @description * Create a date picker. * @see {@link /tutorial-example01-basic DatePicker example} * @param {HTMLElement|string} container - Container element or selector of DatePicker * @param {Object} [options] - Options * @param {Date|number} [options.date = null] - Initial date. Set by a Date instance or a number(timestamp). (default: no initial date) * @param {('date'|'month'|'year')} [options.type = 'date'] - DatePicker type. Determine whether to choose a date, month, or year. * @param {string} [options.language='en'] - Language code. English('en') and Korean('ko') are provided as default. To set to the other languages, use {@link DatePicker#localeTexts DatePicker.localeTexts}. * @param {object|boolean} [options.timePicker] - [TimePicker](https://nhn.github.io/tui.time-picker/latest) options. Refer to the [TimePicker instance's options](https://nhn.github.io/tui.time-picker/latest/TimePicker). To create the TimePicker without customization, set to true. * @param {object} [options.calendar] - {@link Calendar} options. Refer to the {@link Calendar Calendar instance's options}. * @param {object} [options.input] - Input option * @param {HTMLElement|string} [options.input.element] - Input element or selector * @param {string} [options.input.format = 'yyyy-mm-dd'] - Format of the Date string * @param {Array.>} [options.selectableRanges = 1900/1/1 ~ 2999/12/31] * - Ranges of selectable date. Set by Date instances or numbers(timestamp). * @param {Array} [options.openers = []] - List of the openers to open the DatePicker (example - icon, button, etc.) * @param {boolean} [options.showAlways = false] - Show the DatePicker always * @param {boolean} [options.autoClose = true] - Close the DatePicker after clicking the date * @param {boolean} [options.usageStatistics = true] - Send a hostname to Google Analytics (default: true) * @param {string} [options.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday)) * @example * // ES6 * import DatePicker from 'tui-date-picker' * * // CommonJS * const DatePicker = require('tui-date-picker'); * * // Browser * const DatePicker = tui.DatePicker; * * const range1 = [new Date(2015, 2, 1), new Date(2015, 3, 1)]; * const range2 = [1465570800000, 1481266182155]; // timestamps * * const picker1 = new DatePicker('#datepicker-container1', { * showAlways: true * }); * * const picker2 = new DatePicker('#datepicker-container2', { * showAlways: true, * timePicker: true * }); * * const picker3 = new DatePicker('#datepicker-container3', { * language: 'ko', * calendar: { * showToday: true * }, * timePicker: { * showMeridiem: true, * defaultHour: 13, * defaultMinute: 24 * }, * input: { * element: '#datepicker-input', * format: 'yyyy년 MM월 dd일 hh:mm A' * } * type: 'date', * date: new Date(2015, 0, 1) * selectableRanges: [range1, range2], * openers: ['#opener'], * weekStartDay: 'Mon', * }); */ var DatePicker = defineClass( /** @lends DatePicker.prototype */ { static: { /** * Locale text data. English('en') and Korean('ko') are provided as default. * @type {object} * @memberof DatePicker * @static * @example * DatePicker.localeTexts['customKey'] = { * titles: { * // days * DD: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], * // daysShort * D: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], * // months * MMMM: [ * 'January', 'February', 'March', 'April', 'May', 'June', * 'July', 'August', 'September', 'October', 'November', 'December' * ], * // monthsShort * MMM: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] * }, * titleFormat: 'MMM yyyy', * todayFormat: 'D, MMMM dd, yyyy', * date: 'Date', * time: 'Time' * }; * * const datepicker = new DatePicker('#datepicker-container', { * language: 'customKey' * }); */ localeTexts: localeTexts }, init: function(container, options) { options = mergeDefaultOption(options); /** * Language type * @type {string} * @private */ this._language = options.language; /** * DatePicker container * @type {HTMLElement} * @private */ this._container = util.getElement(container); this._container.innerHTML = tmpl( extend(options, { isTab: options.timePicker && options.timePicker.layoutType === 'tab' }) ); /** * DatePicker element * @type {HTMLElement} * @private */ this._element = this._container.firstChild; /** * Calendar instance * @type {Calendar} * @private */ this._calendar = new Calendar( this._element.querySelector(SELECTOR_CALENDAR_CONTAINER), extend(options.calendar, { usageStatistics: options.usageStatistics, weekStartDay: options.weekStartDay }) ); /** * TimePicker instance * @type {TimePicker} * @private */ this._timePicker = null; /** * DatePicker input * @type {DatePickerInput} * @private */ this._datepickerInput = null; /** * Object having date values * @type {Date} * @private */ this._date = null; /** * Selectable date-ranges model * @type {RangeModel} * @private */ this._rangeModel = null; /** * openers - opener list * @type {Array} * @private */ this._openers = []; /** * State of picker enable * @type {boolean} * @private */ this._isEnabled = true; /** * ID of instance * @type {number} * @private */ this._id = 'tui-datepicker-' + util.generateId(); /** * DatePicker type * @type {TYPE_DATE|TYPE_MONTH|TYPE_YEAR} * @private */ this._type = options.type; /** * Show always or not * @type {boolean} */ this.showAlways = options.showAlways; /** * Close after select a date * @type {boolean} */ this.autoClose = options.autoClose; this._initializeDatePicker(options); }, /** * Initialize method * @param {Object} option - user option * @private */ _initializeDatePicker: function(option) { this.setRanges(option.selectableRanges); this._setEvents(); this._initTimePicker(option.timePicker, option.usageStatistics); this.setInput(option.input.element); this.setDateFormat(option.input.format); this.setDate(option.date); forEachArray(option.openers, this.addOpener, this); if (!this.showAlways) { this._hide(); } if (this.getType() === TYPE_DATE) { addClass(this._element.querySelector(SELECTOR_BODY), 'tui-datepicker-type-date'); } }, /** * Set events on the date picker's element * @param {object} option - Constructor option * @private */ _setEvents: function() { mouseTouchEvent.on(this._element, 'click', this._onClickHandler, this); this._calendar.on('draw', this._onDrawCalendar, this); }, /** * Remove events on the date picker's element * @private */ _removeEvents: function() { mouseTouchEvent.off(this._element, 'click', this._onClickHandler, this); this._calendar.off(); }, /** * Set events on the document * @private */ _setDocumentEvents: function() { mouseTouchEvent.on(document, 'mousedown', this._onMousedownDocument, this); }, /** * Remove events on the document * @private */ _removeDocumentEvents: function() { mouseTouchEvent.off(document, 'mousedown', this._onMousedownDocument); }, /** * Set events on the opener * @param {HTMLElement} opener An opener to bind the events * @private */ _setOpenerEvents: function(opener) { mouseTouchEvent.on(opener, 'click', this.toggle, this); }, /** * Remove events on the opener * @param {HTMLElement} opener An opener to unbind the events * @private */ _removeOpenerEvents: function(opener) { mouseTouchEvent.off(opener, 'click', this.toggle); }, /** * Set TimePicker instance * @param {object|boolean} opTimePicker - TimePicker instance options * @param {boolean} usageStatistics - GA tracking options * @private */ _initTimePicker: function(opTimePicker, usageStatistics) { var layoutType; if (!opTimePicker) { return; } layoutType = opTimePicker.layoutType || ''; if (isObject(opTimePicker)) { opTimePicker.usageStatistics = usageStatistics; } else { opTimePicker = { usageStatistics: usageStatistics }; } this._timePicker = new TimePicker( this._element.querySelector(SELECTOR_TIMEPICKER_CONTAINER), opTimePicker ); if (layoutType.toLowerCase() === 'tab') { this._timePicker.hide(); } this._timePicker.on( 'change', function(ev) { var prevDate; if (this._date) { prevDate = new Date(this._date); this.setDate(prevDate.setHours(ev.hour, ev.minute)); } }, this ); }, /** * Change picker's type by a selector button. * @param {HTMLElement} target A target element * @private */ _changePicker: function(target) { var btnSelector = '.' + CLASS_NAME_SELECTOR_BUTTON; var selectedBtn = closest(target, btnSelector); var isDateElement = !!selectedBtn.querySelector(SELECTOR_DATE_ICO); if (isDateElement) { this._calendar.show(); this._timePicker.hide(); } else { this._calendar.hide(); this._timePicker.show(); } removeClass(this._element.querySelector('.' + CLASS_NAME_CHECKED), CLASS_NAME_CHECKED); addClass(selectedBtn, CLASS_NAME_CHECKED); }, /** * Returns whether the element is opener * @param {string|HTMLElement} element - Element or selector * @returns {boolean} * @private */ _isOpener: function(element) { var el = util.getElement(element); return inArray(el, this._openers) > -1; }, /** * add/remove today-class-name to date element * @param {HTMLElement} el - date element * @private */ _setTodayClassName: function(el) { var timestamp, isToday; if (this.getCalendarType() !== TYPE_DATE) { return; } timestamp = Number(getData(el, 'timestamp')); isToday = timestamp === new Date().setHours(0, 0, 0, 0); if (isToday) { addClass(el, CLASS_NAME_TODAY); } else { removeClass(el, CLASS_NAME_TODAY); } }, /** * add/remove selectable-class-name to date element * @param {HTMLElement} el - date element * @private */ _setSelectableClassName: function(el) { var elDate = new Date(Number(getData(el, 'timestamp'))); if (this._isSelectableOnCalendar(elDate)) { addClass(el, CLASS_NAME_SELECTABLE); removeClass(el, CLASS_NAME_BLOCKED); } else { removeClass(el, CLASS_NAME_SELECTABLE); addClass(el, CLASS_NAME_BLOCKED); } }, /** * add/remove selected-class-name to date element * @param {HTMLElement} el - date element * @private */ _setSelectedClassName: function(el) { var elDate = new Date(Number(getData(el, 'timestamp'))); if (this._isSelectedOnCalendar(elDate)) { addClass(el, CLASS_NAME_SELECTED); } else { removeClass(el, CLASS_NAME_SELECTED); } }, /** * Returns whether the date is selectable on calendar * @param {Date} date - Date instance * @returns {boolean} * @private */ _isSelectableOnCalendar: function(date) { var type = this.getCalendarType(); var start = dateUtil.cloneWithStartOf(date, type).getTime(); var end = dateUtil.cloneWithEndOf(date, type).getTime(); return this._rangeModel.hasOverlap(start, end); }, /** * Returns whether the date is selected on calendar * @param {Date} date - Date instance * @returns {boolean} * @private */ _isSelectedOnCalendar: function(date) { var curDate = this.getDate(); var calendarType = this.getCalendarType(); return curDate && dateUtil.isSame(curDate, date, calendarType); }, /** * Show the date picker element * @private */ _show: function() { removeClass(this._element, CLASS_NAME_HIDDEN); }, /** * Hide the date picker element * @private */ _hide: function() { addClass(this._element, CLASS_NAME_HIDDEN); }, /** * Set value a date-string of current this instance to input element * @private */ _syncToInput: function() { if (!this._date) { return; } this._datepickerInput.setDate(this._date); }, /** * Set date from input value * @param {boolean} [shouldRollback = false] - Should rollback from unselectable or error * @private */ _syncFromInput: function(shouldRollback) { var isFailed = false; var date; try { date = this._datepickerInput.getDate(); if (this.isSelectable(date)) { if (this._timePicker) { this._timePicker.setTime(date.getHours(), date.getMinutes()); } this.setDate(date); } else { isFailed = true; } } catch (err) { this.fire('error', { type: 'ParsingError', message: err.message }); isFailed = true; } finally { if (isFailed) { if (shouldRollback) { this._syncToInput(); } else { this.setNull(); } } } }, /** * Event handler for mousedown of document
* - When click the out of layer, close the layer * @param {Event} ev - Event object * @private */ _onMousedownDocument: function(ev) { var target = util.getTarget(ev); var selector = util.getSelector(target); var isContain = selector ? this._element.querySelector(selector) : false; var isInput = this._datepickerInput.is(target); var isInOpener = inArray(target, this._openers) > -1; var shouldClose = !(this.showAlways || isInput || isContain || isInOpener); if (shouldClose) { this.close(); } }, /** * Event handler for click of calendar * @param {Event} ev An event object * @private */ _onClickHandler: function(ev) { var target = util.getTarget(ev); if (closest(target, '.' + CLASS_NAME_SELECTABLE)) { ev.preventDefault(); this._updateDate(target); } else if (closest(target, '.' + CLASS_NAME_TITLE_TODAY)) { ev.preventDefault(); this._updateDateToToday(); } else if (closest(target, SELECTOR_CALENDAR_TITLE)) { this.drawUpperCalendar(this._date); } else if (closest(target, '.' + CLASS_NAME_SELECTOR_BUTTON)) { this._changePicker(target); } }, /** * Update date to today * @private */ _updateDateToToday: function() { this.setDate(Date.now()); this.close(); }, /** * Update date from event-target * @param {HTMLElement} target An event target element * @private */ _updateDate: function(target) { var timestamp = Number(getData(target, 'timestamp')); var newDate = new Date(timestamp); var timePicker = this._timePicker; var prevDate = this._date; var calendarType = this.getCalendarType(); var pickerType = this.getType(); if (calendarType !== pickerType) { this.drawLowerCalendar(newDate); } else { if (timePicker) { newDate.setHours(timePicker.getHour(), timePicker.getMinute()); } else if (prevDate) { newDate.setHours(prevDate.getHours(), prevDate.getMinutes()); } this.setDate(newDate); if (!this.showAlways && this.autoClose) { this.close(); } } }, /** * Event handler for 'draw'-custom event of calendar * @param {Object} eventData - custom event data * @see {@link Calendar#draw} * @private */ _onDrawCalendar: function(eventData) { forEachArray( eventData.dateElements, function(el) { this._setTodayClassName(el); this._setSelectableClassName(el); this._setSelectedClassName(el); }, this ); this._setDisplayHeadButtons(); /** * Occur after the calendar is drawn. * @event DatePicker#draw * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#on datepicker.on()} to bind event handlers. * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#off datepicker.off()} to unbind event handlers. * @see Refer to {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents CustomEvents from tui-code-snippet} for more methods. DatePicker mixes in the methods from CustomEvents. * @property {Date} date - Calendar date * @property {('date'|'month'|'year')} type - Calendar type * @property {HTMLElement[]} dateElements - elements for dates * @example * // bind the 'draw' event * datepicker.on('draw', (event) => { * console.log(`Draw the ${event.type} calendar and its date is ${event.date}.`); * }); * * // unbind the 'draw' event * datepicker.off('draw'); */ this.fire('draw', eventData); }, /** * Hide useless buttons (next, next-year, prev, prev-year) * @see Don't save buttons reference. The buttons are rerendered every "calendar.draw". * @private */ _setDisplayHeadButtons: function() { var nextYearDate = this._calendar.getNextYearDate(); var prevYearDate = this._calendar.getPrevYearDate(); var maxTimestamp = this._rangeModel.getMaximumValue(); var minTimestamp = this._rangeModel.getMinimumValue(); var nextYearBtn = this._element.querySelector('.' + CLASS_NAME_NEXT_YEAR_BTN); var prevYearBtn = this._element.querySelector('.' + CLASS_NAME_PREV_YEAR_BTN); var nextMonthDate, prevMonthDate, nextMonBtn, prevMonBtn; if (this.getCalendarType() === TYPE_DATE) { nextMonthDate = dateUtil.cloneWithStartOf(this._calendar.getNextDate(), TYPE_MONTH); prevMonthDate = dateUtil.cloneWithEndOf(this._calendar.getPrevDate(), TYPE_MONTH); nextMonBtn = this._element.querySelector('.' + CLASS_NAME_NEXT_MONTH_BTN); prevMonBtn = this._element.querySelector('.' + CLASS_NAME_PREV_MONTH_BTN); this._setDisplay(nextMonBtn, nextMonthDate.getTime() <= maxTimestamp); this._setDisplay(prevMonBtn, prevMonthDate.getTime() >= minTimestamp); prevYearDate.setDate(1); nextYearDate.setDate(1); } else { prevYearDate.setMonth(12, 0); nextYearDate.setMonth(0, 1); } this._setDisplay(nextYearBtn, nextYearDate.getTime() <= maxTimestamp); this._setDisplay(prevYearBtn, prevYearDate.getTime() >= minTimestamp); }, /** * Set display show/hide by condition * @param {HTMLElement} el - An Element * @param {boolean} shouldShow - Condition * @private */ _setDisplay: function(el, shouldShow) { if (el) { if (shouldShow) { removeClass(el, CLASS_NAME_HIDDEN); } else { addClass(el, CLASS_NAME_HIDDEN); } } }, /** * Input change handler * @private * @throws {Error} */ _onChangeInput: function() { this._syncFromInput(true); }, /** * Returns whether the date is changed * @param {Date} date - Date * @returns {boolean} * @private */ _isChanged: function(date) { var prevDate = this.getDate(); return !prevDate || date.getTime() !== prevDate.getTime(); }, /** * Refresh datepicker * @private */ _refreshFromRanges: function() { if (!this.isSelectable(this._date)) { this.setNull(); } else { this._calendar.draw(); // view update } }, /** * Return the current calendar's type. * @returns {('date'|'month'|'year')} */ getCalendarType: function() { return this._calendar.getType(); }, /** * Return the date picker's type. * @returns {('date'|'month'|'year')} */ getType: function() { return this._type; }, /** * Return whether the date is selectable. * @param {Date} date - Date to check * @returns {boolean} */ isSelectable: function(date) { var type = this.getType(); var start, end; if (!dateUtil.isValidDate(date)) { return false; } start = dateUtil.cloneWithStartOf(date, type).getTime(); end = dateUtil.cloneWithEndOf(date, type).getTime(); return this._rangeModel.hasOverlap(start, end); }, /** * Return whether the date is selected. * @param {Date} date - Date to check * @returns {boolean} */ isSelected: function(date) { return dateUtil.isValidDate(date) && dateUtil.isSame(this._date, date, this.getType()); }, /** * Set selectable ranges. Previous ranges will be removed. * @param {Array.>} ranges - Selectable ranges. Use Date instances or numbers(timestamp). * @example * datepicker.setRanges([ * [new Date(2017, 0, 1), new Date(2018, 0, 2)], * [new Date(2015, 2, 3), new Date(2016, 4, 2)] * ]); */ setRanges: function(ranges) { var result = []; forEachArray(ranges, function(range) { var start = new Date(range[0]).getTime(); var end = new Date(range[1]).getTime(); result.push([start, end]); }); this._rangeModel = new RangeModel(result); this._refreshFromRanges(); }, /** * Set the calendar's type. * @param {('date'|'month'|'year')} type - Calendar type * @example * datepicker.setType('month'); */ setType: function(type) { this._type = type; }, /** * Add a selectable range. Use Date instances or numbers(timestamp). * @param {Date|number} start - the start date * @param {Date|number} end - the end date * @example * const start = new Date(2015, 1, 3); * const end = new Date(2015, 2, 6); * * datepicker.addRange(start, end); */ addRange: function(start, end) { start = new Date(start).getTime(); end = new Date(end).getTime(); this._rangeModel.add(start, end); this._refreshFromRanges(); }, /** * Remove a range. Use Date instances or numbers(timestamp). * @param {Date|number} start - the start date * @param {Date|number} end - the end date * @param {null|'date'|'month'|'year'} type - Range type. If falsy, start and end values are considered as timestamp * @example * const start = new Date(2015, 1, 3); * const end = new Date(2015, 2, 6); * * datepicker.removeRange(start, end); */ removeRange: function(start, end, type) { start = new Date(start); end = new Date(end); if (type) { // @todo Consider time-range on timePicker start = dateUtil.cloneWithStartOf(start, type); end = dateUtil.cloneWithEndOf(end, type); } this._rangeModel.exclude(start.getTime(), end.getTime()); this._refreshFromRanges(); }, /** * Add an opener. * @param {HTMLElement|string} opener - element or selector of opener */ addOpener: function(opener) { opener = util.getElement(opener); if (!this._isOpener(opener)) { this._openers.push(opener); this._setOpenerEvents(opener); } }, /** * Remove an opener. * @param {HTMLElement|string} opener - element or selector of opener */ removeOpener: function(opener) { var index; opener = util.getElement(opener); index = inArray(opener, this._openers); if (index > -1) { this._removeOpenerEvents(opener); this._openers.splice(index, 1); } }, /** * Remove all openers. */ removeAllOpeners: function() { forEachArray( this._openers, function(opener) { this._removeOpenerEvents(opener); }, this ); this._openers = []; }, /** * Open the date picker. * @example * datepicker.open(); */ open: function() { if (this.isOpened() || !this._isEnabled) { return; } this._calendar.draw({ date: this._date, type: this._type }); this._show(); if (!this.showAlways) { this._setDocumentEvents(); } /** * Occur after the date picker opens. * @event DatePicker#open * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#on datepicker.on()} to bind event handlers. * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#off datepicker.off()} to unbind event handlers. * @see Refer to {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents CustomEvents from tui-code-snippet} for more methods. DatePicker mixes in the methods from CustomEvents. * @example * // bind the 'open' event * datepicker.on('open', () => { * alert('open'); * }); * * // unbind the 'open' event * datepicker.off('open'); */ this.fire('open'); }, /** * Raise the calendar type. (date -> month -> year) * @param {Date} [date] - Date to set */ drawUpperCalendar: function(date) { var calendarType = this.getCalendarType(); if (calendarType === TYPE_DATE) { this._calendar.draw({ date: date, type: TYPE_MONTH }); } else if (calendarType === TYPE_MONTH) { this._calendar.draw({ date: date, type: TYPE_YEAR }); } }, /** * Lower the calendar type. (year -> month -> date) * @param {Date} [date] - Date to set */ drawLowerCalendar: function(date) { var calendarType = this.getCalendarType(); var pickerType = this.getType(); var isLast = calendarType === pickerType; if (isLast) { return; } if (calendarType === TYPE_MONTH) { this._calendar.draw({ date: date, type: TYPE_DATE }); } else if (calendarType === TYPE_YEAR) { this._calendar.draw({ date: date, type: TYPE_MONTH }); } }, /** * Close the date picker. * @exmaple * datepicker.close(); */ close: function() { if (!this.isOpened()) { return; } this._removeDocumentEvents(); this._hide(); /** * Occur after the date picker closes. * @event DatePicker#close * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#on datepicker.on()} to bind event handlers. * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#off datepicker.off()} to unbind event handlers. * @see Refer to {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents CustomEvents from tui-code-snippet} for more methods. DatePicker mixes in the methods from CustomEvents. * @example * // bind the 'close' event * datepicker.on('close', () => { * alert('close'); * }); * * // unbind the 'close' event * datepicker.off('close'); */ this.fire('close'); }, /** * Toggle the date picker. * @example * datepicker.toggle(); */ toggle: function() { if (this.isOpened()) { this.close(); } else { this.open(); } }, /** * Return the selected date. * @returns {?Date} - selected date * @example * // 2015-04-13 * datepicker.getDate(); // new Date(2015, 3, 13) */ getDate: function() { if (!this._date) { return null; } return new Date(this._date); }, /** * Select the date. * @param {Date|number} date - Date instance or timestamp to set * @example * datepicker.setDate(new Date()); // Set today */ // eslint-disable-next-line complexity setDate: function(date) { var isValidInput, newDate, shouldUpdate; if (date === null) { this.setNull(); return; } isValidInput = isNumber(date) || isDate(date); newDate = new Date(date); shouldUpdate = isValidInput && this._isChanged(newDate) && this.isSelectable(newDate); if (shouldUpdate) { newDate = new Date(date); this._date = newDate; this._calendar.draw({ date: newDate }); if (this._timePicker) { this._timePicker.setTime(newDate.getHours(), newDate.getMinutes()); } this._syncToInput(); /** * Occur after the selected date is changed. * @event DatePicker#change * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#on datepicker.on()} to bind event handlers. * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#off datepicker.off()} to unbind event handlers. * @see Refer to {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents CustomEvents from tui-code-snippet} for more methods. DatePicker mixes in the methods from CustomEvents. * @example * // bind the 'change' event * datepicker.on('change', () => { * console.log(`Selected date: ${datepicker.getDate()}`); * }); * * // unbind the 'change' event * datepicker.off('change'); */ this.fire('change'); } }, /** * Set no date to be selected. (Selected date: null) */ setNull: function() { var calendarDate = this._calendar.getDate(); var isChagned = this._date !== null; this._date = null; if (this._datepickerInput) { this._datepickerInput.clearText(); } if (this._timePicker) { this._timePicker.setTime(0, 0); } // View update if (!this.isSelectable(calendarDate)) { this._calendar.draw({ date: new Date(this._rangeModel.getMinimumValue()) }); } else { this._calendar.draw(); } if (isChagned) { this.fire('change'); } }, /** * Select the date by the date string format. * @param {String} [format] - Date string format * @example * datepicker.setDateFormat('yyyy-MM-dd'); * datepicker.setDateFormat('MM-dd, yyyy'); * datepicker.setDateFormat('yy/M/d'); * datepicker.setDateFormat('yy/MM/dd'); */ setDateFormat: function(format) { this._datepickerInput.setFormat(format); this._syncToInput(); }, /** * Return whether the datepicker opens or not * @returns {boolean} * @example * datepicker.close(); * datepicker.isOpened(); // false * * datepicker.open(); * datepicker.isOpened(); // true */ isOpened: function() { return !hasClass(this._element, CLASS_NAME_HIDDEN); }, /** * Return the time picker instance * @returns {?TimePicker} - TimePicker instance * @see {@link https://nhn.github.io/tui.time-picker/latest tui-time-picker} * @example * const timePicker = this.getTimePicker(); */ getTimePicker: function() { return this._timePicker; }, /** * Return the calendar instance. * @see {@link calendar Calendar} * @returns {Calendar} */ getCalendar: function() { return this._calendar; }, /** * Return the locale text object. * @see {@link DatePicker#localeTexts DatePicker.localeTexts} * @returns {object} */ getLocaleText: function() { return localeTexts[this._language] || localeTexts[DEFAULT_LANGUAGE_TYPE]; }, /** * Set the input element * @param {string|HTMLElement} element - Input element or selector * @param {object} [options] - Input option * @param {string} [options.format = prevInput.format] - Format of the Date string in the input * @param {boolean} [options.syncFromInput = false] - Whether set the date from the input */ setInput: function(element, options) { var prev = this._datepickerInput; var localeText = this.getLocaleText(); var prevFormat; options = options || {}; if (prev) { prevFormat = prev.getFormat(); prev.destroy(); } this._datepickerInput = new DatePickerInput(element, { format: options.format || prevFormat, id: this._id, localeText: localeText }); this._datepickerInput.on( { change: this._onChangeInput, click: this.open }, this ); if (options.syncFromInput) { this._syncFromInput(); } else { this._syncToInput(); } }, /** * Enable the date picker. */ enable: function() { if (this._isEnabled) { return; } this._isEnabled = true; this._datepickerInput.enable(); forEachArray( this._openers, function(opener) { opener.removeAttribute('disabled'); this._setOpenerEvents(opener); }, this ); }, /** * Disable the date picker. */ disable: function() { if (!this._isEnabled) { return; } this._isEnabled = false; this.close(); this._datepickerInput.disable(); forEachArray( this._openers, function(opener) { opener.setAttribute('disabled', true); this._removeOpenerEvents(opener); }, this ); }, /** * Return whether the date picker is disabled * @returns {boolean} */ isDisabled: function() { // @todo this._isEnabled --> this._isDisabled return !this._isEnabled; }, /** * Apply a CSS class to the date picker. * @param {string} className - Class name */ addCssClass: function(className) { addClass(this._element, className); }, /** * Remove a CSS class from the date picker. * @param {string} className - Class name */ removeCssClass: function(className) { removeClass(this._element, className); }, /** * Return the date elements on the calendar. * @returns {HTMLElement[]} */ getDateElements: function() { return this._calendar.getDateElements(); }, /** * Return the first overlapped range from the point or range. * @param {Date|number} startDate - Start date to find overlapped range * @param {Date|number} endDate - End date to find overlapped range * @returns {Array.} - \[startDate, endDate] */ findOverlappedRange: function(startDate, endDate) { var startTimestamp = new Date(startDate).getTime(); var endTimestamp = new Date(endDate).getTime(); var overlappedRange = this._rangeModel.findOverlappedRange(startTimestamp, endTimestamp); return [new Date(overlappedRange[0]), new Date(overlappedRange[1])]; }, /** * Change language. * @param {string} language - Language code. English('en') and Korean('ko') are provided as default. * @see To set to the other languages, use {@link DatePicker#localeTexts DatePicker.localeTexts}. */ changeLanguage: function(language) { this._language = language; this._calendar.changeLanguage(this._language); this._datepickerInput.changeLocaleTitles(this.getLocaleText().titles); this.setDateFormat(this._datepickerInput.getFormat()); if (this._timePicker) { this._timePicker.changeLanguage(this._language); } }, /** * Destroy the date picker. */ destroy: function() { this._removeDocumentEvents(); this._calendar.destroy(); if (this._timePicker) { this._timePicker.destroy(); } if (this._datepickerInput) { this._datepickerInput.destroy(); } this._removeEvents(); removeElement(this._element); this.removeAllOpeners(); this._calendar = this._timePicker = this._datepickerInput = this._container = this._element = this._date = this._rangeModel = this._openers = this._isEnabled = this._id = null; } } ); CustomEvents.mixin(DatePicker); module.exports = DatePicker; /***/ }), /* 22 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is an object or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is an object or not. * If the given variable is an object, return true. * @param {*} obj - Target for checking * @returns {boolean} Is object? * @memberof module:type */ function isObject(obj) { return obj === Object(obj); } module.exports = isObject; /***/ }), /* 23 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Execute the provided callback once for each property of object which actually exist. * @author NHN FE Development Lab */ /** * Execute the provided callback once for each property of object which actually exist. * If the callback function returns false, the loop will be stopped. * Callback function(iteratee) is invoked with three arguments: * 1) The value of the property * 2) The name of the property * 3) The object being traversed * @param {Object} obj The object that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @memberof module:collection * @example * var forEachOwnProperties = require('tui-code-snippet/collection/forEachOwnProperties'); // node, commonjs * * var sum = 0; * * forEachOwnProperties({a:1,b:2,c:3}, function(value){ * sum += value; * }); * alert(sum); // 6 */ function forEachOwnProperties(obj, iteratee, context) { var key; context = context || null; for (key in obj) { if (obj.hasOwnProperty(key)) { if (iteratee.call(context, obj[key], key, obj) === false) { break; } } } } module.exports = forEachOwnProperties; /***/ }), /* 24 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Set className value * @author NHN FE Development Lab */ var isArray = __webpack_require__(6); var isUndefined = __webpack_require__(12); /** * Set className value * @param {(HTMLElement|SVGElement)} element - target element * @param {(string|string[])} cssClass - class names * @private */ function setClassName(element, cssClass) { cssClass = isArray(cssClass) ? cssClass.join(' ') : cssClass; cssClass = cssClass.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); if (isUndefined(element.className.baseVal)) { element.className = cssClass; return; } element.className.baseVal = cssClass; } module.exports = setClassName; /***/ }), /* 25 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Find parent element recursively * @author NHN FE Development Lab */ var matches = __webpack_require__(40); /** * Find parent element recursively * @param {HTMLElement} element - base element to start find * @param {string} selector - selector string for find * @returns {HTMLElement} - element finded or null * @memberof module:domUtil */ function closest(element, selector) { var parent = element.parentNode; if (matches(element, selector)) { return element; } while (parent && parent !== document) { if (matches(parent, selector)) { return parent; } parent = parent.parentNode; } return null; } module.exports = closest; /***/ }), /* 26 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Get data value from data-attribute * @author NHN FE Development Lab */ var convertToKebabCase = __webpack_require__(42); /** * Get data value from data-attribute * @param {HTMLElement} element - target element * @param {string} key - key * @returns {string} value * @memberof module:domUtil */ function getData(element, key) { if (element.dataset) { return element.dataset[key]; } return element.getAttribute('data-' + convertToKebabCase(key)); } module.exports = getData; /***/ }), /* 27 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check element has specific css class * @author NHN FE Development Lab */ var inArray = __webpack_require__(3); var getClass = __webpack_require__(17); /** * Check element has specific css class * @param {(HTMLElement|SVGElement)} element - target element * @param {string} cssClass - css class * @returns {boolean} * @memberof module:domUtil */ function hasClass(element, cssClass) { var origin; if (element.classList) { return element.classList.contains(cssClass); } origin = getClass(element).split(/\s+/); return inArray(cssClass, origin) > -1; } module.exports = hasClass; /***/ }), /* 28 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is an instance of Date or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is an instance of Date or not. * If the given variables is an instance of Date, return true. * @param {*} obj - Target for checking * @returns {boolean} Is an instance of Date? * @memberof module:type */ function isDate(obj) { return obj instanceof Date; } module.exports = isDate; /***/ }), /* 29 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Calendar component * @author NHN. FE dev Lab */ var defineClass = __webpack_require__(0); var CustomEvents = __webpack_require__(8); var addClass = __webpack_require__(16); var hasClass = __webpack_require__(27); var removeClass = __webpack_require__(18); var removeElement = __webpack_require__(14); var extend = __webpack_require__(7); var Header = __webpack_require__(44); var Body = __webpack_require__(49); var localeTexts = __webpack_require__(10); var constants = __webpack_require__(1); var dateUtil = __webpack_require__(5); var util = __webpack_require__(4); var DEFAULT_WEEK_START_DAY = constants.DEFAULT_WEEK_START_DAY; var DEFAULT_LANGUAGE_TYPE = constants.DEFAULT_LANGUAGE_TYPE; var TYPE_DATE = constants.TYPE_DATE; var TYPE_MONTH = constants.TYPE_MONTH; var TYPE_YEAR = constants.TYPE_YEAR; var CLASS_NAME_PREV_MONTH_BTN = constants.CLASS_NAME_PREV_MONTH_BTN; var CLASS_NAME_PREV_YEAR_BTN = constants.CLASS_NAME_PREV_YEAR_BTN; var CLASS_NAME_NEXT_YEAR_BTN = constants.CLASS_NAME_NEXT_YEAR_BTN; var CLASS_NAME_NEXT_MONTH_BTN = constants.CLASS_NAME_NEXT_MONTH_BTN; var CLASS_NAME_CALENDAR_MONTH = 'tui-calendar-month'; var CLASS_NAME_CALENDAR_YEAR = 'tui-calendar-year'; var CLASS_NAME_HIDDEN = 'tui-hidden'; var HEADER_SELECTOR = '.tui-calendar-header'; var BODY_SELECTOR = '.tui-calendar-body'; /** * @class * @description * Create a calendar by {@link DatePicker#createCalendar DatePicker.createCalendar()}. * @see {@link /tutorial-example07-calendar Calendar example} * @param {HTMLElement|string} container - Container or selector of the Calendar * @param {Object} [options] - Calendar options * @param {Date} [options.date = new Date()] - Initial date (default: today) * @param {('date'|'month'|'year')} [options.type = 'date'] - Calendar type. Determine whether to show a date, month, or year. * @param {string} [options.language = 'en'] - Language code. English('en') and Korean('ko') are provided as default. To use the other languages, use {@link DatePicker#localeTexts DatePicker.localeTexts}. * @param {boolean} [options.showToday = true] - Show today. * @param {boolean} [options.showJumpButtons = false] - Show the yearly jump buttons (move to the previous and next year in 'date' Calendar) * @param {boolean} [options.usageStatistics = true] - Send a hostname to Google Analytics (default: true) * @param {string} [options.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday)) * @example * //ES6 * import DatePicker from 'tui-date-picker' * * // CommonJS * const DatePicker = require('tui-date-picker'); * * // Browser * const DatePicker = tui.DatePicker; * * const calendar = DatePicker.createCalendar('#calendar-wrapper', { * language: 'en', * showToday: true, * showJumpButtons: false, * date: new Date(), * type: 'date', * weekStartDay: 'Mon', * }); * * calendar.on('draw', (event) => { * console.log(event.date); * console.log(event.type); * for (let i = 0, len = event.dateElements.length; i < len; i += 1) { * const el = event.dateElements[i]; * const date = new Date(getData(el, 'timestamp')); * console.log(date); * } * }); */ var Calendar = defineClass( /** @lends Calendar.prototype */ { static: { localeTexts: localeTexts }, init: function(container, options) { options = extend( { language: DEFAULT_LANGUAGE_TYPE, showToday: true, showJumpButtons: false, date: new Date(), type: TYPE_DATE, usageStatistics: true, weekStartDay: DEFAULT_WEEK_START_DAY }, options ); /** * Container element * @type {HTMLElement} * @private */ this._container = util.getElement(container); this._container.innerHTML = '
' + '
' + '
' + '
'; /** * Wrapper element * @type {HTMLElement} * @private */ this._element = this._container.firstChild; /** * Date * @type {Date} * @private */ this._date = null; /** * Layer type * @type {string} * @private */ this._type = null; /** * Header box * @type {Header} * @private */ this._header = null; /** * Body box * @type {Body} * @private */ this._body = null; this._initHeader(options); this._initBody(options); this.draw({ date: options.date, type: options.type }); if (options.usageStatistics) { util.sendHostName(); } }, /** * Initialize header * @param {object} options - Header options * @private */ _initHeader: function(options) { var headerContainer = this._element.querySelector(HEADER_SELECTOR); this._header = new Header(headerContainer, options); this._header.on( 'click', function(ev) { var target = util.getTarget(ev); if (hasClass(target, CLASS_NAME_PREV_MONTH_BTN)) { this.drawPrev(); } else if (hasClass(target, CLASS_NAME_PREV_YEAR_BTN)) { this._onClickPrevYear(); } else if (hasClass(target, CLASS_NAME_NEXT_MONTH_BTN)) { this.drawNext(); } else if (hasClass(target, CLASS_NAME_NEXT_YEAR_BTN)) { this._onClickNextYear(); } }, this ); }, /** * Initialize body * @param {object} options - Body options * @private */ _initBody: function(options) { var bodyContainer = this._element.querySelector(BODY_SELECTOR); this._body = new Body(bodyContainer, options); }, /** * clickHandler - prev year button * @private */ _onClickPrevYear: function() { if (this.getType() === TYPE_DATE) { this.draw({ date: this._getRelativeDate(-12) }); } else { this.drawPrev(); } }, /** * clickHandler - next year button * @private */ _onClickNextYear: function() { if (this.getType() === TYPE_DATE) { this.draw({ date: this._getRelativeDate(12) }); } else { this.drawNext(); } }, /** * Returns whether the layer type is valid * @param {string} type - Layer type to check * @returns {boolean} * @private */ _isValidType: function(type) { return type === TYPE_DATE || type === TYPE_MONTH || type === TYPE_YEAR; }, /** * @param {Date} date - Date to draw * @param {string} type - Layer type to draw * @returns {boolean} * @private */ _shouldUpdate: function(date, type) { var prevDate = this._date; if (!dateUtil.isValidDate(date)) { throw new Error('Invalid date'); } if (!this._isValidType(type)) { throw new Error('Invalid layer type'); } return ( !prevDate || prevDate.getFullYear() !== date.getFullYear() || prevDate.getMonth() !== date.getMonth() || this.getType() !== type ); }, /** * Render header & body elements * @private */ _render: function() { var date = this._date; var type = this.getType(); this._header.render(date, type); this._body.render(date, type); removeClass(this._element, CLASS_NAME_CALENDAR_MONTH, CLASS_NAME_CALENDAR_YEAR); switch (type) { case TYPE_MONTH: addClass(this._element, CLASS_NAME_CALENDAR_MONTH); break; case TYPE_YEAR: addClass(this._element, CLASS_NAME_CALENDAR_YEAR); break; default: break; } }, /** * Returns relative date * @param {number} step - Month step * @returns {Date} * @private */ _getRelativeDate: function(step) { var prev = this._date; return new Date(prev.getFullYear(), prev.getMonth() + step); }, /** * Draw the calendar. * @param {Object} [options] - Draw options * @param {Date} [options.date] - Date to set * @param {('date'|'month'|'year')} [options.type = 'date'] - Calendar type. Determine whether to show a date, month, or year. * @example * calendar.draw(); * calendar.draw({ * date: new Date() * }); * calendar.draw({ * type: 'month' * }); * calendar.draw({ * type: 'month', * date: new Date() * }); */ draw: function(options) { var date, type; options = options || {}; date = options.date || this._date; type = (options.type || this.getType()).toLowerCase(); if (this._shouldUpdate(date, type)) { this._date = date; this._type = type; this._render(); } /** * Occur after the calendar draws. * @event Calendar#draw * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#on calendar.on()} to bind event handlers. * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#off calendar.off()} to unbind event handlers. * @see Refer to {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents CustomEvents from tui-code-snippet} for more methods. Calendar mixes in the methods from CustomEvents. * @property {Date} date - Calendar date * @property {('date'|'month'|'year')} type - Calendar type * @property {HTMLElement[]} dateElements - elements for dates * @example * // bind the 'draw' event * calendar.on('draw', ({type, date}) => { * console.log(`Draw the ${type} calendar and its date is ${date}.`); * }); * * // unbind the 'draw' event * calendar.off('draw'); */ this.fire('draw', { date: this._date, type: type, dateElements: this._body.getDateElements() }); }, /** * Show the calendar. */ show: function() { removeClass(this._element, CLASS_NAME_HIDDEN); }, /** * Hide the calendar. */ hide: function() { addClass(this._element, CLASS_NAME_HIDDEN); }, /** * Draw the next page. */ drawNext: function() { this.draw({ date: this.getNextDate() }); }, /** * Draw the previous page. */ drawPrev: function() { this.draw({ date: this.getPrevDate() }); }, /** * Return the next date. * @returns {Date} */ getNextDate: function() { if (this.getType() === TYPE_DATE) { return this._getRelativeDate(1); } return this.getNextYearDate(); }, /** * Return the previous date. * @returns {Date} */ getPrevDate: function() { if (this.getType() === TYPE_DATE) { return this._getRelativeDate(-1); } return this.getPrevYearDate(); }, /** * Return the date a year later. * @returns {Date} */ getNextYearDate: function() { switch (this.getType()) { case TYPE_DATE: case TYPE_MONTH: return this._getRelativeDate(12); // 12 months = 1 year case TYPE_YEAR: return this._getRelativeDate(108); // 108 months = 9 years = 12 * 9 default: throw new Error('Unknown layer type'); } }, /** * Return the date a year previously. * @returns {Date} */ getPrevYearDate: function() { switch (this.getType()) { case TYPE_DATE: case TYPE_MONTH: return this._getRelativeDate(-12); // 12 months = 1 year case TYPE_YEAR: return this._getRelativeDate(-108); // 108 months = 9 years = 12 * 9 default: throw new Error('Unknown layer type'); } }, /** * Change language. * @param {string} language - Language code. English('en') and Korean('ko') are provided as default. * @see To set to the other languages, use {@link DatePicker#localeTexts DatePicker.localeTexts}. */ changeLanguage: function(language) { this._header.changeLanguage(language); this._body.changeLanguage(language); this._render(); }, /** * Return the rendered date. * @returns {Date} */ getDate: function() { return new Date(this._date); }, /** * Return the calendar's type. * @returns {('date'|'month'|'year')} */ getType: function() { return this._type; }, /** * Returns HTML elements for dates. * @returns {HTMLElement[]} */ getDateElements: function() { return this._body.getDateElements(); }, /** * Apply a CSS class to the calendar. * @param {string} className - Class name */ addCssClass: function(className) { addClass(this._element, className); }, /** * Remove a CSS class from the calendar. * @param {string} className - Class name */ removeCssClass: function(className) { removeClass(this._element, className); }, /** * Destroy the calendar. */ destroy: function() { this._header.destroy(); this._body.destroy(); removeElement(this._element); this._type = this._date = this._container = this._element = this._header = this._body = null; } } ); CustomEvents.mixin(Calendar); module.exports = Calendar; /***/ }), /* 30 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Date <-> Text formatting module * @author NHN. FE Development Lab */ var inArray = __webpack_require__(3); var forEachArray = __webpack_require__(2); var defineClass = __webpack_require__(0); var util = __webpack_require__(4); var dateUtil = __webpack_require__(5); var constants = __webpack_require__(1); var localeTexts = __webpack_require__(10); var rFormableKeys = /\\?(yyyy|yy|mmmm|mmm|mm|m|dd|d|hh|h|a)/gi; var mapForConverting = { yyyy: { expression: '(\\d{4}|\\d{2})', type: constants.TYPE_YEAR }, yy: { expression: '(\\d{4}|\\d{2})', type: constants.TYPE_YEAR }, y: { expression: '(\\d{4}|\\d{2})', type: constants.TYPE_YEAR }, M: { expression: '(1[012]|0[1-9]|[1-9])', type: constants.TYPE_MONTH }, MM: { expression: '(1[012]|0[1-9]|[1-9])', type: constants.TYPE_MONTH }, MMM: { expression: '(1[012]|0[1-9]|[1-9])', type: constants.TYPE_MONTH }, MMMM: { expression: '(1[012]|0[1-9]|[1-9])', type: constants.TYPE_MONTH }, mmm: { expression: '(1[012]|0[1-9]|[1-9])', type: constants.TYPE_MONTH }, mmmm: { expression: '(1[012]|0[1-9]|[1-9])', type: constants.TYPE_MONTH }, dd: { expression: '([12]\\d{1}|3[01]|0[1-9]|[1-9])', type: constants.TYPE_DATE }, d: { expression: '([12]\\d{1}|3[01]|0[1-9]|[1-9])', type: constants.TYPE_DATE }, D: { expression: '([12]\\d{1}|3[01]|0[1-9]|[1-9])', type: constants.TYPE_DATE }, DD: { expression: '([12]\\d{1}|3[01]|0[1-9]|[1-9])', type: constants.TYPE_DATE }, h: { expression: '(d{1}|0\\d{1}|1\\d{1}|2[0123])', type: constants.TYPE_HOUR }, hh: { expression: '(d{1}|[01]\\d{1}|2[0123])', type: constants.TYPE_HOUR }, H: { expression: '(d{1}|0\\d{1}|1\\d{1}|2[0123])', type: constants.TYPE_HOUR }, HH: { expression: '(d{1}|[01]\\d{1}|2[0123])', type: constants.TYPE_HOUR }, m: { expression: '(d{1}|[012345]\\d{1})', type: constants.TYPE_MINUTE }, mm: { expression: '(d{1}|[012345]\\d{1})', type: constants.TYPE_MINUTE }, a: { expression: '([ap]m)', type: constants.TYPE_MERIDIEM }, A: { expression: '([ap]m)', type: constants.TYPE_MERIDIEM } }; /** * @class * @ignore */ var DateTimeFormatter = defineClass( /** @lends DateTimeFormatter.prototype */ { init: function(rawStr, titles) { /** * @type {string} * @private */ this._rawStr = rawStr; /** * @type {Array} * @private * @example * rawStr = "yyyy-MM-dd" --> keyOrder = ['year', 'month', 'date'] * rawStr = "MM/dd, yyyy" --> keyOrder = ['month', 'date', 'year'] */ this._keyOrder = null; /** * @type {RegExp} * @private */ this._regExp = null; /** * Titles * @type {object} * @private */ this._titles = titles || localeTexts.en.titles; this._parseFormat(); }, /** * Parse initial format and make the keyOrder, regExp * @private */ _parseFormat: function() { var regExpStr = '^'; var matchedKeys = this._rawStr.match(rFormableKeys); var keyOrder = []; matchedKeys = util.filter(matchedKeys, function(key) { return key[0] !== '\\'; }); forEachArray(matchedKeys, function(key, index) { if (!/m/i.test(key)) { key = key.toLowerCase(); } regExpStr += mapForConverting[key].expression + '[\\D\\s]*'; keyOrder[index] = mapForConverting[key].type; }); // This formatter does not allow additional numbers at the end of string. regExpStr += '$'; this._keyOrder = keyOrder; this._regExp = new RegExp(regExpStr, 'gi'); }, /** * Parse string to dateHash * @param {string} str - Date string * @returns {Date} */ parse: function(str) { var dateHash = { year: 0, month: 1, date: 1, hour: 0, minute: 0 }; var hasMeridiem = false; var isPM = false; var matched; this._regExp.lastIndex = 0; matched = this._regExp.exec(str); if (!matched) { throw Error('DateTimeFormatter: Not matched - "' + str + '"'); } // eslint-disable-next-line complexity forEachArray(this._keyOrder, function(name, index) { var value = matched[index + 1]; if (name === constants.TYPE_MERIDIEM && /[ap]m/i.test(value)) { hasMeridiem = true; isPM = /pm/i.test(value); } else { value = Number(value); if (value !== 0 && !value) { throw Error('DateTimeFormatter: Unknown value - ' + matched[index + 1]); } if (name === constants.TYPE_YEAR && value < 100) { value += 2000; } dateHash[name] = value; } }); if (hasMeridiem) { isPM = isPM || dateHash.hour > 12; dateHash.hour %= 12; if (isPM) { dateHash.hour += 12; } } return new Date( dateHash.year, dateHash.month - 1, dateHash.date, dateHash.hour, dateHash.minute ); }, /** * Returns raw string of format * @returns {string} */ getRawString: function() { return this._rawStr; }, /** * Format date to string * @param {Date} dateObj - Date object * @returns {string} */ format: function(dateObj) { var year = dateObj.getFullYear(); var month = dateObj.getMonth() + 1; var dayInMonth = dateObj.getDate(); var day = dateObj.getDay(); var hour = dateObj.getHours(); var minute = dateObj.getMinutes(); var meridiem = 'a'; // Default value for unusing meridiem format var replaceMap; if (inArray(constants.TYPE_MERIDIEM, this._keyOrder) > -1) { meridiem = hour >= 12 ? 'pm' : 'am'; hour = dateUtil.getMeridiemHour(hour); } replaceMap = { yyyy: year, yy: String(year).substr(2, 2), M: month, MM: dateUtil.prependLeadingZero(month), MMM: this._titles.MMM[month - 1], MMMM: this._titles.MMMM[month - 1], d: dayInMonth, dd: dateUtil.prependLeadingZero(dayInMonth), D: this._titles.D[day], DD: this._titles.DD[day], hh: dateUtil.prependLeadingZero(hour), h: hour, mm: dateUtil.prependLeadingZero(minute), m: minute, A: meridiem.toUpperCase(), a: meridiem }; return this._rawStr.replace(rFormableKeys, function(key) { if (key[0] === '\\') { return key.substr(1); } return replaceMap[key] || replaceMap[key.toLowerCase()] || ''; }); } } ); module.exports = DateTimeFormatter; /***/ }), /* 31 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Bind DOM events * @author NHN FE Development Lab */ var isString = __webpack_require__(13); var forEach = __webpack_require__(9); var safeEvent = __webpack_require__(32); /** * Bind DOM events. * @param {HTMLElement} element - element to bind events * @param {(string|object)} types - Space splitted events names or eventName:handler object * @param {(function|object)} handler - handler function or context for handler method * @param {object} [context] context - context for handler method. * @memberof module:domEvent * @example * var div = document.querySelector('div'); * * // Bind one event to an element. * on(div, 'click', toggle); * * // Bind multiple events with a same handler to multiple elements at once. * // Use event names splitted by a space. * on(div, 'mouseenter mouseleave', changeColor); * * // Bind multiple events with different handlers to an element at once. * // Use an object which of key is an event name and value is a handler function. * on(div, { * keydown: highlight, * keyup: dehighlight * }); * * // Set a context for handler method. * var name = 'global'; * var repository = {name: 'CodeSnippet'}; * on(div, 'drag', function() { * console.log(this.name); * }, repository); * // Result when you drag a div: "CodeSnippet" */ function on(element, types, handler, context) { if (isString(types)) { forEach(types.split(/\s+/g), function(type) { bindEvent(element, type, handler, context); }); return; } forEach(types, function(func, type) { bindEvent(element, type, func, handler); }); } /** * Bind DOM events * @param {HTMLElement} element - element to bind events * @param {string} type - events name * @param {function} handler - handler function or context for handler method * @param {object} [context] context - context for handler method. * @private */ function bindEvent(element, type, handler, context) { /** * Event handler * @param {Event} e - event object */ function eventHandler(e) { handler.call(context || element, e || window.event); } if ('addEventListener' in element) { element.addEventListener(type, eventHandler); } else if ('attachEvent' in element) { element.attachEvent('on' + type, eventHandler); } memorizeHandler(element, type, handler, eventHandler); } /** * Memorize DOM event handler for unbinding. * @param {HTMLElement} element - element to bind events * @param {string} type - events name * @param {function} handler - handler function that user passed at on() use * @param {function} wrappedHandler - handler function that wrapped by domevent for implementing some features * @private */ function memorizeHandler(element, type, handler, wrappedHandler) { var events = safeEvent(element, type); var existInEvents = false; forEach(events, function(obj) { if (obj.handler === handler) { existInEvents = true; return false; } return true; }); if (!existInEvents) { events.push({ handler: handler, wrappedHandler: wrappedHandler }); } } module.exports = on; /***/ }), /* 32 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Get event collection for specific HTML element * @author NHN FE Development Lab */ var EVENT_KEY = '_feEventKey'; /** * Get event collection for specific HTML element * @param {HTMLElement} element - HTML element * @param {string} type - event type * @returns {array} * @private */ function safeEvent(element, type) { var events = element[EVENT_KEY]; var handlers; if (!events) { events = element[EVENT_KEY] = {}; } handlers = events[type]; if (!handlers) { handlers = events[type] = []; } return handlers; } module.exports = safeEvent; /***/ }), /* 33 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Unbind DOM events * @author NHN FE Development Lab */ var isString = __webpack_require__(13); var forEach = __webpack_require__(9); var safeEvent = __webpack_require__(32); /** * Unbind DOM events * If a handler function is not passed, remove all events of that type. * @param {HTMLElement} element - element to unbind events * @param {(string|object)} types - Space splitted events names or eventName:handler object * @param {function} [handler] - handler function * @memberof module:domEvent * @example * // Following the example of domEvent#on * * // Unbind one event from an element. * off(div, 'click', toggle); * * // Unbind multiple events with a same handler from multiple elements at once. * // Use event names splitted by a space. * off(element, 'mouseenter mouseleave', changeColor); * * // Unbind multiple events with different handlers from an element at once. * // Use an object which of key is an event name and value is a handler function. * off(div, { * keydown: highlight, * keyup: dehighlight * }); * * // Unbind events without handlers. * off(div, 'drag'); */ function off(element, types, handler) { if (isString(types)) { forEach(types.split(/\s+/g), function(type) { unbindEvent(element, type, handler); }); return; } forEach(types, function(func, type) { unbindEvent(element, type, func); }); } /** * Unbind DOM events * If a handler function is not passed, remove all events of that type. * @param {HTMLElement} element - element to unbind events * @param {string} type - events name * @param {function} [handler] - handler function * @private */ function unbindEvent(element, type, handler) { var events = safeEvent(element, type); var index; if (!handler) { forEach(events, function(item) { removeHandler(element, type, item.wrappedHandler); }); events.splice(0, events.length); } else { forEach(events, function(item, idx) { if (handler === item.handler) { removeHandler(element, type, item.wrappedHandler); index = idx; return false; } return true; }); events.splice(index, 1); } } /** * Remove an event handler * @param {HTMLElement} element - An element to remove an event * @param {string} type - event type * @param {function} handler - event handler * @private */ function removeHandler(element, type, handler) { if ('removeEventListener' in element) { element.removeEventListener(type, handler); } else if ('detachEvent' in element) { element.detachEvent('on' + type, handler); } } module.exports = off; /***/ }), /* 34 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview The entry file of DatePicker components * @author NHN. FE Development Team */ var DatePicker = __webpack_require__(21); var DateRangePicker = __webpack_require__(60); var Calendar = __webpack_require__(29); __webpack_require__(61); /** * Create a calendar. * @see {@link Calendar} * @see {@link /tutorial-example07-calendar Calendar example} * @static * @param {HTMLElement|string} wrapperElement - Container element or selector of the Calendar * @param {Object} [options] - {@link Calendar} options. Refer to the {@link Calendar Calendar instance's options}. * @returns {Calendar} * @example * const calendar = DatePicker.createCalendar('#calendar-wrapper', { * language: 'en', * showToday: true, * showJumpButtons: false, * date: new Date(), * type: 'date' * }); */ DatePicker.createCalendar = function(wrapperElement, options) { return new Calendar(wrapperElement, options); }; /** * Create a date-range picker. * @see {@link DateRangePicker} * @see {@link /tutorial-example08-daterangepicker DateRangePicker example} * @static * @param {object} options - {@link DateRangePicker} options. Refer to the {@link DateRangePicker DateRangePicker instance's options}. * @returns {DateRangePicker} * @example * const rangepicker = DatePicker.createRangePicker({ * startpicker: { * input: '#start-input', * container: '#start-container' * }, * endpicker: { * input: '#end-input', * container: '#end-container' * }, * type: 'date', * format: 'yyyy-MM-dd' * selectableRanges: [ * [new Date(2017, 3, 1), new Date(2017, 5, 1)], * [new Date(2017, 6, 3), new Date(2017, 10, 5)] * ] * }); */ DatePicker.createRangePicker = function(options) { return new DateRangePicker(options); }; module.exports = DatePicker; /***/ }), /* 35 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Provide a simple inheritance in prototype-oriented. * @author NHN FE Development Lab */ var createObject = __webpack_require__(36); /** * Provide a simple inheritance in prototype-oriented. * Caution : * Don't overwrite the prototype of child constructor. * * @param {function} subType Child constructor * @param {function} superType Parent constructor * @memberof module:inheritance * @example * var inherit = require('tui-code-snippet/inheritance/inherit'); // node, commonjs * * // Parent constructor * function Animal(leg) { * this.leg = leg; * } * Animal.prototype.growl = function() { * // ... * }; * * // Child constructor * function Person(name) { * this.name = name; * } * * // Inheritance * inherit(Person, Animal); * * // After this inheritance, please use only the extending of property. * // Do not overwrite prototype. * Person.prototype.walk = function(direction) { * // ... * }; */ function inherit(subType, superType) { var prototype = createObject(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; } module.exports = inherit; /***/ }), /* 36 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Create a new object with the specified prototype object and properties. * @author NHN FE Development Lab */ /** * @module inheritance */ /** * Create a new object with the specified prototype object and properties. * @param {Object} obj This object will be a prototype of the newly-created object. * @returns {Object} * @memberof module:inheritance */ function createObject(obj) { function F() {} // eslint-disable-line require-jsdoc F.prototype = obj; return new F(); } module.exports = createObject; /***/ }), /* 37 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is existing or not. * @author NHN FE Development Lab */ var isUndefined = __webpack_require__(12); var isNull = __webpack_require__(38); /** * Check whether the given variable is existing or not. * If the given variable is not null and not undefined, returns true. * @param {*} param - Target for checking * @returns {boolean} Is existy? * @memberof module:type * @example * var isExisty = require('tui-code-snippet/type/isExisty'); // node, commonjs * * isExisty(''); //true * isExisty(0); //true * isExisty([]); //true * isExisty({}); //true * isExisty(null); //false * isExisty(undefined); //false */ function isExisty(param) { return !isUndefined(param) && !isNull(param); } module.exports = isExisty; /***/ }), /* 38 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is null or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is null or not. * If the given variable(arguments[0]) is null, returns true. * @param {*} obj - Target for checking * @returns {boolean} Is null? * @memberof module:type */ function isNull(obj) { return obj === null; } module.exports = isNull; /***/ }), /* 39 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is a function or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is a function or not. * If the given variable is a function, return true. * @param {*} obj - Target for checking * @returns {boolean} Is function? * @memberof module:type */ function isFunction(obj) { return obj instanceof Function; } module.exports = isFunction; /***/ }), /* 40 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check element match selector * @author NHN FE Development Lab */ var inArray = __webpack_require__(3); var toArray = __webpack_require__(41); var elProto = Element.prototype; var matchSelector = elProto.matches || elProto.webkitMatchesSelector || elProto.mozMatchesSelector || elProto.msMatchesSelector || function(selector) { var doc = this.document || this.ownerDocument; return inArray(this, toArray(doc.querySelectorAll(selector))) > -1; }; /** * Check element match selector * @param {HTMLElement} element - element to check * @param {string} selector - selector to check * @returns {boolean} is selector matched to element? * @memberof module:domUtil */ function matches(element, selector) { return matchSelector.call(element, selector); } module.exports = matches; /***/ }), /* 41 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Transform the Array-like object to Array. * @author NHN FE Development Lab */ var forEachArray = __webpack_require__(2); /** * Transform the Array-like object to Array. * In low IE (below 8), Array.prototype.slice.call is not perfect. So, try-catch statement is used. * @param {*} arrayLike Array-like object * @returns {Array} Array * @memberof module:collection * @example * var toArray = require('tui-code-snippet/collection/toArray'); // node, commonjs * * var arrayLike = { * 0: 'one', * 1: 'two', * 2: 'three', * 3: 'four', * length: 4 * }; * var result = toArray(arrayLike); * * alert(result instanceof Array); // true * alert(result); // one,two,three,four */ function toArray(arrayLike) { var arr; try { arr = Array.prototype.slice.call(arrayLike); } catch (e) { arr = []; forEachArray(arrayLike, function(value) { arr.push(value); }); } return arr; } module.exports = toArray; /***/ }), /* 42 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Convert kebab-case * @author NHN FE Development Lab */ /** * Convert kebab-case * @param {string} key - string to be converted to Kebab-case * @private */ function convertToKebabCase(key) { return key.replace(/([A-Z])/g, function(match) { return '-' + match.toLowerCase(); }); } module.exports = convertToKebabCase; /***/ }), /* 43 */ /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE__43__; /***/ }), /* 44 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Calendar Header * @author NHN. FE dev Lab */ var defineClass = __webpack_require__(0); var CustomEvents = __webpack_require__(8); var closest = __webpack_require__(25); var removeElement = __webpack_require__(14); var localeTexts = __webpack_require__(10); var headerTmpl = __webpack_require__(45); var DateTimeFormatter = __webpack_require__(30); var constants = __webpack_require__(1); var util = __webpack_require__(4); var mouseTouchEvent = __webpack_require__(19); var TYPE_DATE = constants.TYPE_DATE; var TYPE_MONTH = constants.TYPE_MONTH; var TYPE_YEAR = constants.TYPE_YEAR; var CLASS_NAME_TITLE_MONTH = 'tui-calendar-title-month'; var CLASS_NAME_TITLE_YEAR = 'tui-calendar-title-year'; var CLASS_NAME_TITLE_YEAR_TO_YEAR = 'tui-calendar-title-year-to-year'; var SELECTOR_INNER_ELEM = '.tui-calendar-header-inner'; var SELECTOR_INFO_ELEM = '.tui-calendar-header-info'; var SELECTOR_BTN = '.tui-calendar-btn'; var YEAR_TITLE_FORMAT = 'yyyy'; /** * @ignore * @class * @param {string|HTMLElement} container - Header container or selector * @param {object} option - Header option * @param {string} option.language - Header language * @param {boolean} option.showToday - Has today box or not. * @param {boolean} option.showJumpButtons - Has jump buttons or not. */ var Header = defineClass( /** @lends Header.prototype */ { init: function(container, option) { /** * Container element * @type {HTMLElement} * @private */ this._container = util.getElement(container); /** * Header inner element * @type {HTMLElement} * @private */ this._innerElement = null; /** * Header info element * @type {HTMLElement} * @private */ this._infoElement = null; /** * Render today box or not * @type {boolean} * @private */ this._showToday = option.showToday; /** * Render jump buttons or not (next,prev year on date calendar) * @type {boolean} * @private */ this._showJumpButtons = option.showJumpButtons; /** * Year_Month title formatter * @type {DateTimeFormatter} * @private */ this._yearMonthTitleFormatter = null; /** * Year title formatter * @type {DateTimeFormatter} * @private */ this._yearTitleFormatter = null; /** * Today formatter * @type {DateTimeFormatter} * @private */ this._todayFormatter = null; this._setFormatters(localeTexts[option.language]); this._setEvents(option); }, /** * @param {object} localeText - Locale text * @private */ _setFormatters: function(localeText) { this._yearMonthTitleFormatter = new DateTimeFormatter( localeText.titleFormat, localeText.titles ); this._yearTitleFormatter = new DateTimeFormatter(YEAR_TITLE_FORMAT, localeText.titles); this._todayFormatter = new DateTimeFormatter(localeText.todayFormat, localeText.titles); }, /** * @param {object} option - Constructor option * @private */ _setEvents: function() { mouseTouchEvent.on(this._container, 'click', this._onClickHandler, this); }, /** * @private */ _removeEvents: function() { this.off(); mouseTouchEvent.off(this._container, 'click', this._onClickHandler); }, /** * Fire customEvents * @param {Event} ev An event object * @private */ _onClickHandler: function(ev) { var target = util.getTarget(ev); if (closest(target, SELECTOR_BTN)) { this.fire('click', ev); } }, /** * @param {string} type - Calendar type * @returns {string} * @private */ _getTitleClass: function(type) { switch (type) { case TYPE_DATE: return CLASS_NAME_TITLE_MONTH; case TYPE_MONTH: return CLASS_NAME_TITLE_YEAR; case TYPE_YEAR: return CLASS_NAME_TITLE_YEAR_TO_YEAR; default: return ''; } }, /** * @param {Date} date - date * @param {string} type - Calendar type * @returns {string} * @private */ _getTitleText: function(date, type) { var currentYear, start, end; switch (type) { case TYPE_DATE: return this._yearMonthTitleFormatter.format(date); case TYPE_MONTH: return this._yearTitleFormatter.format(date); case TYPE_YEAR: currentYear = date.getFullYear(); start = new Date(currentYear - 4, 0, 1); end = new Date(currentYear + 4, 0, 1); return ( this._yearTitleFormatter.format(start) + ' - ' + this._yearTitleFormatter.format(end) ); default: return ''; } }, /** * Change langauge * @param {string} language - Language */ changeLanguage: function(language) { this._setFormatters(localeTexts[language]); }, /** * Render header * @param {Date} date - date * @param {string} type - Calendar type */ render: function(date, type) { var context = { showToday: this._showToday, showJumpButtons: this._showJumpButtons, todayText: this._todayFormatter.format(new Date()), isDateCalendar: type === TYPE_DATE, titleClass: this._getTitleClass(type), title: this._getTitleText(date, type) }; this._container.innerHTML = headerTmpl(context).replace(/^\s+|\s+$/g, ''); this._innerElement = this._container.querySelector(SELECTOR_INNER_ELEM); if (context.showToday) { this._infoElement = this._container.querySelector(SELECTOR_INFO_ELEM); } }, /** * Destroy header */ destroy: function() { this._removeEvents(); removeElement(this._innerElement); removeElement(this._infoElement); this._container = this._showToday = this._showJumpButtons = this._yearMonthTitleFormatter = this._yearTitleFormatter = this._todayFormatter = this._innerElement = this._infoElement = null; } } ); CustomEvents.mixin(Header); module.exports = Header; /***/ }), /* 45 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var template = __webpack_require__(11); module.exports = function(context) { var source = '{{if isDateCalendar}}' + ' {{if showJumpButtons}}' + '
' + ' ' + ' ' + ' {{title}}' + ' ' + ' ' + '
' + ' {{else}}' + '
' + ' ' + ' {{title}}' + ' ' + '
' + ' {{/if}}' + '{{else}}' + '
' + ' ' + ' {{title}}' + ' ' + '
' + '{{/if}}' + '{{if showToday}}' + '
' + '

{{todayText}}

' + '
' + '{{/if}}'; return template(source, context); }; /***/ }), /* 46 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Check whether the given variable is a instance of HTMLNode or not. * @author NHN FE Development Lab */ /** * Check whether the given variable is a instance of HTMLNode or not. * If the given variables is a instance of HTMLNode, return true. * @param {*} html - Target for checking * @returns {boolean} Is HTMLNode ? * @memberof module:type */ function isHTMLNode(html) { if (typeof HTMLElement === 'object') { return (html && (html instanceof HTMLElement || !!html.nodeType)); } return !!(html && html.nodeType); } module.exports = isHTMLNode; /***/ }), /* 47 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Send hostname on DOMContentLoaded. * @author NHN FE Development Lab */ var isUndefined = __webpack_require__(12); var imagePing = __webpack_require__(48); var ms7days = 7 * 24 * 60 * 60 * 1000; /** * Check if the date has passed 7 days * @param {number} date - milliseconds * @returns {boolean} * @private */ function isExpired(date) { var now = new Date().getTime(); return now - date > ms7days; } /** * Send hostname on DOMContentLoaded. * To prevent hostname set tui.usageStatistics to false. * @param {string} appName - application name * @param {string} trackingId - GA tracking ID * @ignore */ function sendHostname(appName, trackingId) { var url = 'https://www.google-analytics.com/collect'; var hostname = location.hostname; var hitType = 'event'; var eventCategory = 'use'; var applicationKeyForStorage = 'TOAST UI ' + appName + ' for ' + hostname + ': Statistics'; var date = window.localStorage.getItem(applicationKeyForStorage); // skip if the flag is defined and is set to false explicitly if (!isUndefined(window.tui) && window.tui.usageStatistics === false) { return; } // skip if not pass seven days old if (date && !isExpired(date)) { return; } window.localStorage.setItem(applicationKeyForStorage, new Date().getTime()); setTimeout(function() { if (document.readyState === 'interactive' || document.readyState === 'complete') { imagePing(url, { v: 1, t: hitType, tid: trackingId, cid: hostname, dp: hostname, dh: appName, el: appName, ec: eventCategory }); } }, 1000); } module.exports = sendHostname; /***/ }), /* 48 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Request image ping. * @author NHN FE Development Lab */ var forEachOwnProperties = __webpack_require__(23); /** * @module request */ /** * Request image ping. * @param {String} url url for ping request * @param {Object} trackingInfo infos for make query string * @returns {HTMLElement} * @memberof module:request * @example * var imagePing = require('tui-code-snippet/request/imagePing'); // node, commonjs * * imagePing('https://www.google-analytics.com/collect', { * v: 1, * t: 'event', * tid: 'trackingid', * cid: 'cid', * dp: 'dp', * dh: 'dh' * }); */ function imagePing(url, trackingInfo) { var trackingElement = document.createElement('img'); var queryString = ''; forEachOwnProperties(trackingInfo, function(value, key) { queryString += '&' + key + '=' + value; }); queryString = queryString.substring(1); trackingElement.src = url + '?' + queryString; trackingElement.style.display = 'none'; document.body.appendChild(trackingElement); document.body.removeChild(trackingElement); return trackingElement; } module.exports = imagePing; /***/ }), /* 49 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Calendar body * @author NHN. FE Development Lab */ var forEachArray = __webpack_require__(2); var defineClass = __webpack_require__(0); var DateLayer = __webpack_require__(50); var MonthLayer = __webpack_require__(52); var YearLayer = __webpack_require__(54); var constants = __webpack_require__(1); var TYPE_DATE = constants.TYPE_DATE; var TYPE_MONTH = constants.TYPE_MONTH; var TYPE_YEAR = constants.TYPE_YEAR; /** * @ignore * @class */ var Body = defineClass( /** @lends Body.prototype */ { init: function(bodyContainer, options) { var language = options.language; var weekStartDay = options.weekStartDay; /** * Body container element * @type {HTMLElement} * @private */ this._container = bodyContainer; /** * DateLayer * @type {DateLayer} * @private */ this._dateLayer = new DateLayer(language, weekStartDay); /** * MonthLayer * @type {MonthLayer} * @private */ this._monthLayer = new MonthLayer(language); /** * YearLayer * @type {YearLayer} * @private */ this._yearLayer = new YearLayer(language); /** * Current Layer * @type {DateLayer|MonthLayer|YearLayer} * @private */ this._currentLayer = this._dateLayer; }, /** * Returns matched layer * @param {string} type - Layer type * @returns {Base} - Layer * @private */ _getLayer: function(type) { switch (type) { case TYPE_DATE: return this._dateLayer; case TYPE_MONTH: return this._monthLayer; case TYPE_YEAR: return this._yearLayer; default: return this._currentLayer; } }, /** * Iterate each layer * @param {Function} fn - function * @private */ _eachLayer: function(fn) { forEachArray([this._dateLayer, this._monthLayer, this._yearLayer], fn); }, /** * Change language * @param {string} language - Language */ changeLanguage: function(language) { this._eachLayer(function(layer) { layer.changeLanguage(language); }); }, /** * Render body * @param {Date} date - date * @param {string} type - Layer type */ render: function(date, type) { var nextLayer = this._getLayer(type); var prevLayer = this._currentLayer; prevLayer.remove(); nextLayer.render(date, this._container); this._currentLayer = nextLayer; }, /** * Returns date elements * @returns {HTMLElement[]} */ getDateElements: function() { return this._currentLayer.getDateElements(); }, /** * Destory */ destroy: function() { this._eachLayer(function(layer) { layer.remove(); }); this._container = this._currentLayer = this._dateLayer = this._monthLayer = this._yearLayer = null; } } ); module.exports = Body; /***/ }), /* 50 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Date layer * @author NHN. FE Development Lab */ var defineClass = __webpack_require__(0); var dateUtil = __webpack_require__(5); var bodyTmpl = __webpack_require__(51); var LayerBase = __webpack_require__(20); var TYPE_DATE = __webpack_require__(1).TYPE_DATE; var WEEK_START_DAY_MAP = __webpack_require__(1).WEEK_START_DAY_MAP; var DATE_SELECTOR = '.tui-calendar-date'; var DAYS_OF_WEEK = 7; /** * @ignore * @class * @extends LayerBase * @param {string} language - Initial language */ var DateLayer = defineClass( LayerBase, /** @lends DateLayer.prototype */ { init: function(language, weekStartDay) { LayerBase.call(this, language); this.weekStartDay = WEEK_START_DAY_MAP[String(weekStartDay).toLowerCase()] || 0; }, /** * Layer type * @type {string} * @private */ _type: TYPE_DATE, /** * @override * @private * @returns {object} Template context */ _makeContext: function(date) { var daysShort = this._localeText.titles.D; var year, month, days, i; date = date || new Date(); year = date.getFullYear(); month = date.getMonth() + 1; if (this.weekStartDay) { days = daysShort.slice(); for (i = 0; i < this.weekStartDay; i += 1) { days.push(days.shift()); } daysShort = days; } return { Sun: daysShort[0], Mon: daysShort[1], Tue: daysShort[2], Wed: daysShort[3], Thu: daysShort[4], Fri: daysShort[5], Sat: daysShort[6], year: year, month: month, weeks: this._getWeeks(year, month) }; }, /** * weeks (templating) for date-calendar * @param {number} year - Year * @param {number} month - Month * @returns {Array.>} * @private */ _getWeeks: function(year, month) { var weekNumber = 0; var weeksCount = 6; // Fix for no changing height var weeks = []; var week, dates, i; while (weekNumber < weeksCount) { dates = []; for (i = this.weekStartDay; i < DAYS_OF_WEEK + this.weekStartDay; i += 1) { dates.push(dateUtil.getDateOfWeek(year, month, weekNumber, i)); } week = this._getWeek(year, month, dates); if (this.weekStartDay && !_isFirstWeek(weekNumber, week[0].dayInMonth)) { weeks.push(this._getFirstWeek(year, month)); weeksCount -= 1; // Fix for no changing height } weeks.push(week); weekNumber += 1; } return weeks; }, /** * week (templating) for date-calendar * @param {number} currentYear * @param {number} currentMonth * @param {Array.} dates * @private */ _getWeek: function(currentYear, currentMonth, dates) { var firstDateOfCurrentMonth = new Date(currentYear, currentMonth - 1, 1); var lastDateOfCurrentMonth = new Date(currentYear, currentMonth, 0); var contexts = []; var i = 0; var length = dates.length; var date, className; for (; i < length; i += 1) { className = 'tui-calendar-date'; date = dates[i]; if (date < firstDateOfCurrentMonth) { className += ' tui-calendar-prev-month'; } if (date > lastDateOfCurrentMonth) { className += ' tui-calendar-next-month'; } if (date.getDay() === 0) { className += ' tui-calendar-sun'; } else if (date.getDay() === 6) { className += ' tui-calendar-sat'; } contexts.push({ dayInMonth: date.getDate(), className: className, timestamp: date.getTime() }); } return contexts; }, /** * Render date-layer * @override * @param {Date} date Date to render * @param {HTMLElement} container A container element for the rendered element */ render: function(date, container) { var context = this._makeContext(date); container.innerHTML = bodyTmpl(context); this._element = container.firstChild; }, /** * Return date elements * @override * @returns {HTMLElement[]} */ getDateElements: function() { return this._element.querySelectorAll(DATE_SELECTOR); }, _getFirstWeek: function(year, month) { var firstWeekDates = []; var i; for (i = this.weekStartDay; i < DAYS_OF_WEEK + this.weekStartDay; i += 1) { firstWeekDates.push(dateUtil.getDateOfWeek(year, month, -1, i)); } return this._getWeek(year, month, firstWeekDates); } } ); function _isFirstWeek(weekIndex, dayInMonth) { return weekIndex || dayInMonth === 1 || dayInMonth > DAYS_OF_WEEK; } module.exports = DateLayer; /***/ }), /* 51 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var template = __webpack_require__(11); module.exports = function(context) { var source = '' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' {{each weeks}}' + ' ' + ' {{each @this}}' + ' ' + ' {{/each}}' + ' ' + ' {{/each}}' + ' ' + '
Dates
{{Sun}}{{Mon}}{{Tue}}{{Wed}}{{Thu}}{{Fri}}{{Sat}}
{{@this["dayInMonth"]}}
'; return template(source, context); }; /***/ }), /* 52 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Month layer * @author NHN. FE Development Lab */ var defineClass = __webpack_require__(0); var bodyTmpl = __webpack_require__(53); var LayerBase = __webpack_require__(20); var TYPE_MONTH = __webpack_require__(1).TYPE_MONTH; var dateUtil = __webpack_require__(5); var DATE_SELECTOR = '.tui-calendar-month'; /** * @class * @extends LayerBase * @param {string} language - Initial language * @ignore */ var MonthLayer = defineClass( LayerBase, /** @lends MonthLayer.prototype */ { init: function(language) { LayerBase.call(this, language); }, /** * Layer type * @type {string} * @private */ _type: TYPE_MONTH, /** * @override * @returns {object} Template context * @private */ _makeContext: function(date) { var monthsShort = this._localeText.titles.MMM; return { year: date.getFullYear(), Jan: monthsShort[0], Feb: monthsShort[1], Mar: monthsShort[2], Apr: monthsShort[3], May: monthsShort[4], Jun: monthsShort[5], Jul: monthsShort[6], Aug: monthsShort[7], Sep: monthsShort[8], Oct: monthsShort[9], Nov: monthsShort[10], Dec: monthsShort[11], getFirstDayTimestamp: dateUtil.getFirstDayTimestamp }; }, /** * Render month-layer element * @override * @param {Date} date Date to render * @param {HTMLElement} container A container element for the rendered element */ render: function(date, container) { var context = this._makeContext(date); container.innerHTML = bodyTmpl(context); this._element = container.firstChild; }, /** * Returns month elements * @override * @returns {HTMLElement[]} */ getDateElements: function() { return this._element.querySelectorAll(DATE_SELECTOR); } } ); module.exports = MonthLayer; /***/ }), /* 53 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var template = __webpack_require__(11); module.exports = function(context) { var source = '' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + '
Months
{{Jan}}{{Feb}}{{Mar}}{{Apr}}
{{May}}{{Jun}}{{Jul}}{{Aug}}
{{Sep}}{{Oct}}{{Nov}}{{Dec}}
'; return template(source, context); }; /***/ }), /* 54 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Year layer * @author NHN. FE Development Lab */ var defineClass = __webpack_require__(0); var bodyTmpl = __webpack_require__(55); var LayerBase = __webpack_require__(20); var TYPE_YEAR = __webpack_require__(1).TYPE_YEAR; var dateUtil = __webpack_require__(5); var DATE_SELECTOR = '.tui-calendar-year'; /** * @class * @extends LayerBase * @param {string} language - Initial language * @ignore */ var YearLayer = defineClass( LayerBase, /** @lends YearLayer.prototype */ { init: function(language) { LayerBase.call(this, language); }, /** * Layer type * @type {string} * @private */ _type: TYPE_YEAR, /** * @override * @returns {object} Template context * @private */ _makeContext: function(date) { var year = date.getFullYear(); return { yearGroups: [ dateUtil.getRangeArr(year - 4, year - 2), dateUtil.getRangeArr(year - 1, year + 1), dateUtil.getRangeArr(year + 2, year + 4) ], getFirstDayTimestamp: dateUtil.getFirstDayTimestamp }; }, /** * Render year-layer element * @override * @param {Date} date Date to render * @param {HTMLElement} container A container element for the rendered element */ render: function(date, container) { var context = this._makeContext(date); container.innerHTML = bodyTmpl(context); this._element = container.firstChild; }, /** * Returns year elements * @override * @returns {HTMLElement[]} */ getDateElements: function() { return this._element.querySelectorAll(DATE_SELECTOR); } } ); module.exports = YearLayer; /***/ }), /* 55 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var template = __webpack_require__(11); module.exports = function(context) { var source = '' + ' ' + ' ' + ' {{each yearGroups}}' + ' ' + ' {{each @this}}' + ' ' + ' {{/each}}' + ' ' + ' {{/each}}' + ' ' + '
Years
' + ' {{@this}}' + '
'; return template(source, context); }; /***/ }), /* 56 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview RangeModel * @author NHN. FE Development Lab */ var forEachArray = __webpack_require__(2); var defineClass = __webpack_require__(0); var isNumber = __webpack_require__(15); var Range = __webpack_require__(57); var util = __webpack_require__(4); /** * @class * @ignore * @param {Array.>} ranges - Ranges */ var RangeModel = defineClass( /** @lends RangeModel.prototype */ { init: function(ranges) { ranges = ranges || []; /** * @type {Array.} * @private */ this._ranges = []; forEachArray( ranges, function(range) { this.add(range[0], range[1]); }, this ); }, /** * Whether the ranges contain a time or time-range * @param {number} start - Start * @param {number} [end] - End * @returns {boolean} */ contains: function(start, end) { var i = 0; var length = this._ranges.length; var range; for (; i < length; i += 1) { range = this._ranges[i]; if (range.contains(start, end)) { return true; } } return false; }, /** * Whether overlaps with a point or range * @param {number} start - Start * @param {number} [end] - End * @returns {boolean} */ hasOverlap: function(start, end) { var i = 0; var length = this._ranges.length; var range; for (; i < length; i += 1) { range = this._ranges[i]; if (range.isOverlapped(start, end)) { return true; } } return false; }, /** * Add range * @param {number} start - Start * @param {number} [end] - End */ add: function(start, end) { var overlapped = false; var i = 0; var len = this._ranges.length; var range; for (; i < len; i += 1) { range = this._ranges[i]; overlapped = range.isOverlapped(start, end); if (overlapped) { range.merge(start, end); break; } if (start < range.start) { break; } } if (!overlapped) { this._ranges.splice(i, 0, new Range(start, end)); } }, /** * Returns minimum value in ranges * @returns {number} */ getMinimumValue: function() { return this._ranges[0].start; }, /** * Returns maximum value in ranges * @returns {number} */ getMaximumValue: function() { var length = this._ranges.length; return this._ranges[length - 1].end; }, /** * @param {number} start - Start * @param {number} [end] - End */ exclude: function(start, end) { if (!isNumber(end)) { end = start; } forEachArray( this._ranges, function(range) { var rangeEnd; if (range.isOverlapped(start, end)) { rangeEnd = range.end; // Save before excluding range.exclude(start, end); if (end + 1 <= rangeEnd) { this.add(end + 1, rangeEnd); // Add split range } } }, this ); // Reduce empty ranges this._ranges = util.filter(this._ranges, function(range) { return !range.isEmpty(); }); }, /** * Returns the first overlapped range from the point or range * @param {number} start - Start * @param {number} end - End * @returns {Array.} - [start, end] */ findOverlappedRange: function(start, end) { var i = 0; var len = this._ranges.length; var range; for (; i < len; i += 1) { range = this._ranges[i]; if (range.isOverlapped(start, end)) { return [range.start, range.end]; } } return null; } } ); module.exports = RangeModel; /***/ }), /* 57 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Range (in RangeModel) * @author NHN. FE Development Lab */ var defineClass = __webpack_require__(0); var isNumber = __webpack_require__(15); /** * @class * @ignore * @param {number} start - Start of range * @param {number} [end] - End of range */ var Range = defineClass( /** @lends Range.prototype */ { init: function(start, end) { this.setRange(start, end); }, /** * Set range * @param {number} start - Start number * @param {number} [end] - End number */ setRange: function(start, end) { if (!isNumber(end)) { end = start; } this.start = Math.min(start, end); this.end = Math.max(start, end); }, /** * Merge range * @param {number} start - Start * @param {number} [end] - End */ merge: function(start, end) { if (!isNumber(start) || !isNumber(end) || !this.isOverlapped(start, end)) { return; } this.start = Math.min(start, this.start); this.end = Math.max(end, this.end); }, /** * Whether being empty. * @returns {boolean} */ isEmpty: function() { return !isNumber(this.start) || !isNumber(this.end); }, /** * Set empty */ setEmpty: function() { this.start = this.end = null; }, /** * Whether containing a range. * @param {number} start - Start * @param {number} [end] - End * @returns {boolean} */ contains: function(start, end) { if (!isNumber(end)) { end = start; } return this.start <= start && end <= this.end; }, /** * Whether overlaps with a range * @param {number} start - Start * @param {number} [end] - End * @returns {boolean} */ isOverlapped: function(start, end) { if (!isNumber(end)) { end = start; } return this.start <= end && this.end >= start; }, /** * Exclude a range * @param {number} start - Start * @param {number} end - End */ exclude: function(start, end) { if (start <= this.start && end >= this.end) { // Excluding range contains this this.setEmpty(); } else if (this.contains(start)) { this.setRange(this.start, start - 1); } else if (this.contains(end)) { this.setRange(end + 1, this.end); } } } ); module.exports = Range; /***/ }), /* 58 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var template = __webpack_require__(11); module.exports = function(context) { var source = '
' + ' {{if timePicker}}' + ' {{if isTab}}' + '
' + ' ' + ' ' + '
' + '
' + '
' + '
' + '
' + ' {{else}}' + '
' + '
' + '
' + ' ' + ' {{/if}}' + ' {{else}}' + '
' + '
' + '
' + ' {{/if}}' + '
'; return template(source, context); }; /***/ }), /* 59 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview DatePicker input(element) component * @author NHN. FE Development Lab */ var defineClass = __webpack_require__(0); var CustomEvents = __webpack_require__(8); var on = __webpack_require__(31); var off = __webpack_require__(33); var DateTimeFormatter = __webpack_require__(30); var mouseTouchEvent = __webpack_require__(19); var util = __webpack_require__(4); var DEFAULT_FORMAT = 'yyyy-MM-dd'; /** * DatePicker Input * @ignore * @class * @param {string|HTMLElement} inputElement - Input element or selector * @param {object} option - Option * @param {string} option.id - Id * @param {string} option.format - Text format */ var DatePickerInput = defineClass( /** @lends DatePickerInput.prototype */ { init: function(inputElement, option) { option.format = option.format || DEFAULT_FORMAT; /** * Input element * @type {HTMLElement} * @private */ this._input = util.getElement(inputElement); /** * Id * @type {string} * @private */ this._id = option.id; /** * LocaleText titles * @type {Object} * @private */ this._titles = option.localeText.titles; /** * Text<->DateTime Formatter * @type {DateTimeFormatter} * @private */ this._formatter = new DateTimeFormatter(option.format, this._titles); this._setEvents(); }, /** * Change locale titles * @param {object} titles - locale text in format */ changeLocaleTitles: function(titles) { this._titles = titles; }, /** * Set input 'click', 'change' event * @private */ _setEvents: function() { if (this._input) { on(this._input, 'change', this._onChangeHandler, this); mouseTouchEvent.on(this._input, 'click', this._onClickHandler, this); } }, /** * Remove events * @private */ _removeEvents: function() { this.off(); if (this._input) { off(this._input, 'change', this._onChangeHandler); mouseTouchEvent.off(this._input, 'click', this._onClickHandler); } }, /** * Onchange handler */ _onChangeHandler: function() { this.fire('change'); }, /** * Onclick handler */ _onClickHandler: function() { this.fire('click'); }, /** * Check element is same as the input element. * @param {HTMLElement} el - To check matched set of elements * @returns {boolean} */ is: function(el) { return this._input === el; }, /** * Enable input */ enable: function() { if (this._input) { this._input.removeAttribute('disabled'); } }, /** * Disable input */ disable: function() { if (this._input) { this._input.setAttribute('disabled', true); } }, /** * Return format * @returns {string} */ getFormat: function() { return this._formatter.getRawString(); }, /** * Set format * @param {string} format - Format */ setFormat: function(format) { if (!format) { return; } this._formatter = new DateTimeFormatter(format, this._titles); }, /** * Clear text */ clearText: function() { if (this._input) { this._input.value = ''; } }, /** * Set value from date * @param {Date} date - Date */ setDate: function(date) { if (this._input) { this._input.value = this._formatter.format(date); } }, /** * Returns date from input-text * @returns {Date} * @throws {Error} */ getDate: function() { var value = ''; if (this._input) { value = this._input.value; } return this._formatter.parse(value); }, /** * Destroy */ destroy: function() { this._removeEvents(); this._input = this._id = this._formatter = null; } } ); CustomEvents.mixin(DatePickerInput); module.exports = DatePickerInput; /***/ }), /* 60 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * @fileoverview Date-Range picker * @author NHN. FE Development Lab */ var forEachArray = __webpack_require__(2); var defineClass = __webpack_require__(0); var CustomEvents = __webpack_require__(8); var addClass = __webpack_require__(16); var getData = __webpack_require__(26); var removeClass = __webpack_require__(18); var extend = __webpack_require__(7); var DatePicker = __webpack_require__(21); var dateUtil = __webpack_require__(5); var constants = __webpack_require__(1); var util = __webpack_require__(4); var CLASS_NAME_RANGE_PICKER = 'tui-rangepicker'; var CLASS_NAME_SELECTED = constants.CLASS_NAME_SELECTED; var CLASS_NAME_SELECTED_RANGE = 'tui-is-selected-range'; /** * @class * @description * Create a date-range picker by {@link DatePicker#createRangePicker DatePicker.createRangePicker()}. * @see {@link /tutorial-example08-daterangepicker DateRangePicker example} * @param {object} options - DateRangePicker options * @param {object} options.startpicker - Startpicker options * @param {HTMLElement|string} options.startpicker.input - Startpicker input element or selector * @param {HTMLElement|string} options.startpicker.container - Startpicker container element or selector * @param {Date|number} [options.startpicker.date] - Initial date of the start picker. Set by a Date instance or a number(timestamp). (default: no initial date) * @param {string} [options.startpicker.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday)) * @param {object} options.endpicker - Endpicker options * @param {HTMLElement|string} options.endpicker.input - Endpicker input element or selector * @param {HTMLElement|string} options.endpicker.container - Endpicker container element or selector * @param {Date|number} [options.endpicker.date] - Initial date of the end picker. Set by a Date instance or a number(timestamp). (default: no initial date) * @param {string} [options.endpicker.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday)) * @param {('date'|'month'|'year')} [options.type = 'date'] - DatePicker type. Determine whether to choose a date, month, or year. * @param {string} [options.language='en'] - Language code. English('en') and Korean('ko') are provided as default. To use the other languages, use {@link DatePicker#localeTexts DatePicker.localeTexts}. * @param {object|boolean} [options.timePicker] - [TimePicker](https://nhn.github.io/tui.time-picker/latest) options. Refer to the [TimePicker instance's options](https://nhn.github.io/tui.time-picker/latest/TimePicker). To create the TimePicker without customization, set to true. * @param {object} [options.calendar] - {@link Calendar} options. Refer to the {@link Calendar Calendar instance's options}. * @param {string} [options.format = 'yyyy-mm-dd'] - Format of the Date string * @param {Array.>} [options.selectableRanges] - Ranges of selectable date. Set by Date instances or numbers(timestamp). * @param {boolean} [options.showAlways = false] - Show the DateRangePicker always * @param {boolean} [options.autoClose = true] - Close the DateRangePicker after clicking the date * @param {boolean} [options.usageStatistics = true] - Send a hostname to Google Analytics (default: true) * @example * // ES6 * import DatePicker from 'tui-date-picker' * * // CommonJS * const DatePicker = require('tui-date-picker'); * * // Browser * const DatePicker = tui.DatePicker; * * const rangePicker = DatePicker.createRangePicker({ * startpicker: { * input: '#start-input', * container: '#start-container' * date: new Date(2019, 3, 1), * weekStartDay: 'Mon', * }, * endpicker: { * input: '#end-input', * container: '#end-container', * weekStartDay: 'Mon', * }, * type: 'date', * format: 'yyyy-MM-dd' * selectableRanges: [ * [new Date(2017, 3, 1), new Date(2017, 5, 1)], * [new Date(2017, 6, 3), new Date(2017, 10, 5)] * ] * }); */ var DateRangePicker = defineClass( /** @lends DateRangePicker.prototype */ { init: function(options) { var startpickerOpt, endpickerOpt; options = options || {}; startpickerOpt = options.startpicker; endpickerOpt = options.endpicker; if (!startpickerOpt) { throw new Error('The "startpicker" option is required.'); } if (!endpickerOpt) { throw new Error('The "endpicker" option is required.'); } /** * Start picker * @type {DatePicker} * @private */ this._startpicker = null; /** * End picker * @type {DatePicker} * @private */ this._endpicker = null; this._isRangeSet = false; this._preEndPickerDate = new Date().getDate(); this._initializePickers(options); this._syncRangesToEndpicker(); }, /** * Create picker * @param {Object} options - DatePicker options * @private */ _initializePickers: function(options) { var startpickerContainer = util.getElement(options.startpicker.container); var endpickerContainer = util.getElement(options.endpicker.container); var startInput = util.getElement(options.startpicker.input); var endInput = util.getElement(options.endpicker.input); var startpickerOpt = extend({}, options, { input: { element: startInput, format: options.format }, date: options.startpicker.date, weekStartDay: options.startpicker.weekStartDay }); var endpickerOpt = extend({}, options, { input: { element: endInput, format: options.format }, date: options.endpicker.date, weekStartDay: options.endpicker.weekStartDay }); this._startpicker = new DatePicker(startpickerContainer, startpickerOpt); this._startpicker.addCssClass(CLASS_NAME_RANGE_PICKER); this._startpicker.on('change', this._onChangeStartpicker, this); this._startpicker.on('draw', this._onDrawPicker, this); this._endpicker = new DatePicker(endpickerContainer, endpickerOpt); this._endpicker.addCssClass(CLASS_NAME_RANGE_PICKER); this._endpicker.on('change', this._onChangeEndpicker, this); this._endpicker.on('draw', this._onDrawPicker, this); }, /** * Set selection-class to elements after calendar drawing * @param {Object} eventData - Event data {@link DatePicker#event:draw} * @private */ _onDrawPicker: function(eventData) { var calendarType = eventData.type; var startDate = this._startpicker.getDate(); var endDate = this._endpicker.getDate(); if (!startDate) { return; } if (!endDate) { // Convert null to invaild date. endDate = new Date(NaN); } forEachArray( eventData.dateElements, function(el) { var elDate = new Date(Number(getData(el, 'timestamp'))); var isInRange = dateUtil.inRange(startDate, endDate, elDate, calendarType); var isSelected = dateUtil.isSame(startDate, elDate, calendarType) || dateUtil.isSame(endDate, elDate, calendarType); this._setRangeClass(el, isInRange); this._setSelectedClass(el, isSelected); }, this ); }, /** * Set range class to element * @param {HTMLElement} el - Element * @param {boolean} isInRange - In range * @private */ _setRangeClass: function(el, isInRange) { if (isInRange) { addClass(el, CLASS_NAME_SELECTED_RANGE); } else { removeClass(el, CLASS_NAME_SELECTED_RANGE); } }, /** * Set selected class to element * @param {HTMLElement} el - Element * @param {boolean} isSelected - Is selected * @private */ _setSelectedClass: function(el, isSelected) { if (isSelected) { addClass(el, CLASS_NAME_SELECTED); } else { removeClass(el, CLASS_NAME_SELECTED); } }, /** * Sync ranges to endpicker * @private */ _syncRangesToEndpicker: function() { var startDate = this._startpicker.getDate(); var overlappedRange; if (startDate) { overlappedRange = this._startpicker.findOverlappedRange( dateUtil.cloneWithStartOf(startDate).getTime(), dateUtil.cloneWithEndOf(startDate).getTime() ); this._endpicker.enable(); this._endpicker.setRanges([[startDate.getTime(), overlappedRange[1].getTime()]]); this._setTimeRangeOnEndPicker(); } else { this._endpicker.setNull(); this._endpicker.disable(); } }, /** * After change on start-picker * @private */ _onChangeStartpicker: function() { this._syncRangesToEndpicker(); /** * Occur after the start date is changed. * @event DateRangePicker#change:start * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#on rangePicker.on()} to bind event handlers. * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#off rangePicker.off()} to unbind event handlers. * @see Refer to {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents CustomEvents} for more methods. DateRangePicker mixes in the methods from CustomEvents. * @example * // bind the 'change:start' event * rangePicker.on('change:start', () => { * console.log(`Start date: ${rangePicker.getStartDate()}`); * }); * * // unbind the 'change:start' event * rangePicker.off('change:start'); */ this.fire('change:start'); }, /** * After change on end-picker * @private */ _onChangeEndpicker: function() { /** * Occur after the end date is changed. * @event DateRangePicker#change:end * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#on rangePicker.on()} to bind event handlers. * @see {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents#off rangePicker.off()} to unbind event handlers. * @see Refer to {@link https://nhn.github.io/tui.code-snippet/latest/CustomEvents CustomEvents} for more methods. DateRangePicker mixes in the methods from CustomEvents. * @example * // bind the 'change:end' event * rangePicker.on('change:end', () => { * console.log(`End date: ${rangePicker.getEndDate()}`); * }); * * // unbind the 'change:end' event * rangePicker.off('change:end'); */ var date; var endPickerDate = this._endpicker.getDate(); if (endPickerDate) { date = endPickerDate.getDate(); if (this._preEndPickerDate !== date) { this._setTimeRangeOnEndPicker(); } this._preEndPickerDate = date; } else { this._preEndPickerDate = null; } this.fire('change:end'); }, /** * Set time range on end picker * @private */ _setTimeRangeOnEndPicker: function() { var pickerDate, timeRange; var endTimePicker = this._endpicker._timePicker; if (!endTimePicker) { return; } pickerDate = this._endpicker.getDate() || this._startpicker.getDate(); timeRange = this._getTimeRangeFromStartPicker(); if (pickerDate && timeRange[pickerDate.getDate()]) { endTimePicker.setRange(timeRange[pickerDate.getDate()]); this._isRangeSet = true; } else if (this._isRangeSet) { endTimePicker.setRange({ hour: 0, minute: 0 }); endTimePicker.resetMinuteRange(); this._isRangeSet = false; } }, /** * Return object of time range from start picker. * @returns {object} * @private */ _getTimeRangeFromStartPicker: function() { var startDate = this._startpicker.getDate(); var timeRange = {}; timeRange[startDate.getDate()] = { hour: startDate.getHours(), minute: startDate.getMinutes() }; return timeRange; }, /** * Return a start-datepicker. * @returns {DatePicker} */ getStartpicker: function() { return this._startpicker; }, /** * Return a end-datepicker. * @returns {DatePicker} */ getEndpicker: function() { return this._endpicker; }, /** * Set the start date. * @param {Date} date - Start date */ setStartDate: function(date) { this._startpicker.setDate(date); }, /** * Return the start date. * @returns {?Date} */ getStartDate: function() { return this._startpicker.getDate(); }, /** * Return the end date. * @returns {?Date} */ getEndDate: function() { return this._endpicker.getDate(); }, /** * Set the end date. * @param {Date} date - End date */ setEndDate: function(date) { this._endpicker.setDate(date); }, /** * Set selectable ranges. * @param {Array.>} ranges - Selectable ranges. Use Date instances or numbers(timestamp). */ setRanges: function(ranges) { this._startpicker.setRanges(ranges); this._syncRangesToEndpicker(); }, /** * Add a selectable range. Use Date instances or numbers(timestamp). * @param {Date|number} start - the start date * @param {Date|number} end - the end date */ addRange: function(start, end) { this._startpicker.addRange(start, end); this._syncRangesToEndpicker(); }, /** * Remove a range. Use Date instances or numbers(timestamp). * @param {Date|number} start - the start date * @param {Date|number} end - the end date * @param {null|'date'|'month'|'year'} type - Range type. If falsy, start and end values are considered as timestamp */ removeRange: function(start, end, type) { this._startpicker.removeRange(start, end, type); this._syncRangesToEndpicker(); }, /** * Change language. * @param {string} language - Language code. English('en') and Korean('ko') are provided as default. * @see To set to the other languages, use {@link DatePicker#localeTexts DatePicker.localeTexts}. */ changeLanguage: function(language) { this._startpicker.changeLanguage(language); this._endpicker.changeLanguage(language); }, /** * Destroy the date-range picker. */ destroy: function() { this.off(); this._startpicker.destroy(); this._endpicker.destroy(); this._startpicker = this._endpicker = null; } } ); CustomEvents.mixin(DateRangePicker); module.exports = DateRangePicker; /***/ }), /* 61 */ /***/ (function(module, exports, __webpack_require__) { // extracted by mini-css-extract-plugin /***/ }) /******/ ]); });