/*! * tui-code-snippet.js * @version 1.4.0 * @author NHNEnt FE Development Lab * @license MIT */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["util"] = factory(); else root["tui"] = root["tui"] || {}, root["tui"]["util"] = factory(); })(this, function() { 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] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = 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; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "dist"; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { 'use strict'; /** * @fileoverview * @author NHN Ent. * FE Development Lab * @namespace tui.util * @example * // node, commonjs * var util = require('tui-code-snippet'); * @example * // distribution file, script * * "; * var result = util.encodeHTMLEntity(htmlEntityString); * //"<script> alert('test');</script><a href='test'>" */ function encodeHTMLEntity(html) { var entities = { '"': 'quot', '&': 'amp', '<': 'lt', '>': 'gt', '\'': '#39' }; return html.replace(/[<>&"']/g, function(m0) { return entities[m0] ? '&' + entities[m0] + ';' : m0; }); } /** * Return whether the string capable to transform into plain string is in the given string or not. * @param {String} string - test string * @memberof tui.util * @returns {boolean} */ function hasEncodableString(string) { return (/[<>&"']/).test(string); } /** * Return duplicate charters * @param {string} operandStr1 The operand string * @param {string} operandStr2 The operand string * @private * @memberof tui.util * @returns {string} * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * util.getDuplicatedChar('fe dev', 'nhn entertainment'); // 'e' * util.getDuplicatedChar('fdsa', 'asdf'); // 'asdf' */ function getDuplicatedChar(operandStr1, operandStr2) { var i = 0; var len = operandStr1.length; var pool = {}; var dupl, key; for (; i < len; i += 1) { key = operandStr1.charAt(i); pool[key] = 1; } for (i = 0, len = operandStr2.length; i < len; i += 1) { key = operandStr2.charAt(i); if (pool[key]) { pool[key] += 1; } } pool = collection.filter(pool, function(item) { return item > 1; }); pool = object.keys(pool).sort(); dupl = pool.join(''); return dupl; } module.exports = { decodeHTMLEntity: decodeHTMLEntity, encodeHTMLEntity: encodeHTMLEntity, hasEncodableString: hasEncodableString, getDuplicatedChar: getDuplicatedChar }; /***/ }), /* 8 */ /***/ (function(module, exports) { /** * @fileoverview collections of some technic methods. * @author NHN Ent. FE Development Lab */ 'use strict'; var tricks = {}; var aps = Array.prototype.slice; /** * Creates a debounced function that delays invoking fn until after delay milliseconds has elapsed * since the last time the debouced function was invoked. * @param {function} fn The function to debounce. * @param {number} [delay=0] The number of milliseconds to delay * @memberof tui.util * @returns {function} debounced function. * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * function someMethodToInvokeDebounced() {} * * var debounced = util.debounce(someMethodToInvokeDebounced, 300); * * // invoke repeatedly * debounced(); * debounced(); * debounced(); * debounced(); * debounced(); * debounced(); // last invoke of debounced() * * // invoke someMethodToInvokeDebounced() after 300 milliseconds. */ function debounce(fn, delay) { var timer, args; /* istanbul ignore next */ delay = delay || 0; function debounced() { // eslint-disable-line require-jsdoc args = aps.call(arguments); window.clearTimeout(timer); timer = window.setTimeout(function() { fn.apply(null, args); }, delay); } return debounced; } /** * return timestamp * @memberof tui.util * @returns {number} The number of milliseconds from Jan. 1970 00:00:00 (GMT) */ function timestamp() { return Number(new Date()); } /** * Creates a throttled function that only invokes fn at most once per every interval milliseconds. * * You can use this throttle short time repeatedly invoking functions. (e.g MouseMove, Resize ...) * * if you need reuse throttled method. you must remove slugs (e.g. flag variable) related with throttling. * @param {function} fn function to throttle * @param {number} [interval=0] the number of milliseconds to throttle invocations to. * @memberof tui.util * @returns {function} throttled function * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * function someMethodToInvokeThrottled() {} * * var throttled = util.throttle(someMethodToInvokeThrottled, 300); * * // invoke repeatedly * throttled(); // invoke (leading) * throttled(); * throttled(); // invoke (near 300 milliseconds) * throttled(); * throttled(); * throttled(); // invoke (near 600 milliseconds) * // ... * // invoke (trailing) * * // if you need reuse throttled method. then invoke reset() * throttled.reset(); */ function throttle(fn, interval) { var base; var isLeading = true; var tick = function(_args) { fn.apply(null, _args); base = null; }; var debounced, stamp, args; /* istanbul ignore next */ interval = interval || 0; debounced = tricks.debounce(tick, interval); function throttled() { // eslint-disable-line require-jsdoc args = aps.call(arguments); if (isLeading) { tick(args); isLeading = false; return; } stamp = tricks.timestamp(); base = base || stamp; // pass array directly because `debounce()`, `tick()` are already use // `apply()` method to invoke developer's `fn` handler. // // also, this `debounced` line invoked every time for implements // `trailing` features. debounced(args); if ((stamp - base) >= interval) { tick(args); } } function reset() { // eslint-disable-line require-jsdoc isLeading = true; base = null; } throttled.reset = reset; return throttled; } tricks.timestamp = timestamp; tricks.debounce = debounce; tricks.throttle = throttle; module.exports = tricks; /***/ }), /* 9 */ /***/ (function(module, exports, __webpack_require__) { /** * @fileoverview This module has some functions for handling object as collection. * @author NHN Ent. * FE Development Lab */ 'use strict'; var object = __webpack_require__(1); var collection = __webpack_require__(4); var type = __webpack_require__(2); /** * Send hostname on DOMContentLoaded. * To prevent hostname set tui.usageStatistics to false. * @param {string} applicationId - application id to send * @ignore */ function sendHostname(applicationId) { var url = 'https://www.google-analytics.com/collect'; var hostname = location.hostname; var hitType = 'event'; var trackingId = 'UA-115377265-9'; // skip only if the flag is defined and is set to false explicitly if (!type.isUndefined(window.tui) && window.tui.usageStatistics === false) { return; } setTimeout(function() { if (document.readyState === 'interactive' || document.readyState === 'complete') { imagePing(url, { v: 1, t: hitType, tid: trackingId, cid: hostname, dp: hostname, dh: applicationId }); } }, 1000); } /** * Request image ping. * @param {String} url url for ping request * @param {Object} trackingInfo infos for make query string * @returns {HTMLElement} * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * util.imagePing('https://www.google-analytics.com/collect', { * v: 1, * t: 'event', * tid: 'trackingid', * cid: 'cid', * dp: 'dp', * dh: 'dh' * }); */ function imagePing(url, trackingInfo) { var queryString = collection.map(object.keys(trackingInfo), function(key, index) { var startWith = index === 0 ? '' : '&'; return startWith + key + '=' + trackingInfo[key]; }).join(''); var trackingElement = document.createElement('img'); trackingElement.src = url + '?' + queryString; trackingElement.style.display = 'none'; document.body.appendChild(trackingElement); document.body.removeChild(trackingElement); return trackingElement; } module.exports = { imagePing: imagePing, sendHostname: sendHostname }; /***/ }), /* 10 */ /***/ (function(module, exports) { /** * @fileoverview This module detects the kind of well-known browser and version. * @author NHN Ent. * FE Development Lab */ 'use strict'; /** * This object has an information that indicate the kind of browser.
* The list below is a detectable browser list. * - ie8 ~ ie11 * - chrome * - firefox * - safari * - edge * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * util.browser.chrome === true; // chrome * util.browser.firefox === true; // firefox * util.browser.safari === true; // safari * util.browser.msie === true; // IE * util.browser.edge === true; // edge * util.browser.others === true; // other browser * util.browser.version; // browser version */ var browser = { chrome: false, firefox: false, safari: false, msie: false, edge: false, others: false, version: 0 }; var nav = window.navigator; var appName = nav.appName.replace(/\s/g, '_'); var userAgent = nav.userAgent; var rIE = /MSIE\s([0-9]+[.0-9]*)/; var rIE11 = /Trident.*rv:11\./; var rEdge = /Edge\/(\d+)\./; var versionRegex = { firefox: /Firefox\/(\d+)\./, chrome: /Chrome\/(\d+)\./, safari: /Version\/([\d.]+).*Safari\/(\d+)/ }; var key, tmp; var detector = { Microsoft_Internet_Explorer: function() { // eslint-disable-line camelcase var detectedVersion = userAgent.match(rIE); if (detectedVersion) { // ie8 ~ ie10 browser.msie = true; browser.version = parseFloat(detectedVersion[1]); } else { // no version information browser.others = true; } }, Netscape: function() { // eslint-disable-line complexity var detected = false; if (rIE11.exec(userAgent)) { browser.msie = true; browser.version = 11; detected = true; } else if (rEdge.exec(userAgent)) { browser.edge = true; browser.version = userAgent.match(rEdge)[1]; detected = true; } else { for (key in versionRegex) { if (versionRegex.hasOwnProperty(key)) { tmp = userAgent.match(versionRegex[key]); if (tmp && tmp.length > 1) { // eslint-disable-line max-depth browser[key] = detected = true; browser.version = parseFloat(tmp[1] || 0); break; } } } } if (!detected) { browser.others = true; } } }; var fn = detector[appName]; if (fn) { detector[appName](); } module.exports = browser; /***/ }), /* 11 */ /***/ (function(module, exports, __webpack_require__) { /** * @fileoverview This module has some methods for handling popup-window * @author NHN Ent. * FE Development Lab */ 'use strict'; var collection = __webpack_require__(4); var type = __webpack_require__(2); var func = __webpack_require__(5); var browser = __webpack_require__(10); var object = __webpack_require__(1); var popupId = 0; /** * Popup management class * @constructor * @memberof tui.util * @example * // node, commonjs * var popup = require('tui-code-snippet').popup; * @example * // distribution file, script * * * */ 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 * //-- #1. Get Module --// * var CustomEvents = require('tui-code-snippet').CustomEvents; // node, commonjs * var CustomEvents = tui.util.CustomEvents; // distribution file * * //-- #2. Use property --// * 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) { object.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 (!type.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 (!type.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; // node, commonjs * var CustomEvents = tui.util.CustomEvents; // distribution file * * //-- #2. Use property --// * // # 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 (type.isString(eventName)) { // [syntax 1, 2] eventName = eventName.split(R_EVENTNAME_SPLIT); collection.forEach(eventName, function(name) { self._bindEvent(name, handler, context); }); } else if (type.isObject(eventName)) { // [syntax 3, 4] context = handler; collection.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 (type.isObject(eventName)) { context = handler; collection.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 (!type.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 forEach = collection.forEachArray; var andByHandler = type.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); collection.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) { collection.forEach(obj, function(func, name) { self.off(name, func); }); } else if (type.isString(handler)) { matchFunc = this._matchContext(obj); self._spliceMatches(this._safeEvent(handler), matchFunc); } else if (type.isFunction(handler)) { matchFunc = this._matchHandlerAndContext(handler, obj); collection.forEach(this._safeEvent(), function(handlerItems) { self._spliceMatches(handlerItems, matchFunc); }); } else { matchFunc = this._matchContext(obj); collection.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; // node, commonjs * var CustomEvents = tui.util.CustomEvents; // distribution file * * //-- #2. Use property --// * // # 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 (type.isString(eventName)) { // [syntax 1, 2] this._offByEventName(eventName, handler); } else if (!arguments.length) { // [syntax 8] this.events = {}; this.contexts = []; } else if (type.isFunction(eventName)) { // [syntax 3] this._offByHandler(eventName); } else if (type.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; /***/ }), /* 17 */ /***/ (function(module, exports, __webpack_require__) { /** * @fileoverview This module provides a Enum Constructor. * @author NHN Ent. * FE Development Lab * @example * // node, commonjs * var Enum = require('tui-code-snippet').Enum; * @example * // distribution file, script * * * * *