tui-date-picker
Version:
TOAST UI Components: DatePicker
1,933 lines (1,638 loc) • 196 kB
JavaScript
/*!
* TOAST UI Date Picker
* @version 4.3.3
* @author NHN Cloud. FE Development Lab <dl_javascript@nhn.com>
* @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 <dl_javascript@nhn.com>
*/
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
*/
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 <dl_javascript@nhn.com>
*/
/**
* 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 <dl_javascript@nhn.com>
*/
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
*/
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
*/
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 <dl_javascript@nhn.com>
*/
/**
* 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 <dl_javascript@nhn.com>
*/
/**
* @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 <dl_javascript@nhn.com>
*/
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.<string, function> 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 <dl_javascript@nhn.com>
*/
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
*/
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 <dl_javascript@nhn.com>
*/
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.<string>}
*/
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.<string>} ifExps - args of if expression
* @param {Array.<string>} 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.<string>} exps - array of expressions split by spaces
* @param {Array.<string>} 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.<string>} exps - array of expressions split by spaces
* @param {Array.<string>} 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.<string>} exps - array of expressions split by spaces
* @param {Array.<string>} 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.<string>} sources - array of sources
* @param {number} start - index of start block
* @param {number} end - index of end block
* @returns {Array.<string>}
* @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.<string>} sourcesToEnd - array of sources after the starting block
* @param {object} context - context
* @returns {Array.<string>}
* @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.<string>} 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.<string>} 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.<string>} sources - array of sources split by regexp of expression.
* @param {object} context - context
* @returns {Array.<string>} - 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.
* <br>
* 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'.
* <br>
* 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'.
* <br>
* 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 =
* '<h1>'
* + '{{if isValidNumber title}}'
* + '{{title}}th'
* + '{{elseif isValidDate title}}'
* + 'Date: {{title}}'
* + '{{/if}}'
* + '</h1>'
* + '{{each list}}'
* + '{{with addOne @index as idx}}'
* + '<p>{{idx}}: {{@this}}</p>'
* + '{{/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); // <h1>Date: 2019-11-25</h1><p>1: Clean the room</p><p>2: Wash the dishes</p>
*/
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 <dl_javascript@nhn.com>
*/
/**
* 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 <dl_javascript@nhn.com>
*/
/**
* 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 <dl_javascript@nhn.com>
*/
/**
* Remove ele