{"version":3,"file":"player.min.js","sources":["player.merge.js"],"sourcesContent":["/*jshint browser: true\n*/\n\n(function () {\n 'use strict';\n\n if (!Function.prototype.bind) {\n Function.prototype.bind = function (oThis) {\n if (typeof this !== 'function') {\n // closest thing possible to the ECMAScript 5 internal IsCallable function\n throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');\n }\n \n var self = this,\n args = Array.prototype.slice.call(arguments, 1);\n return function () {\n return self.apply(oThis, args.concat(Array.prototype.slice.call(arguments)));\n };\n };\n }\n\n})();\n/*jshint browser: true\n*/\n/**\n@module daumtools\n**/\n(function (exports) {\n \"use strict\";\n \n /**\n HTMLElement 의 className attribute 값을 관리한다.\n\n @class daumtools.classList\n @static\n **/\n var classList = exports.classList = (function () {\n if ('classList' in document.documentElement) {\n return {\n has: function (el, cname) {\n assertElement(el, cname, 'has');\n return el.classList.contains(cname);\n },\n add: function (el, cname) {\n assertElement(el, cname, 'add');\n el.classList.add(cname);\n },\n remove: function (el, cname) {\n assertElement(el, cname, 'remove');\n el.classList.remove(cname);\n },\n toggle: function (el, cname) {\n assertElement(el, cname, 'toggle');\n el.classList.toggle(cname);\n }\n };\n } else {\n return {\n /**\n HTMLElement 의 class list에 주어진 class가 존재하는지 판단한다.\n\n @method daumtools.classList.has\n @param el {HTMLElement} dom element\n @param cname {String} class name\n @return {Boolean} el의 class name에 cname이 존재할 경우 true, 그렇지 않을 경우 false.\n **/\n has: function (el, cname) {\n assertElement(el, cname, 'has');\n return el.className && ((\" \" + el.className + \" \").lastIndexOf(\" \" + cname + \" \") > -1);\n },\n /**\n HTMLElement 의 class list에 주어진 class 를 추가한다.\n\n @method daumtools.classList.add\n @param el {HTMLElement} dom element\n @param cname {String} el에 추가할 class name\n **/\n add: function (el, cname) {\n assertElement(el, cname, 'add');\n if (!el.className) {\n el.className = cname;\n } else if (!classList.has(el, cname)) {\n el.className += \" \" + cname;\n }\n },\n /**\n HTMLElement 의 class list에 주어진 class 를 삭제한다.\n\n @method daumtools.classList.remove\n @param el {HTMLElement} dom element\n @param cname {String} el에서 삭제할 class name\n **/\n remove: function (el, cname) {\n assertElement(el, cname, 'remove');\n if (el.className) {\n el.className = (\" \" + el.className + \" \").replace(\" \" + cname + \" \", \" \").replace(/^\\s+|\\s+$/g, '');\n }\n },\n /**\n HTMLElement 의 class list에 주어진 class 를 추가 혹은 삭제한다.\n\n @method daumtools.classList.toggle\n @param el {HTMLElement} dom element\n @param cname {String} class name\n **/\n toggle: function (el, cname) {\n assertElement(el, cname, 'toggle');\n if (el.className && classList.has(el, cname)) {\n classList.remove(el, cname);\n } else {\n classList.add(el, cname);\n }\n }\n };\n }\n })();\n\n function assertElement(el, cname, method) {\n if (!el) {\n throw new Error('el is not valid, el : ' + el + ', method : ' + method + ', className : ' + cname);\n }\n }\n \n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n\n/*jshint loopfunc: true, expr: true, newcap: false, latedef: false, noarg: false, undef:false */\n\n/* Simple JavaScript Inheritance\n * By John Resig http://ejohn.org/\n * MIT Licensed.\n */\n// Inspired by base2 and Prototype\n(function(exports){\n var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\\b_super\\b/ : /.*/;\n // The base Class implementation (does nothing)\n this.Class = exports.Class = function(){};\n \n // Create a new Class that inherits from this class\n Class.extend = function(prop) {\n var _super = this.prototype;\n \n // Instantiate a base class (but only create the instance,\n // don't run the init constructor)\n initializing = true;\n var prototype = new this();\n initializing = false;\n \n // Copy the properties over onto the new prototype\n for (var name in prop) {\n // Check if we're overwriting an existing function\n prototype[name] = typeof prop[name] === \"function\" &&\n typeof _super[name] === \"function\" && fnTest.test(prop[name]) ?\n (function(name, fn){\n return function() {\n var tmp = this._super;\n \n // Add a new ._super() method that is the same method\n // but on the super-class\n this._super = _super[name];\n \n // The method only need to be bound temporarily, so we\n // remove it when we're done executing\n var ret = fn.apply(this, arguments); \n this._super = tmp;\n \n return ret;\n };\n })(name, prop[name]) :\n prop[name];\n }\n \n // The dummy class constructor\n function Class() {\n // All construction is actually done in the init method\n if ( !initializing && this.init ) {\n this.init.apply(this, arguments);\n }\n }\n \n // Populate our constructed prototype object\n Class.prototype = prototype;\n \n // Enforce the constructor to be what we expect\n Class.prototype.constructor = Class;\n\n // And make this class extendable\n Class.extend = arguments.callee;\n \n return Class;\n };\n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n/*\n * classList.js: Cross-browser full element.classList implementation.\n * 1.2.20171210\n *\n * By Eli Grey, http://eligrey.com\n * License: Dedicated to the public domain.\n * See https://github.com/eligrey/classList.js/blob/master/LICENSE.md\n */\n\n/*global self, document, DOMException */\n\n/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */\n\nif (\"document\" in self) {\n\n // Full polyfill for browsers with no classList support\n // Including IE < Edge missing SVGElement.classList\n if (!(\"classList\" in document.createElement(\"_\")) || document.createElementNS && !(\"classList\" in document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\"))) {\n\n (function(view) {\n\n \"use strict\";\n\n if (!('Element' in view)) return;\n\n var\n classListProp = \"classList\",\n protoProp = \"prototype\",\n elemCtrProto = view.Element[protoProp],\n objCtr = Object,\n strTrim = String[protoProp].trim || function() {\n return this.replace(/^\\s+|\\s+$/g, \"\");\n }, arrIndexOf = Array[protoProp].indexOf || function(item) {\n var\n i = 0,\n len = this.length;\n for (; i < len; i++) {\n if (i in this && this[i] === item) {\n return i;\n }\n }\n return -1;\n }\n // Vendors: please allow content code to instantiate DOMExceptions\n ,\n DOMEx = function(type, message) {\n this.name = type;\n this.code = DOMException[type];\n this.message = message;\n }, checkTokenAndGetIndex = function(classList, token) {\n if (token === \"\") {\n throw new DOMEx(\"SYNTAX_ERR\", \"The token must not be empty.\");\n }\n if (/\\s/.test(token)) {\n throw new DOMEx(\"INVALID_CHARACTER_ERR\", \"The token must not contain space characters.\");\n }\n return arrIndexOf.call(classList, token);\n }, ClassList = function(elem) {\n var\n trimmedClasses = strTrim.call(elem.getAttribute(\"class\") || \"\"),\n classes = trimmedClasses ? trimmedClasses.split(/\\s+/) : [],\n i = 0,\n len = classes.length;\n for (; i < len; i++) {\n this.push(classes[i]);\n }\n this._updateClassName = function() {\n elem.setAttribute(\"class\", this.toString());\n };\n }, classListProto = ClassList[protoProp] = [],\n classListGetter = function() {\n return new ClassList(this);\n };\n // Most DOMException implementations don't allow calling DOMException's toString()\n // on non-DOMExceptions. Error's toString() is sufficient here.\n DOMEx[protoProp] = Error[protoProp];\n classListProto.item = function(i) {\n return this[i] || null;\n };\n classListProto.contains = function(token) {\n return~checkTokenAndGetIndex(this, token + \"\");\n };\n classListProto.add = function() {\n var\n tokens = arguments,\n i = 0,\n l = tokens.length,\n token, updated = false;\n do {\n token = tokens[i] + \"\";\n if (!~checkTokenAndGetIndex(this, token)) {\n this.push(token);\n updated = true;\n }\n }\n while (++i < l);\n\n if (updated) {\n this._updateClassName();\n }\n };\n classListProto.remove = function() {\n var\n tokens = arguments,\n i = 0,\n l = tokens.length,\n token, updated = false,\n index;\n do {\n token = tokens[i] + \"\";\n index = checkTokenAndGetIndex(this, token);\n while (~index) {\n this.splice(index, 1);\n updated = true;\n index = checkTokenAndGetIndex(this, token);\n }\n }\n while (++i < l);\n\n if (updated) {\n this._updateClassName();\n }\n };\n classListProto.toggle = function(token, force) {\n var\n result = this.contains(token),\n method = result ? force !== true && \"remove\" : force !== false && \"add\";\n\n if (method) {\n this[method](token);\n }\n\n if (force === true || force === false) {\n return force;\n } else {\n return !result;\n }\n };\n classListProto.replace = function(token, replacement_token) {\n var index = checkTokenAndGetIndex(token + \"\");\n if (~index) {\n this.splice(index, 1, replacement_token);\n this._updateClassName();\n }\n }\n classListProto.toString = function() {\n return this.join(\" \");\n };\n\n if (objCtr.defineProperty) {\n var classListPropDesc = {\n get: classListGetter,\n enumerable: true,\n configurable: true\n };\n try {\n objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);\n } catch (ex) { // IE 8 doesn't support enumerable:true\n // adding undefined to fight this issue https://github.com/eligrey/classList.js/issues/36\n // modernie IE8-MSW7 machine has IE8 8.0.6001.18702 and is affected\n if (ex.number === undefined || ex.number === -0x7FF5EC54) {\n classListPropDesc.enumerable = false;\n objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);\n }\n }\n } else if (objCtr[protoProp].__defineGetter__) {\n elemCtrProto.__defineGetter__(classListProp, classListGetter);\n }\n\n }(self));\n\n }\n\n // There is full or partial native classList support, so just check if we need\n // to normalize the add/remove and toggle APIs.\n\n (function() {\n \"use strict\";\n\n var testElement = document.createElement(\"_\");\n\n testElement.classList.add(\"c1\", \"c2\");\n\n // Polyfill for IE 10/11 and Firefox <26, where classList.add and\n // classList.remove exist but support only one argument at a time.\n if (!testElement.classList.contains(\"c2\")) {\n var createMethod = function(method) {\n var original = DOMTokenList.prototype[method];\n\n DOMTokenList.prototype[method] = function(token) {\n var i, len = arguments.length;\n\n for (i = 0; i < len; i++) {\n token = arguments[i];\n original.call(this, token);\n }\n };\n };\n createMethod('add');\n createMethod('remove');\n }\n\n testElement.classList.toggle(\"c3\", false);\n\n // Polyfill for IE 10 and Firefox <24, where classList.toggle does not\n // support the second argument.\n if (testElement.classList.contains(\"c3\")) {\n var _toggle = DOMTokenList.prototype.toggle;\n\n DOMTokenList.prototype.toggle = function(token, force) {\n if (1 in arguments && !this.contains(token) === !force) {\n return force;\n } else {\n return _toggle.call(this, token);\n }\n };\n\n }\n\n // replace() polyfill\n if (!(\"replace\" in document.createElement(\"_\").classList)) {\n DOMTokenList.prototype.replace = function(token, replacement_token) {\n var\n tokens = this.toString().split(\" \"),\n index = tokens.indexOf(token + \"\");\n if (~index) {\n tokens = tokens.slice(index);\n this.remove.apply(this, tokens);\n this.add(replacement_token);\n this.add.apply(this, tokens.slice(1));\n }\n }\n }\n\n testElement = null;\n }());\n\n}\n\nif (!Element.prototype.matches) {\n Element.prototype.matches = Element.prototype.msMatchesSelector ||\n Element.prototype.webkitMatchesSelector;\n}\n\nif (!Element.prototype.closest) {\n Element.prototype.closest = function (s) {\n var el = this;\n\n do {\n if (el.matches(s)) {\n return el;\n }\n el = el.parentElement || el.parentNode;\n } while (el !== null && el.nodeType === 1);\n return null;\n };\n}\n\n/*jshint devel: true\n */\n/*global Class, daumtools:true*/\n(function (exports) {\n 'use strict';\n\n exports.Observable = Class.extend({\n on: function (event, listener) {\n var events = [].concat(event);\n for (var i = 0, l = events.length; i < l; i++) {\n this.addListener.apply(this, [events[i], listener]);\n }\n\n return this;\n },\n addListener: function (event, listener) {\n var listeners = this.getListeners(event);\n listeners.push(listener);\n return this;\n },\n once: function (event, listener) {\n if (!listener) {\n return ;\n }\n var self = this;\n var onetimeListener = function () {\n self.off(event, onetimeListener);\n listener.apply(this, arguments);\n };\n listener.__onetime_listener = onetimeListener;\n this.on(event, onetimeListener);\n },\n emit: function (event) {\n var events = [].concat(event);\n var args = [].slice.call(arguments, 1);\n for (var i = 0, l = events.length; i < l; i++) {\n this._emit(events[i], args);\n }\n\n return this;\n },\n _emit: function (event, args) {\n var cloneListeners = this.getListeners(event).slice(0);\n if (typeof cloneListeners !== 'undefined') {\n for (var i = 0, len = cloneListeners.length; i < len; i++) {\n try {\n cloneListeners[i].apply(this, args);\n } catch (e) {\n if (typeof console !== 'undefined') {\n console.error('failed on while \"' + event + '\" event, caused by\\r\\n > ' + e);\n }\n throw e;\n }\n }\n }\n },\n getListeners: function (event) {\n this.listeners = this.listeners || {};\n this.listeners[event] = this.listeners[event] || [];\n return this.listeners[event];\n },\n off: function (event, listener) {\n var events = [].concat(event);\n if (listener && typeof listener.__onetime_listener === 'function') {\n listener = listener.__onetime_listener;\n }\n\n for (var i = 0, l = events.length; i < l; i++) {\n this.removeListener.apply(this, [events[i], listener]);\n }\n\n if (listener && typeof listener.__onetime_listener === 'function') {\n delete listener.__onetime_listener;\n }\n return this;\n },\n removeListener: function (event, listener) {\n var listeners = this.getListeners(event);\n if (typeof listeners !== 'undefined') {\n for (var i = 0, len = listeners.length; i < len; i++) {\n if (listeners[i] === listener || listeners[i].__original__ === listener) {\n listeners.splice(i, 1);\n break;\n }\n }\n }\n return this;\n },\n destroy: function () {\n this.listeners = null;\n }\n });\n})(window.daumtools = (typeof daumtools === 'undefined') ? {} : daumtools);\n/*jshint browser: true\n */\n/*global daumtools: true*/\n\n(function (exports) {\n \"use strict\";\n\n /**\n * 주어진 엘리먼트의 문서(body) 좌상단(0, 0)으로부터의 위치(coordinates)를 반환한다.\n * @param el\n * @returns {{x: (Number|number), y: (Number|number)}}\n */\n exports.offset = function (el) {\n var x = el.offsetLeft,\n y = el.offsetTop,\n offsetNode = el;\n\n while (offsetNode.offsetParent && offsetNode.offsetParent !== document.body) {\n offsetNode = offsetNode.offsetParent;\n x += offsetNode.offsetLeft;\n y += offsetNode.offsetTop;\n }\n\n return {\n x: x,\n y: y\n };\n };\n\n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n/*! ua_parser - v1.2.7 - 2020-06-03\n* Copyright (c) 2020 HTML5 Tech. Team in Daum Communications Corp.;\n* Licensed MIT */\n/*jshint browser: true, node: true\n*/\n\n(function (exports) {\n 'use strict';\n\n if (!Array.isArray) {\n Array.isArray = function(arg) {\n return Object.prototype.toString.call(arg) === '[object Array]';\n };\n }\n \n function checkUserAgent(ua) {\n var browser = {};\n var match = /(dolfin)[ \\/]([\\w.]+)/.exec( ua ) ||\n /(edge)[ \\/]([\\w.]+)/.exec( ua ) ||\n /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n /(tizen)[ \\/]([\\w.]+)/.exec( ua ) ||\n /(opera)(?:.*version)?[ \\/]([\\w.]+)/.exec( ua ) ||\n /(webkit)(?:.*version)?[ \\/]([\\w.]+)/.exec( ua ) ||\n /(msie) ([\\w.]+)/.exec( ua ) ||\n ua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+))?/.exec( ua ) ||\n [\"\",\"unknown\"];\n if (match[1] === \"webkit\") {\n match = /(iphone|ipad|ipod)[\\S\\s]*os ([\\w._\\-]+) like/.exec(ua) ||\n /(android)[ \\/]([\\w._\\-]+);/.exec(ua) || [match[0], \"safari\", match[2]];\n } else if (match[1] === \"mozilla\") {\n if (/trident/.test(ua)) {\n match[1] = \"msie\";\n } else {\n match[1] = \"firefox\";\n }\n } else if (/polaris|natebrowser|([010|011|016|017|018|019]{3}\\d{3,4}\\d{4}$)/.test(ua)) {\n match[1] = \"polaris\";\n }\n\n browser[match[1]] = true;\n browser.name = match[1];\n browser.version = setVersion(match[2]);\n\n return browser;\n }\n\n function setVersion(versionString) {\n var version = {};\n\n var versions = versionString ? versionString.split(/\\.|-|_/) : [\"0\",\"0\",\"0\"];\n version.info = versions.join(\".\");\n version.major = versions[0] || \"0\";\n version.minor = versions[1] || \"0\";\n version.patch = versions[2] || \"0\";\n\n return version;\n }\n\n function checkPlatform (ua) {\n if (isPc(ua)) {\n return \"pc\";\n } else if (isTablet(ua)) {\n return \"tablet\";\n } else if (isMobile(ua)) {\n return \"mobile\";\n } else {\n return \"\";\n }\n }\n function isPc (ua) {\n if (ua.match(/linux|windows (nt|98)|macintosh|cros/) && !ua.match(/android|mobile|polaris|lgtelecom|uzard|natebrowser|ktf;|skt;/)) {\n return true;\n }\n return false;\n }\n function isTablet (ua) {\n if (ua.match(/ipad/) || (ua.match(/android/) && !ua.match(/mobi|mini|fennec/)) || \n (ua.match(/macintosh/) && window.navigator.maxTouchPoints > 1)) {\n return true;\n }\n return false;\n }\n function isMobile (ua) {\n if (!!ua.match(/ip(hone|od)|android.+mobile|windows (ce|phone)|blackberry|bb10|symbian|webos|firefox.+fennec|opera m(ob|in)i|tizen.+mobile|polaris|iemobile|lgtelecom|nokia|sonyericsson|dolfin|uzard|natebrowser|ktf;|skt;/)) {\n return true;\n } else {\n return false;\n }\n }\n\n function checkOs (ua) {\n var os = {},\n match = /(iphone|ipad|ipod)[\\S\\s]*os ([\\w._\\-]+) like/.exec(ua) ||\n (/polaris|natebrowser|([010|011|016|017|018|019]{3}\\d{3,4}\\d{4}$)/.test(ua)? [\"\", \"polaris\", \"0.0.0\"] : false) ||\n /(windows)(?: nt | phone(?: os){0,1} | )([\\w._\\-]+)/.exec(ua) ||\n /(android)[ \\/]([\\w._\\-]+);/.exec(ua) ||\n (/android/.test(ua)? [\"\", \"android\", \"0.0.0\"] : false) ||\n (/(windows)/.test(ua)? [\"\", \"windows\", \"0.0.0\"] : false) ||\n /(mac) os x ([\\w._\\-]+)/.exec(ua) ||\n /(tizen)[ \\/]([\\w._\\-]+);/.exec(ua) ||\n (/(linux)/.test(ua)? [\"\", \"linux\", \"0.0.0\"] : false) ||\n (/webos/.test(ua)? [\"\", \"webos\", \"0.0.0\"] : false) ||\n /(cros)(?:\\s[\\w]+\\s)([\\d._\\-]+)/.exec(ua) ||\n /(bada)[ \\/]([\\w._\\-]+)/.exec(ua) ||\n (/bada/.test(ua)? [\"\", \"bada\", \"0.0.0\"] : false) ||\n (/(rim|blackberry|bb10)/.test(ua)? [\"\", \"blackberry\", \"0.0.0\"] : false) ||\n [\"\", \"unknown\", \"0.0.0\"];\n\n if (match[1] === \"iphone\" || match[1] === \"ipad\" || match[1] === \"ipod\") {\n match[1] = \"ios\";\n } else if (match[1] === \"windows\" && match[2] === \"98\") {\n match[2] = \"0.98.0\";\n }\n\n if (match[1] === \"mac\" && window.navigator.maxTouchPoints > 1) {\n match[1] = \"ios\";\n }\n if (match[1] === 'cros') {\n match[1] = \"chrome\";\n }\n os[match[1]] = true;\n os.name = match[1];\n os.version = setVersion(match[2]);\n return os;\n }\n\n var baseAppList = ['crios', 'fxios', 'daumapps'];\n function checkApp (ua, customAppList) {\n var app = {},\n match = null,\n checkAppList = baseAppList;\n\n if (Array.isArray(customAppList)) {\n checkAppList = baseAppList.concat(customAppList); \n } else if (typeof customAppList === 'string') {\n checkAppList = baseAppList.concat([customAppList]);\n }\n\n for(var i=0, len=checkAppList.length; i -1) {\n fn(e, currentTarget);\n break;\n }\n currentTarget = currentTarget.parentNode;\n }\n });\n }\n\n exports.event.delegate = delegate;\n\n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n\n/*! gesture - v1.0.6 - 2013-07-09\n * http://digit.daumcorp.com/eastkiki/gesture\n * Copyright (c) 2013 FT tech team, Daum corp; Licensed */\n\n\n(function(exports) {\n \"use strict\";\n\n var DEFAULT_FLICK_THRESHOLD = 30,\n DEFAULT_GESTURE_THRESHOLD = 30,\n EventUtil;\n\n function point(x, y) {\n return {\n 'x': x,\n 'y': y,\n 'minus': function(aPoint) {\n return point(this.x - aPoint.x, this.y - aPoint.y);\n }\n };\n }\n\n function GestureSession(lastSession, startPosX, startPosY, gestureThreshold, flickThreshold) {\n this.type = 'unindentified';\n this.direction = 'unindentified';\n this.startPos = point(startPosX, startPosY);\n this.delta = point(0, 0);\n this.targetEvent = null;\n this.term = 0;\n this.startTime = new Date();\n this.gestureThreshold = gestureThreshold;\n this.flickThreshold = flickThreshold;\n this.lastSession = lastSession;\n }\n\n GestureSession.prototype = {};\n GestureSession.prototype.isSwipe = function() {\n return this.type === 'swipe';\n };\n GestureSession.prototype.isScroll = function() {\n return this.type === 'scroll';\n };\n GestureSession.prototype.isLeft = function() {\n return this.direction === 'left';\n };\n GestureSession.prototype.isRight = function() {\n return this.direction === 'right';\n };\n GestureSession.prototype.isUp = function() {\n return this.direction === 'up';\n };\n GestureSession.prototype.isDown = function() {\n return this.direction === 'down';\n };\n GestureSession.prototype.isFlick = function() {\n return this.term < 200;\n };\n GestureSession.prototype.getTerm = function() {\n return this.term;\n };\n GestureSession.prototype.isTab = function() {\n return this.type === 'unindentified';\n };\n GestureSession.prototype.isDoubleTab = function() {\n if (typeof this.checkDoubleTab !== 'boolean') {\n this.checkDoubleTab = this.lastSession ? (this.startTime.getTime() - this.lastSession.startTime < 500 && this.lastSession.isTab === true && this.lastSession.isDoubleTab === false && this.type === 'unindentified') : false;\n }\n\n return this.checkDoubleTab;\n };\n\n GestureSession.prototype.recognizeGesture = function(x, y) {\n var currentPos = point(x, y),\n delta = currentPos.minus(this.startPos);\n\n this.delta = delta;\n\n if (this.type === 'unindentified') {\n if (Math.abs(delta.x) > this.gestureThreshold && Math.abs(delta.x) >= Math.abs(delta.y)) {\n this.type = 'swipe';\n if (delta.x < 0) {\n this.direction = 'left';\n } else {\n this.direction = 'right';\n }\n } else if (Math.abs(delta.y) > this.gestureThreshold && Math.abs(delta.y) > Math.abs(delta.x)) {\n this.type = 'scroll';\n if (delta.y < 0) {\n this.direction = 'up';\n } else {\n this.direction = 'down';\n }\n }\n }\n };\n\n GestureSession.prototype.checkFlick = function() {\n this.term = new Date().getTime() - this.startTime;\n };\n\n EventUtil = {\n START: function() {\n return ('ontouchstart' in window) ? 'touchstart' : 'mousedown';\n }(),\n MOVE: function() {\n return ('ontouchstart' in window) ? 'touchmove' : 'mousemove';\n }(),\n END: function() {\n return ('ontouchstart' in window) ? 'touchend' : 'mouseup';\n }(),\n listen: function() {\n if (document.addEventListener) {\n return function(el, type, fn) {\n el.addEventListener(type, fn, false);\n };\n } else {\n return function(el, type, fn) {\n el.attachEvent('on' + type, fn);\n };\n }\n }(),\n unListen: function() {\n if (document.removeEventListener) {\n return function(el, type, fn) {\n el.removeEventListener(type, fn, false);\n };\n } else {\n return function(el, type, fn) {\n el.detachEvent(\"on\" + type, fn);\n };\n }\n }(),\n getX: function(e) {\n var point = e.touches ? e.touches[0] : e;\n return point.pageX || point.clientX;\n },\n getY: function(e) {\n var point = e.touches ? e.touches[0] : e;\n return point.pageY || point.clientY;\n }\n };\n\n\n function GestureListener(elem, gestureThreshold, flickThreshold) {\n var session = null,\n lastSession = null,\n gestureHandlers = {\n 'onGestureStart': null,\n 'onGestureMove': null,\n 'onGetstureEnd': null\n };\n\n if (typeof gestureThreshold === 'undefined') {\n gestureThreshold = DEFAULT_GESTURE_THRESHOLD;\n } else if (typeof gestureThreshold !== \"number\") {\n throw new Error('gestureThreshold must be a number');\n }\n if (typeof flickThreshold === 'undefined') {\n flickThreshold = DEFAULT_FLICK_THRESHOLD;\n } else if (typeof flickThreshold !== \"number\") {\n throw new Error('flickThreshold must be a number');\n }\n\n function onMoveGesture(e) {\n if (session) {\n session.recognizeGesture(EventUtil.getX(e), EventUtil.getY(e));\n session.targetEvent = e || window.event;\n if (gestureHandlers.onGestureMove) {\n gestureHandlers.onGestureMove(session);\n }\n }\n }\n\n function onEndGesture(e) {\n if (session) {\n session.checkFlick();\n session.targetEvent = e || window.event;\n\n if (gestureHandlers.onGestureEnd) {\n gestureHandlers.onGestureEnd(session);\n }\n\n lastSession = {\n isTab: session.isTab(),\n isDoubleTab: session.isDoubleTab(),\n startTime: session.startTime\n };\n session = null;\n }\n EventUtil.unListen(document, EventUtil.MOVE, onMoveGesture);\n EventUtil.unListen(document, EventUtil.END, onEndGesture);\n if ('ontouchstart' in window) {\n EventUtil.unListen(document, \"touchcancel\", onEndGesture);\n }\n }\n\n function onStartGesture(e) {\n session = new GestureSession(lastSession, EventUtil.getX(e), EventUtil.getY(e), gestureThreshold, flickThreshold);\n session.targetEvent = e || window.event;\n\n if (gestureHandlers.onGestureStart) {\n gestureHandlers.onGestureStart(session);\n }\n\n EventUtil.listen(document, EventUtil.MOVE, onMoveGesture);\n EventUtil.listen(document, EventUtil.END, onEndGesture);\n if ('ontouchstart' in window) {\n EventUtil.listen(document, \"touchcancel\", onEndGesture);\n }\n }\n\n EventUtil.listen(elem, EventUtil.START, onStartGesture);\n\n function destroy() {\n EventUtil.unListen(elem, EventUtil.START, onStartGesture);\n }\n\n return {\n onGestureStart: function(fn) {\n gestureHandlers.onGestureStart = fn;\n },\n onGestureMove: function(fn) {\n gestureHandlers.onGestureMove = fn;\n },\n onGestureEnd: function(fn) {\n gestureHandlers.onGestureEnd = fn;\n },\n destroy: function() {\n destroy();\n }\n };\n }\n\n exports.GestureListener = GestureListener;\n exports.GestureSession = GestureSession;\n exports.EventUtil = EventUtil;\n})(window.gesture = {});\n(function (exports) {\n \"use strict\";\n\n function emptyFn () {}\n function isOldVersionsOfOperaMobile() {\n return hasUserAgent(\"opera\") && hasUserAgent(\"windows ce\");\n }\n function isAndroidStockBrowser() {\n return hasUserAgent(\"android\") && hasUserAgent(\"webkit\") && !hasUserAgent(\"chrome\");\n }\n\n function hasUserAgent(uaString) {\n var ua = navigator.userAgent.toLowerCase();\n return ua.indexOf(uaString) !== -1;\n }\n\n var availOrientationChange = \"onorientationchange\" in window && !isAndroidStockBrowser() ? true : false,\n availResize = \"onresize\" in window;\n\n\n /**\n * 해당 모바일 기기의 현재 Orientation 을 반환한다.\n * window.orientation가 있으면 orient체크(safari,android)\n * opera 는 client 사이즈가 고정이므로 screen 사이즈로 비교, 나머지는 client 사이즈로 비교\n * @return orient portrait/landscape\n */\n var OrientationManager = function () {\n this.init();\n };\n OrientationManager.prototype = {\n init: function () {\n this.orientList = [];\n this.state = this.getOrientation();\n this.bindEvent();\n },\n bindEvent: function () {\n var self = this;\n if (availOrientationChange || availResize) {\n var resize = availOrientationChange ? \"orientationchange\" : \"resize\";\n if (document.addEventListener) {\n window.addEventListener(resize, function (){\n self.onOrientationChange();\n });\n } else {\n window.attachEvent(\"on\" + resize, function (){\n self.onOrientationChange();\n }, false);\n }\n } else {\n window.setInterval(function () {\n self.onOrientationChange();\n }, 1000);\n }\n },\n onOrientationChange: function () {\n var currentState = this.getOrientation();\n this.state = currentState;\n this.emitOrientation(this.state);\n },\n getOrientation: function () {\n if (isOldVersionsOfOperaMobile()) {\n return function () {\n return (window.screen.width > window.screen.height) ? \"landscape\" : \"portrait\";\n };\n } else {\n var body = document.documentElement || document.body;\n return function () {\n return (body.clientWidth > body.clientHeight) ? \"landscape\" : \"portrait\";\n };\n }\n }(),\n emitOrientation: function (state) {\n for (var i=0, len=this.orientList.length; i whenever the\n // window blurs, even if you're tabbing out of the page. ¯\\_(ツ)_/¯\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n\n(function () {\n if (!window.performance) {\n window.performance = {};\n }\n\n if (!Date.now) {\n Date.now = function () {\n return new Date().getTime();\n }\n }\n\n if (!window.performance.now) {\n var nowOffset = Date.now();\n\n if (performance.timing && performance.timing.navigationStart) {\n nowOffset = performance.timing.navigationStart\n }\n\n window.performance.now = function () {\n return Date.now() - nowOffset;\n }\n }\n})();\n\n(function () {\n var lastTime = 0;\n var vendors = ['webkit', 'moz','ms','o'];\n\n for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {\n window.requestAnimationFrame = window[vendors[i]+'RequestAnimationFrame'];\n window.cancelAnimationFrame = window[vendors[i]+'CancelAnimationFrame'] || window[vendors[i]+'CancelRequestAnimationFrame'];\n }\n\n if (!window.requestAnimationFrame) {\n window.requestAnimationFrame = function (callback) {\n var currTime = new Date().getTime();\n var timeToCall = Math.max(0, 16 - (currTime - lastTime));\n var id = window.setTimeout(function () { callback(currTime + timeToCall); },\n timeToCall);\n lastTime = currTime + timeToCall;\n return id;\n };\n }\n\n if (!window.cancelAnimationFrame) {\n window.cancelAnimationFrame = function (id) {\n clearTimeout(id);\n };\n }\n}());\n\n/* global daumtools, jshint devel: true */\n(function (exports) {\n \"use strict\";\n\n exports.web2app = (function () {\n\n var TIMEOUT_IOS = 2 * 1000,\n TIMEOUT_ANDROID = 3 * 100,\n INTERVAL = 100,\n ua = daumtools.userAgent(),\n os = ua.os,\n intentNotSupportedBrowserList = [\n 'firefox',\n 'opr'\n ];\n\n function moveToStore (storeURL) {\n window.location.href = storeURL;\n }\n\n function web2app (context) {\n var willInvokeApp = (typeof context.willInvokeApp === 'function') ? context.willInvokeApp : function(){},\n onAppMissing = (typeof context.onAppMissing === 'function') ? context.onAppMissing : moveToStore,\n onUnsupportedEnvironment = (typeof context.onUnsupportedEnvironment === 'function') ? context.onUnsupportedEnvironment : function(){};\n\n willInvokeApp();\n\n if (os.android) {\n if (isIntentSupportedBrowser() && context.intentURI && !context.useUrlScheme) {\n web2appViaIntentURI(context.intentURI);\n } else if (context.storeURL) {\n web2appViaCustomUrlSchemeForAndroid(context.urlScheme, context.storeURL, onAppMissing);\n }\n } else if (os.ios && context.storeURL) {\n web2appViaCustomUrlSchemeForIOS(context.urlScheme, context.storeURL, onAppMissing, context.universalLink);\n } else {\n setTimeout(function () {\n onUnsupportedEnvironment();\n }, 100);\n }\n }\n\n // chrome 25 and later supports intent. https://developer.chrome.com/multidevice/android/intents\n function isIntentSupportedBrowser () {\n var supportsIntent = ua.browser.chrome && +(ua.browser.version.major) >= 25;\n var blackListRegexp = new RegExp(intentNotSupportedBrowserList.join('|'), \"i\");\n return supportsIntent && !blackListRegexp.test(ua.ua);\n }\n\n function web2appViaCustomUrlSchemeForAndroid (urlScheme, storeURL, fallback) {\n deferFallback(TIMEOUT_ANDROID, storeURL, fallback);\n launchAppViaHiddenIframe(urlScheme);\n }\n\n function deferFallback(timeout, storeURL, fallback) {\n var clickedAt = new Date().getTime();\n return setTimeout(function () {\n var now = new Date().getTime();\n if (isPageVisible() && now - clickedAt < timeout + INTERVAL) {\n fallback(storeURL);\n }\n }, timeout);\n }\n\n function web2appViaIntentURI (launchURI) {\n if ( ua.browser.chrome ){\n move();\n }else{\n setTimeout(move, 100);\n }\n\n function move(){\n top.location.href = launchURI;\n }\n }\n\n function web2appViaCustomUrlSchemeForIOS (urlScheme, storeURL, fallback, universalLink) {\n var tid = deferFallback(TIMEOUT_IOS, storeURL, fallback);\n if (parseInt(ua.os.version.major, 10) < 8) {\n bindPagehideEvent(tid);\n } else {\n bindVisibilityChangeEvent(tid);\n }\n\n // https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple_ref/doc/uid/TP40016308-CH12\n if ( isSupportUniversalLinks() ){\n if (universalLink === undefined) {\n universalLink = urlScheme;\n } else {\n clearTimeout(tid);\n }\n launchAppViaChangingLocation(universalLink);\n }else{\n launchAppViaHiddenIframe(urlScheme);\n }\n }\n\n function bindPagehideEvent (tid) {\n window.addEventListener('pagehide', function clear () {\n if (isPageVisible()) {\n clearTimeout(tid);\n window.removeEventListener('pagehide', clear);\n }\n });\n }\n\n function bindVisibilityChangeEvent (tid) {\n document.addEventListener('visibilitychange', function clear () {\n if (isPageVisible()) {\n clearTimeout(tid);\n document.removeEventListener('visibilitychange', clear);\n }\n });\n }\n\n function isPageVisible () {\n var attrNames = ['hidden', 'webkitHidden'];\n for(var i=0, len=attrNames.length; i 8 && ua.os.ios);\n }\n\n /**\n * app.을 실행하거나 / store 페이지에 연결하여 준다.\n * @function\n * @param context {object} urlScheme, intentURI, storeURL, appName, onAppMissing, onUnsupportedEnvironment, willInvokeApp\n * @example daumtools.web2app({ urlScheme : 'daumapps://open', intentURI : '', storeURL: 'itms-app://...', appName: '다음앱' });\n */\n return web2app;\n\n })();\n\n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n\n\n/**\n @module daumtools\n **/\n(function (exports) {\n 'use strict';\n\n exports.classListAll = (function () {\n return {\n add: function (el, cname) {\n assertElement(el, cname, 'add');\n\n if (!el || !cname || typeof cname !== 'string') {\n return;\n }\n\n for (var i = 0, len = el.length; i < len; i += 1) {\n daumtools.classList.add(el[i], cname);\n }\n },\n remove: function (el, cname) {\n assertElement(el, cname, 'remove');\n\n if (!el || !cname || typeof cname !== 'string') {\n return;\n }\n\n for (var i = 0, len = el.length; i < len; i += 1) {\n daumtools.classList.remove(el[i], cname);\n }\n }\n };\n })();\n\n function assertElement(el, cname, method) {\n if (!el) {\n throw new Error('el is not valid, el : ' + el + ', method : ' + method + ', className : ' + cname);\n }\n }\n\n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n\n/**\n @module daumtools\n **/\n(function (exports) {\n 'use strict';\n\n exports.dataset = function (node, attr, value) {\n\n var self = {\n set: function (node, attr, value) {\n node.setAttribute('data-' + attr, value);\n },\n get: function (node, attr) {\n return node.getAttribute('data-' + attr);\n }\n };\n\n if (arguments.length === 3) {\n return self.set(node, attr, value);\n }\n if (arguments.length === 2) {\n return self.get(node, attr);\n }\n\n return self;\n }\n\n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n/*!\n * clipboard.js v2.0.4\n * https://zenorocha.github.io/clipboard.js\n *\n * Licensed MIT © Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n if(typeof exports === 'object' && typeof module === 'object')\n module.exports = factory();\n else if(typeof define === 'function' && define.amd)\n define([], factory);\n else if(typeof exports === 'object')\n exports[\"ClipboardJS\"] = factory();\n else\n root[\"ClipboardJS\"] = factory();\n})(this, function() {\n return /******/ (function(modules) { // webpackBootstrap\n /******/ \t// The module cache\n /******/ \tvar installedModules = {};\n /******/\n /******/ \t// The require function\n /******/ \tfunction __webpack_require__(moduleId) {\n /******/\n /******/ \t\t// Check if module is in cache\n /******/ \t\tif(installedModules[moduleId]) {\n /******/ \t\t\treturn installedModules[moduleId].exports;\n /******/ \t\t}\n /******/ \t\t// Create a new module (and put it into the cache)\n /******/ \t\tvar module = installedModules[moduleId] = {\n /******/ \t\t\ti: moduleId,\n /******/ \t\t\tl: false,\n /******/ \t\t\texports: {}\n /******/ \t\t};\n /******/\n /******/ \t\t// Execute the module function\n /******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n /******/\n /******/ \t\t// Flag the module as loaded\n /******/ \t\tmodule.l = true;\n /******/\n /******/ \t\t// Return the exports of the module\n /******/ \t\treturn module.exports;\n /******/ \t}\n /******/\n /******/\n /******/ \t// expose the modules object (__webpack_modules__)\n /******/ \t__webpack_require__.m = modules;\n /******/\n /******/ \t// expose the module cache\n /******/ \t__webpack_require__.c = installedModules;\n /******/\n /******/ \t// define getter function for harmony exports\n /******/ \t__webpack_require__.d = function(exports, name, getter) {\n /******/ \t\tif(!__webpack_require__.o(exports, name)) {\n /******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n /******/ \t\t}\n /******/ \t};\n /******/\n /******/ \t// define __esModule on exports\n /******/ \t__webpack_require__.r = function(exports) {\n /******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n /******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n /******/ \t\t}\n /******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n /******/ \t};\n /******/\n /******/ \t// create a fake namespace object\n /******/ \t// mode & 1: value is a module id, require it\n /******/ \t// mode & 2: merge all properties of value into the ns\n /******/ \t// mode & 4: return value when already ns object\n /******/ \t// mode & 8|1: behave like require\n /******/ \t__webpack_require__.t = function(value, mode) {\n /******/ \t\tif(mode & 1) value = __webpack_require__(value);\n /******/ \t\tif(mode & 8) return value;\n /******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n /******/ \t\tvar ns = Object.create(null);\n /******/ \t\t__webpack_require__.r(ns);\n /******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n /******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n /******/ \t\treturn ns;\n /******/ \t};\n /******/\n /******/ \t// getDefaultExport function for compatibility with non-harmony modules\n /******/ \t__webpack_require__.n = function(module) {\n /******/ \t\tvar getter = module && module.__esModule ?\n /******/ \t\t\tfunction getDefault() { return module['default']; } :\n /******/ \t\t\tfunction getModuleExports() { return module; };\n /******/ \t\t__webpack_require__.d(getter, 'a', getter);\n /******/ \t\treturn getter;\n /******/ \t};\n /******/\n /******/ \t// Object.prototype.hasOwnProperty.call\n /******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n /******/\n /******/ \t// __webpack_public_path__\n /******/ \t__webpack_require__.p = \"\";\n /******/\n /******/\n /******/ \t// Load entry module and return exports\n /******/ \treturn __webpack_require__(__webpack_require__.s = 0);\n /******/ })\n /************************************************************************/\n /******/ ([\n /* 0 */\n /***/ (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n\n\n var _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\n var _clipboardAction = __webpack_require__(1);\n\n var _clipboardAction2 = _interopRequireDefault(_clipboardAction);\n\n var _tinyEmitter = __webpack_require__(3);\n\n var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);\n\n var _goodListener = __webpack_require__(4);\n\n var _goodListener2 = _interopRequireDefault(_goodListener);\n\n function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\n function _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\n /**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n var Clipboard = function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n _classCallCheck(this, Clipboard);\n\n var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));\n\n _this.resolveOptions(options);\n _this.listenClick(trigger);\n return _this;\n }\n\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = _typeof(options.container) === 'object' ? options.container : document.body;\n }\n\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: 'listenClick',\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: 'onClick',\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n\n if (this.clipboardAction) {\n this.clipboardAction = null;\n }\n\n this.clipboardAction = new _clipboardAction2.default({\n action: this.action(trigger),\n target: this.target(trigger),\n text: this.text(trigger),\n container: this.container,\n trigger: trigger,\n emitter: this\n });\n }\n\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultAction',\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultTarget',\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: 'defaultText',\n\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: 'destroy',\n value: function destroy() {\n this.listener.destroy();\n\n if (this.clipboardAction) {\n this.clipboardAction.destroy();\n this.clipboardAction = null;\n }\n }\n }], [{\n key: 'isSupported',\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n\n return support;\n }\n }]);\n\n return Clipboard;\n }(_tinyEmitter2.default);\n\n /**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\n\n function getAttributeValue(suffix, element) {\n var attribute = 'data-clipboard-' + suffix;\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n }\n\n module.exports = Clipboard;\n\n /***/ }),\n /* 1 */\n /***/ (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n\n\n var _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\n var _select = __webpack_require__(2);\n\n var _select2 = _interopRequireDefault(_select);\n\n function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n /**\n * Inner class which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n */\n var ClipboardAction = function () {\n /**\n * @param {Object} options\n */\n function ClipboardAction(options) {\n _classCallCheck(this, ClipboardAction);\n\n this.resolveOptions(options);\n this.initSelection();\n }\n\n /**\n * Defines base properties passed from constructor.\n * @param {Object} options\n */\n\n\n _createClass(ClipboardAction, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = options.action;\n this.container = options.container;\n this.emitter = options.emitter;\n this.target = options.target;\n this.text = options.text;\n this.trigger = options.trigger;\n\n this.selectedText = '';\n }\n\n /**\n * Decides which selection strategy is going to be applied based\n * on the existence of `text` and `target` properties.\n */\n\n }, {\n key: 'initSelection',\n value: function initSelection() {\n if (this.text) {\n this.selectFake();\n } else if (this.target) {\n this.selectTarget();\n }\n }\n\n /**\n * Creates a fake textarea element, sets its value from `text` property,\n * and makes a selection on it.\n */\n\n }, {\n key: 'selectFake',\n value: function selectFake() {\n var _this = this;\n\n var isRTL = document.documentElement.getAttribute('dir') == 'rtl';\n\n this.removeFake();\n\n this.fakeHandlerCallback = function () {\n return _this.removeFake();\n };\n this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;\n\n this.fakeElem = document.createElement('textarea');\n // Prevent zooming on iOS\n this.fakeElem.style.fontSize = '12pt';\n // Reset box model\n this.fakeElem.style.border = '0';\n this.fakeElem.style.padding = '0';\n this.fakeElem.style.margin = '0';\n // Move element out of screen horizontally\n this.fakeElem.style.position = 'absolute';\n this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';\n // Move element to the same position vertically\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n this.fakeElem.style.top = yPosition + 'px';\n\n this.fakeElem.setAttribute('readonly', '');\n this.fakeElem.value = this.text;\n\n this.container.appendChild(this.fakeElem);\n\n this.selectedText = (0, _select2.default)(this.fakeElem);\n this.copyText();\n }\n\n /**\n * Only removes the fake element after another click event, that way\n * a user can hit `Ctrl+C` to copy because selection still exists.\n */\n\n }, {\n key: 'removeFake',\n value: function removeFake() {\n if (this.fakeHandler) {\n this.container.removeEventListener('click', this.fakeHandlerCallback);\n this.fakeHandler = null;\n this.fakeHandlerCallback = null;\n }\n\n if (this.fakeElem) {\n this.container.removeChild(this.fakeElem);\n this.fakeElem = null;\n }\n }\n\n /**\n * Selects the content from element passed on `target` property.\n */\n\n }, {\n key: 'selectTarget',\n value: function selectTarget() {\n this.selectedText = (0, _select2.default)(this.target);\n this.copyText();\n }\n\n /**\n * Executes the copy operation based on the current selection.\n */\n\n }, {\n key: 'copyText',\n value: function copyText() {\n var succeeded = void 0;\n\n try {\n succeeded = document.execCommand(this.action);\n } catch (err) {\n succeeded = false;\n }\n\n this.handleResult(succeeded);\n }\n\n /**\n * Fires an event based on the copy operation result.\n * @param {Boolean} succeeded\n */\n\n }, {\n key: 'handleResult',\n value: function handleResult(succeeded) {\n this.emitter.emit(succeeded ? 'success' : 'error', {\n action: this.action,\n text: this.selectedText,\n trigger: this.trigger,\n clearSelection: this.clearSelection.bind(this)\n });\n }\n\n /**\n * Moves focus away from `target` and back to the trigger, removes current selection.\n */\n\n }, {\n key: 'clearSelection',\n value: function clearSelection() {\n if (this.trigger) {\n this.trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n\n /**\n * Sets the `action` to be performed which can be either 'copy' or 'cut'.\n * @param {String} action\n */\n\n }, {\n key: 'destroy',\n\n\n /**\n * Destroy lifecycle.\n */\n value: function destroy() {\n this.removeFake();\n }\n }, {\n key: 'action',\n set: function set() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';\n\n this._action = action;\n\n if (this._action !== 'copy' && this._action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n }\n }\n\n /**\n * Gets the `action` property.\n * @return {String}\n */\n ,\n get: function get() {\n return this._action;\n }\n\n /**\n * Sets the `target` property using an element\n * that will be have its content copied.\n * @param {Element} target\n */\n\n }, {\n key: 'target',\n set: function set(target) {\n if (target !== undefined) {\n if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {\n if (this.action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n\n this._target = target;\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n }\n }\n\n /**\n * Gets the `target` property.\n * @return {String|HTMLElement}\n */\n ,\n get: function get() {\n return this._target;\n }\n }]);\n\n return ClipboardAction;\n }();\n\n module.exports = ClipboardAction;\n\n /***/ }),\n /* 2 */\n /***/ (function(module, exports) {\n\n function select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n }\n\n module.exports = select;\n\n\n /***/ }),\n /* 3 */\n /***/ (function(module, exports) {\n\n function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n }\n\n E.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n };\n\n module.exports = E;\n\n\n /***/ }),\n /* 4 */\n /***/ (function(module, exports, __webpack_require__) {\n\n var is = __webpack_require__(5);\n var delegate = __webpack_require__(6);\n\n /**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\n function listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n }\n\n /**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\n function listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n }\n\n /**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\n function listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n }\n\n /**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\n function listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n }\n\n module.exports = listen;\n\n\n /***/ }),\n /* 5 */\n /***/ (function(module, exports) {\n\n /**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\n exports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n };\n\n /**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\n exports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n };\n\n /**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\n exports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n };\n\n /**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\n exports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n };\n\n\n /***/ }),\n /* 6 */\n /***/ (function(module, exports, __webpack_require__) {\n\n var closest = __webpack_require__(7);\n\n /**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\n function _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n }\n\n /**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\n function delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n }\n\n /**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\n function listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n }\n\n module.exports = delegate;\n\n\n /***/ }),\n /* 7 */\n /***/ (function(module, exports) {\n\n var DOCUMENT_NODE_TYPE = 9;\n\n /**\n * A polyfill for Element.matches()\n */\n if (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n }\n\n /**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\n function closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n }\n\n module.exports = closest;\n\n\n /***/ })\n /******/ ]);\n});\n\n/*! GetDevicePixelRatio | Author: Tyson Matanich, 2012 | License: MIT */\n(function (window) {\n window.getDevicePixelRatio = function () {\n var ratio = 1;\n // To account for zoom, change to use deviceXDPI instead of systemXDPI\n if (window.screen.systemXDPI !== undefined && window.screen.logicalXDPI !== undefined && window.screen.systemXDPI > window.screen.logicalXDPI) {\n // Only allow for values > 1\n ratio = window.screen.systemXDPI / window.screen.logicalXDPI;\n }\n else if (window.devicePixelRatio !== undefined) {\n ratio = window.devicePixelRatio;\n }\n return ratio;\n };\n})(this);\n\n(function () {\n 'use strict';\n\n function startLazyModuls() {\n setTimeout(function () {\n daumtools.group('event: window:ready_1');\n monet.queue.emit('window:ready_1');\n daumtools.groupEnd();\n }, 500);\n setTimeout(function () {\n daumtools.group('event: window:ready_2');\n monet.queue.emit('window:ready_2');\n daumtools.groupEnd();\n }, 1000);\n }\n\n monet.fireLoadEvent = function () {\n var isNotFiredLoadEvent = true;\n return function () {\n if (isNotFiredLoadEvent) {\n isNotFiredLoadEvent = false;\n monet.queue.emit('window:load');\n setTimeout(function () {\n daumtools.group('event: window:ready');\n monet.queue.emit('window:ready');\n daumtools.groupEnd();\n\n startLazyModuls();\n }, 25);\n daumtools.info('Now Load event fire');\n } else {\n daumtools.warn('Already Load event is fired');\n }\n };\n }();\n daumtools.event.on(window, 'load', function () {\n if(!monet.disableLoadEvent) {\n monet.fireLoadEvent();\n }\n });\n\n daumtools.event.on(window, 'unload', function () {\n monet.queue.emit('window:unload');\n });\n\n daumtools.event.on(window, 'pageshow', function (e) {\n if (e.persisted) {\n monet.queue.emit('window:restored');\n }\n });\n\n daumtools.event.on(window, 'pagehide', function (e) {\n if (e.persisted) {\n monet.queue.emit('window:saved');\n }\n });\n}());\n/*! iScroll v5.2.0-snapshot ~ (c) 2008-2017 Matteo Spinelli ~ http://cubiq.org/license */\n(function(window, document, Math) {\n var rAF = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {\n window.setTimeout(callback, 1000 / 60);\n };\n\n var utils = (function() {\n var me = {};\n\n var _elementStyle = document.createElement('div').style;\n var _vendor = (function() {\n var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],\n transform,\n i = 0,\n l = vendors.length;\n\n for (; i < l; i++) {\n transform = vendors[i] + 'ransform';\n if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);\n }\n\n return false;\n })();\n\n function _prefixStyle(style) {\n if (_vendor === false) return false;\n if (_vendor === '') return style;\n return _vendor + style.charAt(0).toUpperCase() + style.substr(1);\n }\n\n me.getTime = Date.now || function getTime() {\n return new Date().getTime();\n };\n\n me.extend = function(target, obj) {\n for (var i in obj) {\n target[i] = obj[i];\n }\n };\n\n me.addEvent = function(el, type, fn, capture) {\n el.addEventListener(type, fn, !! capture);\n };\n\n me.removeEvent = function(el, type, fn, capture) {\n el.removeEventListener(type, fn, !! capture);\n };\n\n me.prefixPointerEvent = function(pointerEvent) {\n return window.MSPointerEvent ? 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8) : pointerEvent;\n };\n\n me.momentum = function(current, start, time, lowerMargin, wrapperSize, deceleration) {\n var distance = current - start,\n speed = Math.abs(distance) / time,\n destination,\n duration;\n\n deceleration = deceleration === undefined ? 0.0006 : deceleration;\n\n destination = current + (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1);\n duration = speed / deceleration;\n\n if (destination < lowerMargin) {\n destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin;\n distance = Math.abs(destination - current);\n duration = distance / speed;\n } else if (destination > 0) {\n destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0;\n distance = Math.abs(current) + destination;\n duration = distance / speed;\n }\n\n return {\n destination: Math.round(destination),\n duration: duration\n };\n };\n\n var _transform = _prefixStyle('transform');\n\n me.extend(me, {\n hasTransform: _transform !== false,\n hasPerspective: _prefixStyle('perspective') in _elementStyle,\n hasTouch: 'ontouchstart' in window,\n hasPointer: !! (window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed\n hasTransition: _prefixStyle('transition') in _elementStyle\n });\n\n /*\n\tThis should find all Android browsers lower than build 535.19 (both stock browser and webview)\n\t- galaxy S2 is ok\n - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`\n - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n - galaxy S3 is badAndroid (stock brower, webview)\n `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n - galaxy S4 is badAndroid (stock brower, webview)\n `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n - galaxy S5 is OK\n `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n - galaxy S6 is OK\n `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n */\n me.isBadAndroid = (function() {\n var appVersion = window.navigator.appVersion;\n // Android browser is not a chrome browser.\n if (/Android/.test(appVersion) && !(/Chrome\\/\\d/.test(appVersion))) {\n var safariVersion = appVersion.match(/Safari\\/(\\d+.\\d)/);\n if (safariVersion && typeof safariVersion === \"object\" && safariVersion.length >= 2) {\n return parseFloat(safariVersion[1]) < 535.19;\n } else {\n return true;\n }\n } else {\n return false;\n }\n })();\n\n me.extend(me.style = {}, {\n transform: _transform,\n transitionTimingFunction: _prefixStyle('transitionTimingFunction'),\n transitionDuration: _prefixStyle('transitionDuration'),\n transitionDelay: _prefixStyle('transitionDelay'),\n transformOrigin: _prefixStyle('transformOrigin'),\n touchAction: _prefixStyle('touchAction')\n });\n\n me.hasClass = function(e, c) {\n var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\");\n return re.test(e.className);\n };\n\n me.addClass = function(e, c) {\n if (me.hasClass(e, c)) {\n return;\n }\n\n var newclass = e.className.split(' ');\n newclass.push(c);\n e.className = newclass.join(' ');\n };\n\n me.removeClass = function(e, c) {\n if (!me.hasClass(e, c)) {\n return;\n }\n\n var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", 'g');\n e.className = e.className.replace(re, ' ');\n };\n\n me.offset = function(el) {\n var left = -el.offsetLeft,\n top = -el.offsetTop;\n\n // jshint -W084\n while (el = el.offsetParent) {\n left -= el.offsetLeft;\n top -= el.offsetTop;\n }\n // jshint +W084\n\n return {\n left: left,\n top: top\n };\n };\n\n me.preventDefaultException = function(el, exceptions) {\n for (var i in exceptions) {\n if (exceptions[i].test(el[i])) {\n return true;\n }\n }\n\n return false;\n };\n\n me.extend(me.eventType = {}, {\n touchstart: 1,\n touchmove: 1,\n touchend: 1,\n\n mousedown: 2,\n mousemove: 2,\n mouseup: 2,\n\n pointerdown: 1,\n pointermove: 1,\n pointerup: 1,\n\n MSPointerDown: 3,\n MSPointerMove: 3,\n MSPointerUp: 3\n });\n\n me.extend(me.ease = {}, {\n quadratic: {\n style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n fn: function(k) {\n return k * (2 - k);\n }\n },\n circular: {\n style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly \"circular\" but this looks better, it should be (0.075, 0.82, 0.165, 1)\n fn: function(k) {\n return Math.sqrt(1 - (--k * k));\n }\n },\n back: {\n style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',\n fn: function(k) {\n var b = 4;\n return (k = k - 1) * k * ((b + 1) * k + b) + 1;\n }\n },\n bounce: {\n style: '',\n fn: function(k) {\n if ((k /= 1) < (1 / 2.75)) {\n return 7.5625 * k * k;\n } else if (k < (2 / 2.75)) {\n return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;\n } else if (k < (2.5 / 2.75)) {\n return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;\n } else {\n return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;\n }\n }\n },\n elastic: {\n style: '',\n fn: function(k) {\n var f = 0.22,\n e = 0.4;\n\n if (k === 0) {\n return 0;\n }\n if (k == 1) {\n return 1;\n }\n\n return (e * Math.pow(2, - 10 * k) * Math.sin((k - f / 4) * (2 * Math.PI) / f) + 1);\n }\n }\n });\n\n me.tap = function(e, eventName) {\n var ev = document.createEvent('Event');\n ev.initEvent(eventName, true, true);\n ev.pageX = e.pageX;\n ev.pageY = e.pageY;\n e.target.dispatchEvent(ev);\n };\n\n me.click = function(e) {\n var target = e.target,\n ev;\n\n if (!(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName)) {\n // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent\n // initMouseEvent is deprecated.\n ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');\n ev.initEvent('click', true, true);\n ev.view = e.view || window;\n ev.detail = 1;\n ev.screenX = target.screenX || 0;\n ev.screenY = target.screenY || 0;\n ev.clientX = target.clientX || 0;\n ev.clientY = target.clientY || 0;\n ev.ctrlKey = !! e.ctrlKey;\n ev.altKey = !! e.altKey;\n ev.shiftKey = !! e.shiftKey;\n ev.metaKey = !! e.metaKey;\n ev.button = 0;\n ev.relatedTarget = null;\n ev._constructed = true;\n target.dispatchEvent(ev);\n }\n };\n\n me.getTouchAction = function(eventPassthrough, addPinch) {\n var touchAction = 'none';\n if (eventPassthrough === 'vertical') {\n touchAction = 'pan-y';\n } else if (eventPassthrough === 'horizontal') {\n touchAction = 'pan-x';\n }\n if (addPinch && touchAction != 'none') {\n // add pinch-zoom support if the browser supports it, but if not (eg. Chrome <55) do nothing\n touchAction += ' pinch-zoom';\n }\n return touchAction;\n };\n\n me.getRect = function(el) {\n if (el instanceof SVGElement) {\n var rect = el.getBoundingClientRect();\n return {\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height\n };\n } else {\n return {\n top: el.offsetTop,\n left: el.offsetLeft,\n width: el.offsetWidth,\n height: el.offsetHeight\n };\n }\n };\n\n return me;\n })();\n\n function IScroll(el, options) {\n this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;\n this.scroller = this.wrapper.children[0];\n this.scrollerStyle = this.scroller.style; // cache style for better performance\n\n this.options = {\n\n resizeScrollbars: true,\n\n mouseWheelSpeed: 20,\n\n snapThreshold: 0.334,\n\n // INSERT POINT: OPTIONS\n disablePointer: false,\n disableTouch: utils.hasPointer || !utils.hasTouch,\n disableMouse: utils.hasPointer || utils.hasTouch,\n startX: 0,\n startY: 0,\n scrollY: true,\n directionLockThreshold: 5,\n momentum: true,\n\n bounce: true,\n bounceTime: 600,\n bounceEasing: '',\n\n preventDefault: true,\n preventDefaultException: {\n tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/\n },\n\n HWCompositing: true,\n useTransition: true,\n useTransform: true,\n bindToWrapper: typeof window.onmousedown === \"undefined\"\n };\n\n for (var i in options) {\n this.options[i] = options[i];\n }\n\n // Normalize options\n this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';\n\n this.options.useTransition = utils.hasTransition && this.options.useTransition;\n this.options.useTransform = utils.hasTransform && this.options.useTransform;\n\n this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;\n this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;\n\n // If you want eventPassthrough I have to lock one of the axes\n this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;\n this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;\n\n // With eventPassthrough we also need lockDirection mechanism\n this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;\n this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;\n\n this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;\n\n this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;\n\n if (this.options.tap === true) {\n this.options.tap = 'tap';\n }\n\n // https://github.com/cubiq/iscroll/issues/1029\n if (!this.options.useTransition && !this.options.useTransform) {\n if (!(/relative|absolute/i).test(this.scrollerStyle.position)) {\n this.scrollerStyle.position = \"relative\";\n }\n }\n\n if (this.options.shrinkScrollbars == 'scale') {\n this.options.useTransition = false;\n }\n\n this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;\n\n if (this.options.probeType == 3) {\n this.options.useTransition = false;\n }\n\n // INSERT POINT: NORMALIZATION\n\n // Some defaults\n this.x = 0;\n this.y = 0;\n this.directionX = 0;\n this.directionY = 0;\n this._events = {};\n\n // INSERT POINT: DEFAULTS\n\n this._init();\n this.refresh();\n\n this.scrollTo(this.options.startX, this.options.startY);\n this.enable();\n }\n\n IScroll.prototype = {\n version: '5.2.0-snapshot',\n\n _init: function() {\n this._initEvents();\n\n if (this.options.scrollbars || this.options.indicators) {\n this._initIndicators();\n }\n\n if (this.options.mouseWheel) {\n this._initWheel();\n }\n\n if (this.options.snap) {\n this._initSnap();\n }\n\n if (this.options.keyBindings) {\n this._initKeys();\n }\n\n // INSERT POINT: _init\n\n },\n\n destroy: function() {\n this._initEvents(true);\n clearTimeout(this.resizeTimeout);\n this.resizeTimeout = null;\n this._execEvent('destroy');\n },\n\n _transitionEnd: function(e) {\n if (e.target != this.scroller || !this.isInTransition) {\n return;\n }\n\n this._transitionTime();\n if (!this.resetPosition(this.options.bounceTime)) {\n this.isInTransition = false;\n this._execEvent('scrollEnd');\n }\n },\n\n _start: function(e) {\n // React to left mouse button only\n if (utils.eventType[e.type] != 1) {\n // for button property\n // http://unixpapa.com/js/mouse.html\n var button;\n if (!e.which) {\n /* IE case */\n button = (e.button < 2) ? 0 : ((e.button == 4) ? 1 : 2);\n } else {\n /* All others */\n button = e.button;\n }\n if (button !== 0) {\n return;\n }\n }\n\n if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {\n return;\n }\n\n if (this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {\n e.preventDefault();\n }\n\n var point = e.touches ? e.touches[0] : e,\n pos;\n\n this.initiated = utils.eventType[e.type];\n this.moved = false;\n this.distX = 0;\n this.distY = 0;\n this.directionX = 0;\n this.directionY = 0;\n this.directionLocked = 0;\n\n this.startTime = utils.getTime();\n\n if (this.options.useTransition && this.isInTransition) {\n this._transitionTime();\n this.isInTransition = false;\n pos = this.getComputedPosition();\n this._translate(Math.round(pos.x), Math.round(pos.y));\n this._execEvent('scrollEnd');\n } else if (!this.options.useTransition && this.isAnimating) {\n this.isAnimating = false;\n this._execEvent('scrollEnd');\n }\n\n this.startX = this.x;\n this.startY = this.y;\n this.absStartX = this.x;\n this.absStartY = this.y;\n this.pointX = point.pageX;\n this.pointY = point.pageY;\n\n this._execEvent('beforeScrollStart');\n },\n\n _move: function(e) {\n if (!this.enabled || utils.eventType[e.type] !== this.initiated) {\n return;\n }\n\n if (this.options.preventDefault) { // increases performance on Android? TODO: check!\n e.preventDefault();\n }\n\n var point = e.touches ? e.touches[0] : e,\n deltaX = point.pageX - this.pointX,\n deltaY = point.pageY - this.pointY,\n timestamp = utils.getTime(),\n newX, newY,\n absDistX, absDistY;\n\n this.pointX = point.pageX;\n this.pointY = point.pageY;\n\n this.distX += deltaX;\n this.distY += deltaY;\n absDistX = Math.abs(this.distX);\n absDistY = Math.abs(this.distY);\n\n // We need to move at least 10 pixels for the scrolling to initiate\n if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) {\n return;\n }\n\n // If you are scrolling in one direction lock the other\n if (!this.directionLocked && !this.options.freeScroll) {\n if (absDistX > absDistY + this.options.directionLockThreshold) {\n this.directionLocked = 'h'; // lock horizontally\n } else if (absDistY >= absDistX + this.options.directionLockThreshold) {\n this.directionLocked = 'v'; // lock vertically\n } else {\n this.directionLocked = 'n'; // no lock\n }\n }\n\n if (this.directionLocked == 'h') {\n if (this.options.eventPassthrough == 'vertical') {\n e.preventDefault();\n } else if (this.options.eventPassthrough == 'horizontal') {\n this.initiated = false;\n return;\n }\n\n deltaY = 0;\n } else if (this.directionLocked == 'v') {\n if (this.options.eventPassthrough == 'horizontal') {\n e.preventDefault();\n } else if (this.options.eventPassthrough == 'vertical') {\n this.initiated = false;\n return;\n }\n\n deltaX = 0;\n }\n\n deltaX = this.hasHorizontalScroll ? deltaX : 0;\n deltaY = this.hasVerticalScroll ? deltaY : 0;\n\n newX = this.x + deltaX;\n newY = this.y + deltaY;\n\n // Slow down if outside of the boundaries\n if (newX > 0 || newX < this.maxScrollX) {\n newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;\n }\n if (newY > 0 || newY < this.maxScrollY) {\n newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;\n }\n\n this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n if (!this.moved) {\n this._execEvent('scrollStart');\n }\n\n this.moved = true;\n\n this._translate(newX, newY);\n\n /* REPLACE START: _move */\n if (timestamp - this.startTime > 300) {\n this.startTime = timestamp;\n this.startX = this.x;\n this.startY = this.y;\n\n if (this.options.probeType == 1) {\n this._execEvent('scroll');\n }\n }\n\n if (this.options.probeType > 1) {\n this._execEvent('scroll');\n }\n /* REPLACE END: _move */\n\n },\n\n _end: function(e) {\n if (!this.enabled || utils.eventType[e.type] !== this.initiated) {\n return;\n }\n\n if (this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {\n e.preventDefault();\n }\n\n var point = e.changedTouches ? e.changedTouches[0] : e,\n momentumX,\n momentumY,\n duration = utils.getTime() - this.startTime,\n newX = Math.round(this.x),\n newY = Math.round(this.y),\n distanceX = Math.abs(newX - this.startX),\n distanceY = Math.abs(newY - this.startY),\n time = 0,\n easing = '';\n\n this.isInTransition = 0;\n this.initiated = 0;\n this.endTime = utils.getTime();\n\n // reset if we are outside of the boundaries\n if (this.resetPosition(this.options.bounceTime)) {\n return;\n }\n\n this.scrollTo(newX, newY); // ensures that the last position is rounded\n\n // we scrolled less than 10 pixels\n if (!this.moved) {\n if (this.options.tap) {\n utils.tap(e, this.options.tap);\n }\n\n if (this.options.click) {\n utils.click(e);\n }\n\n this._execEvent('scrollCancel');\n return;\n }\n\n if (this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100) {\n this._execEvent('flick');\n return;\n }\n\n // start momentum animation if needed\n if (this.options.momentum && duration < 300) {\n momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : {\n destination: newX,\n duration: 0\n };\n momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : {\n destination: newY,\n duration: 0\n };\n newX = momentumX.destination;\n newY = momentumY.destination;\n time = Math.max(momentumX.duration, momentumY.duration);\n this.isInTransition = 1;\n }\n\n\n if (this.options.snap) {\n var snap = this._nearestSnap(newX, newY);\n this.currentPage = snap;\n time = this.options.snapSpeed || Math.max(\n Math.max(\n Math.min(Math.abs(newX - snap.x), 1000),\n Math.min(Math.abs(newY - snap.y), 1000)), 300);\n newX = snap.x;\n newY = snap.y;\n\n this.directionX = 0;\n this.directionY = 0;\n easing = this.options.bounceEasing;\n }\n\n // INSERT POINT: _end\n\n if (newX != this.x || newY != this.y) {\n // change easing function when scroller goes out of the boundaries\n if (newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) {\n easing = utils.ease.quadratic;\n }\n\n this.scrollTo(newX, newY, time, easing);\n return;\n }\n\n this._execEvent('scrollEnd');\n },\n\n _resize: function() {\n var that = this;\n\n clearTimeout(this.resizeTimeout);\n\n this.resizeTimeout = setTimeout(function() {\n that.refresh();\n }, this.options.resizePolling);\n },\n\n resetPosition: function(time) {\n var x = this.x,\n y = this.y;\n\n time = time || 0;\n\n if (!this.hasHorizontalScroll || this.x > 0) {\n x = 0;\n } else if (this.x < this.maxScrollX) {\n x = this.maxScrollX;\n }\n\n if (!this.hasVerticalScroll || this.y > 0) {\n y = 0;\n } else if (this.y < this.maxScrollY) {\n y = this.maxScrollY;\n }\n\n if (x == this.x && y == this.y) {\n return false;\n }\n\n this.scrollTo(x, y, time, this.options.bounceEasing);\n\n return true;\n },\n\n disable: function() {\n this.enabled = false;\n },\n\n enable: function() {\n this.enabled = true;\n },\n\n refresh: function() {\n utils.getRect(this.wrapper); // Force reflow\n\n this.wrapperWidth = this.wrapper.clientWidth;\n this.wrapperHeight = this.wrapper.clientHeight;\n\n var rect = utils.getRect(this.scroller);\n /* REPLACE START: refresh */\n\n this.scrollerWidth = rect.width;\n this.scrollerHeight = rect.height;\n\n this.maxScrollX = this.wrapperWidth - this.scrollerWidth;\n this.maxScrollY = this.wrapperHeight - this.scrollerHeight;\n\n /* REPLACE END: refresh */\n\n this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;\n this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;\n\n if (!this.hasHorizontalScroll) {\n this.maxScrollX = 0;\n this.scrollerWidth = this.wrapperWidth;\n }\n\n if (!this.hasVerticalScroll) {\n this.maxScrollY = 0;\n this.scrollerHeight = this.wrapperHeight;\n }\n\n this.endTime = 0;\n this.directionX = 0;\n this.directionY = 0;\n\n if (utils.hasPointer && !this.options.disablePointer) {\n // The wrapper should have `touchAction` property for using pointerEvent.\n this.wrapper.style[utils.style.touchAction] = utils.getTouchAction(this.options.eventPassthrough, true);\n\n // case. not support 'pinch-zoom'\n // https://github.com/cubiq/iscroll/issues/1118#issuecomment-270057583\n if (!this.wrapper.style[utils.style.touchAction]) {\n this.wrapper.style[utils.style.touchAction] = utils.getTouchAction(this.options.eventPassthrough, false);\n }\n }\n this.wrapperOffset = utils.offset(this.wrapper);\n\n this._execEvent('refresh');\n\n this.resetPosition();\n\n // INSERT POINT: _refresh\n\n },\n\n on: function(type, fn) {\n if (!this._events[type]) {\n this._events[type] = [];\n }\n\n this._events[type].push(fn);\n },\n\n off: function(type, fn) {\n if (!this._events[type]) {\n return;\n }\n\n var index = this._events[type].indexOf(fn);\n\n if (index > -1) {\n this._events[type].splice(index, 1);\n }\n },\n\n _execEvent: function(type) {\n if (!this._events[type]) {\n return;\n }\n\n var i = 0,\n l = this._events[type].length;\n\n if (!l) {\n return;\n }\n\n for (; i < l; i++) {\n this._events[type][i].apply(this, [].slice.call(arguments, 1));\n }\n },\n\n scrollBy: function(x, y, time, easing) {\n x = this.x + x;\n y = this.y + y;\n time = time || 0;\n\n this.scrollTo(x, y, time, easing);\n },\n\n scrollTo: function(x, y, time, easing) {\n easing = easing || utils.ease.circular;\n\n this.isInTransition = this.options.useTransition && time > 0;\n var transitionType = this.options.useTransition && easing.style;\n if (!time || transitionType) {\n if (transitionType) {\n this._transitionTimingFunction(easing.style);\n this._transitionTime(time);\n }\n this._translate(x, y);\n } else {\n this._animate(x, y, time, easing.fn);\n }\n },\n\n scrollToElement: function(el, time, offsetX, offsetY, easing) {\n el = el.nodeType ? el : this.scroller.querySelector(el);\n\n if (!el) {\n return;\n }\n\n var pos = utils.offset(el);\n\n pos.left -= this.wrapperOffset.left;\n pos.top -= this.wrapperOffset.top;\n\n // if offsetX/Y are true we center the element to the screen\n var elRect = utils.getRect(el);\n var wrapperRect = utils.getRect(this.wrapper);\n if (offsetX === true) {\n offsetX = Math.round(elRect.width / 2 - wrapperRect.width / 2);\n }\n if (offsetY === true) {\n offsetY = Math.round(elRect.height / 2 - wrapperRect.height / 2);\n }\n\n pos.left -= offsetX || 0;\n pos.top -= offsetY || 0;\n\n pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;\n pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;\n\n time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x - pos.left), Math.abs(this.y - pos.top)) : time;\n\n this.scrollTo(pos.left, pos.top, time, easing);\n },\n\n _transitionTime: function(time) {\n if (!this.options.useTransition) {\n return;\n }\n time = time || 0;\n var durationProp = utils.style.transitionDuration;\n if (!durationProp) {\n return;\n }\n\n this.scrollerStyle[durationProp] = time + 'ms';\n\n if (!time && utils.isBadAndroid) {\n this.scrollerStyle[durationProp] = '0.0001ms';\n // remove 0.0001ms\n var self = this;\n rAF(function() {\n if (self.scrollerStyle[durationProp] === '0.0001ms') {\n self.scrollerStyle[durationProp] = '0s';\n }\n });\n }\n\n\n if (this.indicators) {\n for (var i = this.indicators.length; i--;) {\n this.indicators[i].transitionTime(time);\n }\n }\n\n\n // INSERT POINT: _transitionTime\n\n },\n\n _transitionTimingFunction: function(easing) {\n this.scrollerStyle[utils.style.transitionTimingFunction] = easing;\n\n\n if (this.indicators) {\n for (var i = this.indicators.length; i--;) {\n this.indicators[i].transitionTimingFunction(easing);\n }\n }\n\n\n // INSERT POINT: _transitionTimingFunction\n\n },\n\n _translate: function(x, y) {\n if (this.options.useTransform) {\n\n /* REPLACE START: _translate */\n\n this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;\n\n /* REPLACE END: _translate */\n\n } else {\n x = Math.round(x);\n y = Math.round(y);\n this.scrollerStyle.left = x + 'px';\n this.scrollerStyle.top = y + 'px';\n }\n\n this.x = x;\n this.y = y;\n\n\n if (this.indicators) {\n for (var i = this.indicators.length; i--;) {\n this.indicators[i].updatePosition();\n }\n }\n\n\n // INSERT POINT: _translate\n\n },\n\n _initEvents: function(remove) {\n var eventType = remove ? utils.removeEvent : utils.addEvent,\n target = this.options.bindToWrapper ? this.wrapper : window;\n\n eventType(window, 'orientationchange', this);\n eventType(window, 'resize', this);\n\n if (this.options.click) {\n eventType(this.wrapper, 'click', this, true);\n }\n\n if (!this.options.disableMouse) {\n eventType(this.wrapper, 'mousedown', this);\n eventType(target, 'mousemove', this);\n eventType(target, 'mousecancel', this);\n eventType(target, 'mouseup', this);\n }\n\n if (utils.hasPointer && !this.options.disablePointer) {\n eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);\n eventType(target, utils.prefixPointerEvent('pointermove'), this);\n eventType(target, utils.prefixPointerEvent('pointercancel'), this);\n eventType(target, utils.prefixPointerEvent('pointerup'), this);\n }\n\n if (utils.hasTouch && !this.options.disableTouch) {\n eventType(this.wrapper, 'touchstart', this);\n eventType(target, 'touchmove', this);\n eventType(target, 'touchcancel', this);\n eventType(target, 'touchend', this);\n }\n\n eventType(this.scroller, 'transitionend', this);\n eventType(this.scroller, 'webkitTransitionEnd', this);\n eventType(this.scroller, 'oTransitionEnd', this);\n eventType(this.scroller, 'MSTransitionEnd', this);\n },\n\n getComputedPosition: function() {\n var matrix = window.getComputedStyle(this.scroller, null),\n x, y;\n\n if (this.options.useTransform) {\n matrix = matrix[utils.style.transform].split(')')[0].split(', ');\n x = +(matrix[12] || matrix[4]);\n y = +(matrix[13] || matrix[5]);\n } else {\n x = +matrix.left.replace(/[^-\\d.]/g, '');\n y = +matrix.top.replace(/[^-\\d.]/g, '');\n }\n\n return {\n x: x,\n y: y\n };\n },\n _initIndicators: function() {\n var interactive = this.options.interactiveScrollbars,\n customStyle = typeof this.options.scrollbars != 'string',\n indicators = [],\n indicator;\n\n var that = this;\n\n this.indicators = [];\n\n if (this.options.scrollbars) {\n // Vertical scrollbar\n if (this.options.scrollY) {\n indicator = {\n el: createDefaultScrollbar('v', interactive, this.options.scrollbars),\n interactive: interactive,\n defaultScrollbars: true,\n customStyle: customStyle,\n resize: this.options.resizeScrollbars,\n shrink: this.options.shrinkScrollbars,\n fade: this.options.fadeScrollbars,\n listenX: false\n };\n\n this.wrapper.appendChild(indicator.el);\n indicators.push(indicator);\n }\n\n // Horizontal scrollbar\n if (this.options.scrollX) {\n indicator = {\n el: createDefaultScrollbar('h', interactive, this.options.scrollbars),\n interactive: interactive,\n defaultScrollbars: true,\n customStyle: customStyle,\n resize: this.options.resizeScrollbars,\n shrink: this.options.shrinkScrollbars,\n fade: this.options.fadeScrollbars,\n listenY: false\n };\n\n this.wrapper.appendChild(indicator.el);\n indicators.push(indicator);\n }\n }\n\n if (this.options.indicators) {\n // TODO: check concat compatibility\n indicators = indicators.concat(this.options.indicators);\n }\n\n for (var i = indicators.length; i--;) {\n this.indicators.push(new Indicator(this, indicators[i]));\n }\n\n // TODO: check if we can use array.map (wide compatibility and performance issues)\n function _indicatorsMap(fn) {\n if (that.indicators) {\n for (var i = that.indicators.length; i--;) {\n fn.call(that.indicators[i]);\n }\n }\n }\n\n if (this.options.fadeScrollbars) {\n this.on('scrollEnd', function() {\n _indicatorsMap(function() {\n this.fade();\n });\n });\n\n this.on('scrollCancel', function() {\n _indicatorsMap(function() {\n this.fade();\n });\n });\n\n this.on('scrollStart', function() {\n _indicatorsMap(function() {\n this.fade(1);\n });\n });\n\n this.on('beforeScrollStart', function() {\n _indicatorsMap(function() {\n this.fade(1, true);\n });\n });\n }\n\n\n this.on('refresh', function() {\n _indicatorsMap(function() {\n this.refresh();\n });\n });\n\n this.on('destroy', function() {\n _indicatorsMap(function() {\n this.destroy();\n });\n\n delete this.indicators;\n });\n },\n\n _initWheel: function() {\n utils.addEvent(this.wrapper, 'wheel', this);\n utils.addEvent(this.wrapper, 'mousewheel', this);\n utils.addEvent(this.wrapper, 'DOMMouseScroll', this);\n\n this.on('destroy', function() {\n clearTimeout(this.wheelTimeout);\n this.wheelTimeout = null;\n utils.removeEvent(this.wrapper, 'wheel', this);\n utils.removeEvent(this.wrapper, 'mousewheel', this);\n utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);\n });\n },\n\n _wheel: function(e) {\n if (!this.enabled) {\n return;\n }\n\n e.preventDefault();\n\n var wheelDeltaX, wheelDeltaY,\n newX, newY,\n that = this;\n\n if (this.wheelTimeout === undefined) {\n that._execEvent('scrollStart');\n }\n\n // Execute the scrollEnd event after 400ms the wheel stopped scrolling\n clearTimeout(this.wheelTimeout);\n this.wheelTimeout = setTimeout(function() {\n if (!that.options.snap) {\n that._execEvent('scrollEnd');\n }\n that.wheelTimeout = undefined;\n }, 400);\n\n if ('deltaX' in e) {\n if (e.deltaMode === 1) {\n wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;\n wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;\n } else {\n wheelDeltaX = -e.deltaX;\n wheelDeltaY = -e.deltaY;\n }\n } else if ('wheelDeltaX' in e) {\n wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;\n wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;\n } else if ('wheelDelta' in e) {\n wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;\n } else if ('detail' in e) {\n wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;\n } else {\n return;\n }\n\n wheelDeltaX *= this.options.invertWheelDirection;\n wheelDeltaY *= this.options.invertWheelDirection;\n\n if (!this.hasVerticalScroll) {\n wheelDeltaX = wheelDeltaY;\n wheelDeltaY = 0;\n }\n\n if (this.options.snap) {\n newX = this.currentPage.pageX;\n newY = this.currentPage.pageY;\n\n if (wheelDeltaX > 0) {\n newX--;\n } else if (wheelDeltaX < 0) {\n newX++;\n }\n\n if (wheelDeltaY > 0) {\n newY--;\n } else if (wheelDeltaY < 0) {\n newY++;\n }\n\n this.goToPage(newX, newY);\n\n return;\n }\n\n newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);\n newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);\n\n this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;\n this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;\n\n if (newX > 0) {\n newX = 0;\n } else if (newX < this.maxScrollX) {\n newX = this.maxScrollX;\n }\n\n if (newY > 0) {\n newY = 0;\n } else if (newY < this.maxScrollY) {\n newY = this.maxScrollY;\n }\n\n this.scrollTo(newX, newY, 0);\n\n if (this.options.probeType > 1) {\n this._execEvent('scroll');\n }\n\n // INSERT POINT: _wheel\n },\n\n _initSnap: function() {\n this.currentPage = {};\n\n if (typeof this.options.snap == 'string') {\n this.options.snap = this.scroller.querySelectorAll(this.options.snap);\n }\n\n this.on('refresh', function() {\n var i = 0,\n l,\n m = 0,\n n,\n cx, cy,\n x = 0,\n y,\n stepX = this.options.snapStepX || this.wrapperWidth,\n stepY = this.options.snapStepY || this.wrapperHeight,\n el,\n rect;\n\n this.pages = [];\n\n if (!this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight) {\n return;\n }\n\n if (this.options.snap === true) {\n cx = Math.round(stepX / 2);\n cy = Math.round(stepY / 2);\n\n while (x > -this.scrollerWidth) {\n this.pages[i] = [];\n l = 0;\n y = 0;\n\n while (y > -this.scrollerHeight) {\n this.pages[i][l] = {\n x: Math.max(x, this.maxScrollX),\n y: Math.max(y, this.maxScrollY),\n width: stepX,\n height: stepY,\n cx: x - cx,\n cy: y - cy\n };\n\n y -= stepY;\n l++;\n }\n\n x -= stepX;\n i++;\n }\n } else {\n el = this.options.snap;\n l = el.length;\n n = -1;\n\n for (; i < l; i++) {\n rect = utils.getRect(el[i]);\n if (i === 0 || rect.left <= utils.getRect(el[i - 1]).left) {\n m = 0;\n n++;\n }\n\n if (!this.pages[m]) {\n this.pages[m] = [];\n }\n\n x = Math.max(-rect.left, this.maxScrollX);\n y = Math.max(-rect.top, this.maxScrollY);\n cx = x - Math.round(rect.width / 2);\n cy = y - Math.round(rect.height / 2);\n\n this.pages[m][n] = {\n x: x,\n y: y,\n width: rect.width,\n height: rect.height,\n cx: cx,\n cy: cy\n };\n\n if (x > this.maxScrollX) {\n m++;\n }\n }\n }\n\n this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);\n\n // Update snap threshold if needed\n if (this.options.snapThreshold % 1 === 0) {\n this.snapThresholdX = this.options.snapThreshold;\n this.snapThresholdY = this.options.snapThreshold;\n } else {\n this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);\n this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);\n }\n });\n\n this.on('flick', function() {\n var time = this.options.snapSpeed || Math.max(\n Math.max(\n Math.min(Math.abs(this.x - this.startX), 1000),\n Math.min(Math.abs(this.y - this.startY), 1000)), 300);\n\n this.goToPage(\n this.currentPage.pageX + this.directionX,\n this.currentPage.pageY + this.directionY,\n time);\n });\n },\n\n _nearestSnap: function(x, y) {\n if (!this.pages.length) {\n return {\n x: 0,\n y: 0,\n pageX: 0,\n pageY: 0\n };\n }\n\n var i = 0,\n l = this.pages.length,\n m = 0;\n\n // Check if we exceeded the snap threshold\n if (Math.abs(x - this.absStartX) < this.snapThresholdX && Math.abs(y - this.absStartY) < this.snapThresholdY) {\n return this.currentPage;\n }\n\n if (x > 0) {\n x = 0;\n } else if (x < this.maxScrollX) {\n x = this.maxScrollX;\n }\n\n if (y > 0) {\n y = 0;\n } else if (y < this.maxScrollY) {\n y = this.maxScrollY;\n }\n\n for (; i < l; i++) {\n if (x >= this.pages[i][0].cx) {\n x = this.pages[i][0].x;\n break;\n }\n }\n\n l = this.pages[i].length;\n\n for (; m < l; m++) {\n if (y >= this.pages[0][m].cy) {\n y = this.pages[0][m].y;\n break;\n }\n }\n\n if (i == this.currentPage.pageX) {\n i += this.directionX;\n\n if (i < 0) {\n i = 0;\n } else if (i >= this.pages.length) {\n i = this.pages.length - 1;\n }\n\n x = this.pages[i][0].x;\n }\n\n if (m == this.currentPage.pageY) {\n m += this.directionY;\n\n if (m < 0) {\n m = 0;\n } else if (m >= this.pages[0].length) {\n m = this.pages[0].length - 1;\n }\n\n y = this.pages[0][m].y;\n }\n\n return {\n x: x,\n y: y,\n pageX: i,\n pageY: m\n };\n },\n\n goToPage: function(x, y, time, easing) {\n easing = easing || this.options.bounceEasing;\n\n if (x >= this.pages.length) {\n x = this.pages.length - 1;\n } else if (x < 0) {\n x = 0;\n }\n\n if (y >= this.pages[x].length) {\n y = this.pages[x].length - 1;\n } else if (y < 0) {\n y = 0;\n }\n\n var posX = this.pages[x][y].x,\n posY = this.pages[x][y].y;\n\n time = time === undefined ? this.options.snapSpeed || Math.max(\n Math.max(\n Math.min(Math.abs(posX - this.x), 1000),\n Math.min(Math.abs(posY - this.y), 1000)), 300) : time;\n\n this.currentPage = {\n x: posX,\n y: posY,\n pageX: x,\n pageY: y\n };\n\n this.scrollTo(posX, posY, time, easing);\n },\n\n next: function(time, easing) {\n var x = this.currentPage.pageX,\n y = this.currentPage.pageY;\n\n x++;\n\n if (x >= this.pages.length && this.hasVerticalScroll) {\n x = 0;\n y++;\n }\n\n this.goToPage(x, y, time, easing);\n },\n\n prev: function(time, easing) {\n var x = this.currentPage.pageX,\n y = this.currentPage.pageY;\n\n x--;\n\n if (x < 0 && this.hasVerticalScroll) {\n x = 0;\n y--;\n }\n\n this.goToPage(x, y, time, easing);\n },\n\n _initKeys: function(e) {\n // default key bindings\n var keys = {\n pageUp: 33,\n pageDown: 34,\n end: 35,\n home: 36,\n left: 37,\n up: 38,\n right: 39,\n down: 40\n };\n var i;\n\n // if you give me characters I give you keycode\n if (typeof this.options.keyBindings == 'object') {\n for (i in this.options.keyBindings) {\n if (typeof this.options.keyBindings[i] == 'string') {\n this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);\n }\n }\n } else {\n this.options.keyBindings = {};\n }\n\n for (i in keys) {\n this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];\n }\n\n utils.addEvent(window, 'keydown', this);\n\n this.on('destroy', function() {\n utils.removeEvent(window, 'keydown', this);\n });\n },\n\n _key: function(e) {\n if (!this.enabled) {\n return;\n }\n\n var snap = this.options.snap, // we are using this alot, better to cache it\n newX = snap ? this.currentPage.pageX : this.x,\n newY = snap ? this.currentPage.pageY : this.y,\n now = utils.getTime(),\n prevTime = this.keyTime || 0,\n acceleration = 0.250,\n pos;\n\n if (this.options.useTransition && this.isInTransition) {\n pos = this.getComputedPosition();\n\n this._translate(Math.round(pos.x), Math.round(pos.y));\n this.isInTransition = false;\n }\n\n this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;\n\n switch (e.keyCode) {\n case this.options.keyBindings.pageUp:\n if (this.hasHorizontalScroll && !this.hasVerticalScroll) {\n newX += snap ? 1 : this.wrapperWidth;\n } else {\n newY += snap ? 1 : this.wrapperHeight;\n }\n break;\n case this.options.keyBindings.pageDown:\n if (this.hasHorizontalScroll && !this.hasVerticalScroll) {\n newX -= snap ? 1 : this.wrapperWidth;\n } else {\n newY -= snap ? 1 : this.wrapperHeight;\n }\n break;\n case this.options.keyBindings.end:\n newX = snap ? this.pages.length - 1 : this.maxScrollX;\n newY = snap ? this.pages[0].length - 1 : this.maxScrollY;\n break;\n case this.options.keyBindings.home:\n newX = 0;\n newY = 0;\n break;\n case this.options.keyBindings.left:\n newX += snap ? -1 : 5 + this.keyAcceleration >> 0;\n break;\n case this.options.keyBindings.up:\n newY += snap ? 1 : 5 + this.keyAcceleration >> 0;\n break;\n case this.options.keyBindings.right:\n newX -= snap ? -1 : 5 + this.keyAcceleration >> 0;\n break;\n case this.options.keyBindings.down:\n newY -= snap ? 1 : 5 + this.keyAcceleration >> 0;\n break;\n default:\n return;\n }\n\n if (snap) {\n this.goToPage(newX, newY);\n return;\n }\n\n if (newX > 0) {\n newX = 0;\n this.keyAcceleration = 0;\n } else if (newX < this.maxScrollX) {\n newX = this.maxScrollX;\n this.keyAcceleration = 0;\n }\n\n if (newY > 0) {\n newY = 0;\n this.keyAcceleration = 0;\n } else if (newY < this.maxScrollY) {\n newY = this.maxScrollY;\n this.keyAcceleration = 0;\n }\n\n this.scrollTo(newX, newY, 0);\n\n this.keyTime = now;\n },\n\n _animate: function(destX, destY, duration, easingFn) {\n var that = this,\n startX = this.x,\n startY = this.y,\n startTime = utils.getTime(),\n destTime = startTime + duration;\n\n function step() {\n var now = utils.getTime(),\n newX, newY,\n easing;\n\n if (now >= destTime) {\n that.isAnimating = false;\n that._translate(destX, destY);\n\n if (!that.resetPosition(that.options.bounceTime)) {\n that._execEvent('scrollEnd');\n }\n\n return;\n }\n\n now = (now - startTime) / duration;\n easing = easingFn(now);\n newX = (destX - startX) * easing + startX;\n newY = (destY - startY) * easing + startY;\n that._translate(newX, newY);\n\n if (that.isAnimating) {\n rAF(step);\n }\n\n if (that.options.probeType == 3) {\n that._execEvent('scroll');\n }\n }\n\n this.isAnimating = true;\n step();\n },\n\n handleEvent: function(e) {\n switch (e.type) {\n case 'touchstart':\n case 'pointerdown':\n case 'MSPointerDown':\n case 'mousedown':\n this._start(e);\n break;\n case 'touchmove':\n case 'pointermove':\n case 'MSPointerMove':\n case 'mousemove':\n this._move(e);\n break;\n case 'touchend':\n case 'pointerup':\n case 'MSPointerUp':\n case 'mouseup':\n case 'touchcancel':\n case 'pointercancel':\n case 'MSPointerCancel':\n case 'mousecancel':\n this._end(e);\n break;\n case 'orientationchange':\n case 'resize':\n this._resize();\n break;\n case 'transitionend':\n case 'webkitTransitionEnd':\n case 'oTransitionEnd':\n case 'MSTransitionEnd':\n this._transitionEnd(e);\n break;\n case 'wheel':\n case 'DOMMouseScroll':\n case 'mousewheel':\n this._wheel(e);\n break;\n case 'keydown':\n this._key(e);\n break;\n case 'click':\n if (this.enabled && !e._constructed) {\n e.preventDefault();\n e.stopPropagation();\n }\n break;\n }\n }\n };\n\n function createDefaultScrollbar(direction, interactive, type) {\n var scrollbar = document.createElement('div'),\n indicator = document.createElement('div');\n\n if (type === true) {\n scrollbar.style.cssText = 'position:absolute;z-index:9999';\n indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';\n }\n\n indicator.className = 'iScrollIndicator';\n\n if (direction == 'h') {\n if (type === true) {\n scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';\n indicator.style.height = '100%';\n }\n scrollbar.className = 'iScrollHorizontalScrollbar';\n } else {\n if (type === true) {\n scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';\n indicator.style.width = '100%';\n }\n scrollbar.className = 'iScrollVerticalScrollbar';\n }\n\n scrollbar.style.cssText += ';overflow:hidden';\n\n if (!interactive) {\n scrollbar.style.pointerEvents = 'none';\n }\n\n scrollbar.appendChild(indicator);\n\n return scrollbar;\n }\n\n function Indicator(scroller, options) {\n this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;\n this.wrapperStyle = this.wrapper.style;\n this.indicator = this.wrapper.children[0];\n this.indicatorStyle = this.indicator.style;\n this.scroller = scroller;\n\n this.options = {\n listenX: true,\n listenY: true,\n interactive: false,\n resize: true,\n defaultScrollbars: false,\n shrink: false,\n fade: false,\n speedRatioX: 0,\n speedRatioY: 0\n };\n\n for (var i in options) {\n this.options[i] = options[i];\n }\n\n this.sizeRatioX = 1;\n this.sizeRatioY = 1;\n this.maxPosX = 0;\n this.maxPosY = 0;\n\n if (this.options.interactive) {\n if (!this.options.disableTouch) {\n utils.addEvent(this.indicator, 'touchstart', this);\n utils.addEvent(window, 'touchend', this);\n }\n if (!this.options.disablePointer) {\n utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);\n }\n if (!this.options.disableMouse) {\n utils.addEvent(this.indicator, 'mousedown', this);\n utils.addEvent(window, 'mouseup', this);\n }\n }\n\n if (this.options.fade) {\n this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;\n var durationProp = utils.style.transitionDuration;\n if (!durationProp) {\n return;\n }\n this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';\n // remove 0.0001ms\n var self = this;\n if (utils.isBadAndroid) {\n rAF(function() {\n if (self.wrapperStyle[durationProp] === '0.0001ms') {\n self.wrapperStyle[durationProp] = '0s';\n }\n });\n }\n this.wrapperStyle.opacity = '0';\n }\n }\n\n Indicator.prototype = {\n handleEvent: function(e) {\n switch (e.type) {\n case 'touchstart':\n case 'pointerdown':\n case 'MSPointerDown':\n case 'mousedown':\n this._start(e);\n break;\n case 'touchmove':\n case 'pointermove':\n case 'MSPointerMove':\n case 'mousemove':\n this._move(e);\n break;\n case 'touchend':\n case 'pointerup':\n case 'MSPointerUp':\n case 'mouseup':\n case 'touchcancel':\n case 'pointercancel':\n case 'MSPointerCancel':\n case 'mousecancel':\n this._end(e);\n break;\n }\n },\n\n destroy: function() {\n if (this.options.fadeScrollbars) {\n clearTimeout(this.fadeTimeout);\n this.fadeTimeout = null;\n }\n if (this.options.interactive) {\n utils.removeEvent(this.indicator, 'touchstart', this);\n utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n utils.removeEvent(this.indicator, 'mousedown', this);\n\n utils.removeEvent(window, 'touchmove', this);\n utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n utils.removeEvent(window, 'mousemove', this);\n\n utils.removeEvent(window, 'touchend', this);\n utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);\n utils.removeEvent(window, 'mouseup', this);\n }\n\n if (this.options.defaultScrollbars && this.wrapper.parentNode) {\n this.wrapper.parentNode.removeChild(this.wrapper);\n }\n },\n\n _start: function(e) {\n var point = e.touches ? e.touches[0] : e;\n\n e.preventDefault();\n e.stopPropagation();\n\n this.transitionTime();\n\n this.initiated = true;\n this.moved = false;\n this.lastPointX = point.pageX;\n this.lastPointY = point.pageY;\n\n this.startTime = utils.getTime();\n\n if (!this.options.disableTouch) {\n utils.addEvent(window, 'touchmove', this);\n }\n if (!this.options.disablePointer) {\n utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);\n }\n if (!this.options.disableMouse) {\n utils.addEvent(window, 'mousemove', this);\n }\n\n this.scroller._execEvent('beforeScrollStart');\n },\n\n _move: function(e) {\n var point = e.touches ? e.touches[0] : e,\n deltaX, deltaY,\n newX, newY,\n timestamp = utils.getTime();\n\n if (!this.moved) {\n this.scroller._execEvent('scrollStart');\n }\n\n this.moved = true;\n\n deltaX = point.pageX - this.lastPointX;\n this.lastPointX = point.pageX;\n\n deltaY = point.pageY - this.lastPointY;\n this.lastPointY = point.pageY;\n\n newX = this.x + deltaX;\n newY = this.y + deltaY;\n\n this._pos(newX, newY);\n\n\n if (this.scroller.options.probeType == 1 && timestamp - this.startTime > 300) {\n this.startTime = timestamp;\n this.scroller._execEvent('scroll');\n } else if (this.scroller.options.probeType > 1) {\n this.scroller._execEvent('scroll');\n }\n\n\n // INSERT POINT: indicator._move\n\n e.preventDefault();\n e.stopPropagation();\n },\n\n _end: function(e) {\n if (!this.initiated) {\n return;\n }\n\n this.initiated = false;\n\n e.preventDefault();\n e.stopPropagation();\n\n utils.removeEvent(window, 'touchmove', this);\n utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n utils.removeEvent(window, 'mousemove', this);\n\n if (this.scroller.options.snap) {\n var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);\n\n var time = this.options.snapSpeed || Math.max(\n Math.max(\n Math.min(Math.abs(this.scroller.x - snap.x), 1000),\n Math.min(Math.abs(this.scroller.y - snap.y), 1000)), 300);\n\n if (this.scroller.x != snap.x || this.scroller.y != snap.y) {\n this.scroller.directionX = 0;\n this.scroller.directionY = 0;\n this.scroller.currentPage = snap;\n this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);\n }\n }\n\n if (this.moved) {\n this.scroller._execEvent('scrollEnd');\n }\n },\n\n transitionTime: function(time) {\n time = time || 0;\n var durationProp = utils.style.transitionDuration;\n if (!durationProp) {\n return;\n }\n\n this.indicatorStyle[durationProp] = time + 'ms';\n\n if (!time && utils.isBadAndroid) {\n this.indicatorStyle[durationProp] = '0.0001ms';\n // remove 0.0001ms\n var self = this;\n rAF(function() {\n if (self.indicatorStyle[durationProp] === '0.0001ms') {\n self.indicatorStyle[durationProp] = '0s';\n }\n });\n }\n },\n\n transitionTimingFunction: function(easing) {\n this.indicatorStyle[utils.style.transitionTimingFunction] = easing;\n },\n\n refresh: function() {\n this.transitionTime();\n\n if (this.options.listenX && !this.options.listenY) {\n this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';\n } else if (this.options.listenY && !this.options.listenX) {\n this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';\n } else {\n this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';\n }\n\n if (this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll) {\n utils.addClass(this.wrapper, 'iScrollBothScrollbars');\n utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');\n\n if (this.options.defaultScrollbars && this.options.customStyle) {\n if (this.options.listenX) {\n this.wrapper.style.right = '8px';\n } else {\n this.wrapper.style.bottom = '8px';\n }\n }\n } else {\n utils.removeClass(this.wrapper, 'iScrollBothScrollbars');\n utils.addClass(this.wrapper, 'iScrollLoneScrollbar');\n\n if (this.options.defaultScrollbars && this.options.customStyle) {\n if (this.options.listenX) {\n this.wrapper.style.right = '2px';\n } else {\n this.wrapper.style.bottom = '2px';\n }\n }\n }\n\n utils.getRect(this.wrapper); // force refresh\n\n if (this.options.listenX) {\n this.wrapperWidth = this.wrapper.clientWidth;\n if (this.options.resize) {\n this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);\n this.indicatorStyle.width = this.indicatorWidth + 'px';\n } else {\n this.indicatorWidth = this.indicator.clientWidth;\n }\n\n this.maxPosX = this.wrapperWidth - this.indicatorWidth;\n\n if (this.options.shrink == 'clip') {\n this.minBoundaryX = -this.indicatorWidth + 8;\n this.maxBoundaryX = this.wrapperWidth - 8;\n } else {\n this.minBoundaryX = 0;\n this.maxBoundaryX = this.maxPosX;\n }\n\n this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));\n }\n\n if (this.options.listenY) {\n this.wrapperHeight = this.wrapper.clientHeight;\n if (this.options.resize) {\n this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);\n this.indicatorStyle.height = this.indicatorHeight + 'px';\n } else {\n this.indicatorHeight = this.indicator.clientHeight;\n }\n\n this.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\n if (this.options.shrink == 'clip') {\n this.minBoundaryY = -this.indicatorHeight + 8;\n this.maxBoundaryY = this.wrapperHeight - 8;\n } else {\n this.minBoundaryY = 0;\n this.maxBoundaryY = this.maxPosY;\n }\n\n this.maxPosY = this.wrapperHeight - this.indicatorHeight;\n this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));\n }\n\n this.updatePosition();\n },\n\n updatePosition: function() {\n var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,\n y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;\n\n if (!this.options.ignoreBoundaries) {\n if (x < this.minBoundaryX) {\n if (this.options.shrink == 'scale') {\n this.width = Math.max(this.indicatorWidth + x, 8);\n this.indicatorStyle.width = this.width + 'px';\n }\n x = this.minBoundaryX;\n } else if (x > this.maxBoundaryX) {\n if (this.options.shrink == 'scale') {\n this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);\n this.indicatorStyle.width = this.width + 'px';\n x = this.maxPosX + this.indicatorWidth - this.width;\n } else {\n x = this.maxBoundaryX;\n }\n } else if (this.options.shrink == 'scale' && this.width != this.indicatorWidth) {\n this.width = this.indicatorWidth;\n this.indicatorStyle.width = this.width + 'px';\n }\n\n if (y < this.minBoundaryY) {\n if (this.options.shrink == 'scale') {\n this.height = Math.max(this.indicatorHeight + y * 3, 8);\n this.indicatorStyle.height = this.height + 'px';\n }\n y = this.minBoundaryY;\n } else if (y > this.maxBoundaryY) {\n if (this.options.shrink == 'scale') {\n this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);\n this.indicatorStyle.height = this.height + 'px';\n y = this.maxPosY + this.indicatorHeight - this.height;\n } else {\n y = this.maxBoundaryY;\n }\n } else if (this.options.shrink == 'scale' && this.height != this.indicatorHeight) {\n this.height = this.indicatorHeight;\n this.indicatorStyle.height = this.height + 'px';\n }\n }\n\n this.x = x;\n this.y = y;\n\n if (this.scroller.options.useTransform) {\n this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;\n } else {\n this.indicatorStyle.left = x + 'px';\n this.indicatorStyle.top = y + 'px';\n }\n },\n\n _pos: function(x, y) {\n if (x < 0) {\n x = 0;\n } else if (x > this.maxPosX) {\n x = this.maxPosX;\n }\n\n if (y < 0) {\n y = 0;\n } else if (y > this.maxPosY) {\n y = this.maxPosY;\n }\n\n x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;\n y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;\n\n this.scroller.scrollTo(x, y);\n },\n\n fade: function(val, hold) {\n if (hold && !this.visible) {\n return;\n }\n\n clearTimeout(this.fadeTimeout);\n this.fadeTimeout = null;\n\n var time = val ? 250 : 500,\n delay = val ? 0 : 300;\n\n val = val ? '1' : '0';\n\n this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';\n\n this.fadeTimeout = setTimeout((function(val) {\n this.wrapperStyle.opacity = val;\n this.visible = +val;\n }).bind(this, val), delay);\n }\n };\n\n IScroll.utils = utils;\n\n if (typeof module != 'undefined' && module.exports) {\n module.exports = IScroll;\n } else if (typeof define == 'function' && define.amd) {\n define(function() {\n return IScroll;\n });\n } else {\n window.IScroll = IScroll;\n }\n\n})(window, document, Math);\n\n// ProgressBar.js 1.0.1\n// https://kimmobrunfeldt.github.io/progressbar.js\n// License: MIT\n\n(function(f) {\n if (typeof exports === \"object\" && typeof module !== \"undefined\") {\n module.exports = f()\n } else if (typeof define === \"function\" && define.amd) {\n define([], f)\n } else {\n var g;\n if (typeof window !== \"undefined\") {\n g = window\n } else if (typeof global !== \"undefined\") {\n g = global\n } else if (typeof self !== \"undefined\") {\n g = self\n } else {\n g = this\n }\n g.ProgressBar = f()\n }\n})(function() {\n var define, module, exports;\n return (function e(t, n, r) {\n function s(o, u) {\n if (!n[o]) {\n if (!t[o]) {\n var a = typeof require == \"function\" && require;\n if (!u && a) return a(o, !0);\n if (i) return i(o, !0);\n var f = new Error(\"Cannot find module '\" + o + \"'\");\n throw f.code = \"MODULE_NOT_FOUND\", f\n }\n var l = n[o] = {\n exports: {}\n };\n t[o][0].call(l.exports, function(e) {\n var n = t[o][1][e];\n return s(n ? n : e)\n }, l, l.exports, e, t, n, r)\n }\n return n[o].exports\n }\n var i = typeof require == \"function\" && require;\n for (var o = 0; o < r.length; o++) s(r[o]);\n return s\n })({\n 1: [function(require, module, exports) {\n /* shifty - v1.5.2 - 2016-02-10 - http://jeremyckahn.github.io/shifty */;\n (function() {\n var root = this || Function('return this')();\n\n /**\n * Shifty Core\n * By Jeremy Kahn - jeremyckahn@gmail.com\n */\n\n var Tweenable = (function() {\n\n 'use strict';\n\n // Aliases that get defined later in this function\n var formula;\n\n // CONSTANTS\n var DEFAULT_SCHEDULE_FUNCTION;\n var DEFAULT_EASING = 'linear';\n var DEFAULT_DURATION = 500;\n var UPDATE_TIME = 1000 / 60;\n\n var _now = Date.now ? Date.now : function() {\n return +new Date();\n };\n\n var now = typeof SHIFTY_DEBUG_NOW !== 'undefined' ? SHIFTY_DEBUG_NOW : _now;\n\n if (typeof window !== 'undefined') {\n // requestAnimationFrame() shim by Paul Irish (modified for Shifty)\n // http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n DEFAULT_SCHEDULE_FUNCTION = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || (window.mozCancelRequestAnimationFrame && window.mozRequestAnimationFrame) || setTimeout;\n } else {\n DEFAULT_SCHEDULE_FUNCTION = setTimeout;\n }\n\n function noop() {\n // NOOP!\n }\n\n /**\n * Handy shortcut for doing a for-in loop. This is not a \"normal\" each\n * function, it is optimized for Shifty. The iterator function only receives\n * the property name, not the value.\n * @param {Object} obj\n * @param {Function(string)} fn\n * @private\n */\n function each(obj, fn) {\n var key;\n for (key in obj) {\n if (Object.hasOwnProperty.call(obj, key)) {\n fn(key);\n }\n }\n }\n\n /**\n * Perform a shallow copy of Object properties.\n * @param {Object} targetObject The object to copy into\n * @param {Object} srcObject The object to copy from\n * @return {Object} A reference to the augmented `targetObj` Object\n * @private\n */\n function shallowCopy(targetObj, srcObj) {\n each(srcObj, function(prop) {\n targetObj[prop] = srcObj[prop];\n });\n\n return targetObj;\n }\n\n /**\n * Copies each property from src onto target, but only if the property to\n * copy to target is undefined.\n * @param {Object} target Missing properties in this Object are filled in\n * @param {Object} src\n * @private\n */\n function defaults(target, src) {\n each(src, function(prop) {\n if (typeof target[prop] === 'undefined') {\n target[prop] = src[prop];\n }\n });\n }\n\n /**\n * Calculates the interpolated tween values of an Object for a given\n * timestamp.\n * @param {Number} forPosition The position to compute the state for.\n * @param {Object} currentState Current state properties.\n * @param {Object} originalState: The original state properties the Object is\n * tweening from.\n * @param {Object} targetState: The destination state properties the Object\n * is tweening to.\n * @param {number} duration: The length of the tween in milliseconds.\n * @param {number} timestamp: The UNIX epoch time at which the tween began.\n * @param {Object} easing: This Object's keys must correspond to the keys in\n * targetState.\n * @private\n */\n function tweenProps(forPosition, currentState, originalState, targetState,\n duration, timestamp, easing) {\n var normalizedPosition = forPosition < timestamp ? 0 : (forPosition - timestamp) / duration;\n\n\n var prop;\n var easingObjectProp;\n var easingFn;\n for (prop in currentState) {\n if (currentState.hasOwnProperty(prop)) {\n easingObjectProp = easing[prop];\n easingFn = typeof easingObjectProp === 'function' ? easingObjectProp : formula[easingObjectProp];\n\n currentState[prop] = tweenProp(\n originalState[prop],\n targetState[prop],\n easingFn,\n normalizedPosition);\n }\n }\n\n return currentState;\n }\n\n /**\n * Tweens a single property.\n * @param {number} start The value that the tween started from.\n * @param {number} end The value that the tween should end at.\n * @param {Function} easingFunc The easing curve to apply to the tween.\n * @param {number} position The normalized position (between 0.0 and 1.0) to\n * calculate the midpoint of 'start' and 'end' against.\n * @return {number} The tweened value.\n * @private\n */\n function tweenProp(start, end, easingFunc, position) {\n return start + (end - start) * easingFunc(position);\n }\n\n /**\n * Applies a filter to Tweenable instance.\n * @param {Tweenable} tweenable The `Tweenable` instance to call the filter\n * upon.\n * @param {String} filterName The name of the filter to apply.\n * @private\n */\n function applyFilter(tweenable, filterName) {\n var filters = Tweenable.prototype.filter;\n var args = tweenable._filterArgs;\n\n each(filters, function(name) {\n if (typeof filters[name][filterName] !== 'undefined') {\n filters[name][filterName].apply(tweenable, args);\n }\n });\n }\n\n var timeoutHandler_endTime;\n var timeoutHandler_currentTime;\n var timeoutHandler_isEnded;\n var timeoutHandler_offset;\n /**\n * Handles the update logic for one step of a tween.\n * @param {Tweenable} tweenable\n * @param {number} timestamp\n * @param {number} delay\n * @param {number} duration\n * @param {Object} currentState\n * @param {Object} originalState\n * @param {Object} targetState\n * @param {Object} easing\n * @param {Function(Object, *, number)} step\n * @param {Function(Function,number)}} schedule\n * @param {number=} opt_currentTimeOverride Needed for accurate timestamp in\n * Tweenable#seek.\n * @private\n */\n function timeoutHandler(tweenable, timestamp, delay, duration, currentState,\n originalState, targetState, easing, step, schedule,\n opt_currentTimeOverride) {\n\n timeoutHandler_endTime = timestamp + delay + duration;\n\n timeoutHandler_currentTime = Math.min(opt_currentTimeOverride || now(), timeoutHandler_endTime);\n\n timeoutHandler_isEnded = timeoutHandler_currentTime >= timeoutHandler_endTime;\n\n timeoutHandler_offset = duration - (\n timeoutHandler_endTime - timeoutHandler_currentTime);\n\n if (tweenable.isPlaying()) {\n if (timeoutHandler_isEnded) {\n step(targetState, tweenable._attachment, timeoutHandler_offset);\n tweenable.stop(true);\n } else {\n tweenable._scheduleId = schedule(tweenable._timeoutHandler, UPDATE_TIME);\n\n applyFilter(tweenable, 'beforeTween');\n\n // If the animation has not yet reached the start point (e.g., there was\n // delay that has not yet completed), just interpolate the starting\n // position of the tween.\n if (timeoutHandler_currentTime < (timestamp + delay)) {\n tweenProps(1, currentState, originalState, targetState, 1, 1, easing);\n } else {\n tweenProps(timeoutHandler_currentTime, currentState, originalState,\n targetState, duration, timestamp + delay, easing);\n }\n\n applyFilter(tweenable, 'afterTween');\n\n step(currentState, tweenable._attachment, timeoutHandler_offset);\n }\n }\n }\n\n\n /**\n * Creates a usable easing Object from a string, a function or another easing\n * Object. If `easing` is an Object, then this function clones it and fills\n * in the missing properties with `\"linear\"`.\n * @param {Object.} fromTweenParams\n * @param {Object|string|Function} easing\n * @return {Object.}\n * @private\n */\n function composeEasingObject(fromTweenParams, easing) {\n var composedEasing = {};\n var typeofEasing = typeof easing;\n\n if (typeofEasing === 'string' || typeofEasing === 'function') {\n each(fromTweenParams, function(prop) {\n composedEasing[prop] = easing;\n });\n } else {\n each(fromTweenParams, function(prop) {\n if (!composedEasing[prop]) {\n composedEasing[prop] = easing[prop] || DEFAULT_EASING;\n }\n });\n }\n\n return composedEasing;\n }\n\n /**\n * Tweenable constructor.\n * @class Tweenable\n * @param {Object=} opt_initialState The values that the initial tween should\n * start at if a `from` object is not provided to `{{#crossLink\n * \"Tweenable/tween:method\"}}{{/crossLink}}` or `{{#crossLink\n * \"Tweenable/setConfig:method\"}}{{/crossLink}}`.\n * @param {Object=} opt_config Configuration object to be passed to\n * `{{#crossLink \"Tweenable/setConfig:method\"}}{{/crossLink}}`.\n * @module Tweenable\n * @constructor\n */\n function Tweenable(opt_initialState, opt_config) {\n this._currentState = opt_initialState || {};\n this._configured = false;\n this._scheduleFunction = DEFAULT_SCHEDULE_FUNCTION;\n\n // To prevent unnecessary calls to setConfig do not set default\n // configuration here. Only set default configuration immediately before\n // tweening if none has been set.\n if (typeof opt_config !== 'undefined') {\n this.setConfig(opt_config);\n }\n }\n\n /**\n * Configure and start a tween.\n * @method tween\n * @param {Object=} opt_config Configuration object to be passed to\n * `{{#crossLink \"Tweenable/setConfig:method\"}}{{/crossLink}}`.\n * @chainable\n */\n Tweenable.prototype.tween = function(opt_config) {\n if (this._isTweening) {\n return this;\n }\n\n // Only set default config if no configuration has been set previously and\n // none is provided now.\n if (opt_config !== undefined || !this._configured) {\n this.setConfig(opt_config);\n }\n\n this._timestamp = now();\n this._start(this.get(), this._attachment);\n return this.resume();\n };\n\n /**\n * Configure a tween that will start at some point in the future.\n *\n * @method setConfig\n * @param {Object} config The following values are valid:\n * - __from__ (_Object=_): Starting position. If omitted, `{{#crossLink\n * \"Tweenable/get:method\"}}get(){{/crossLink}}` is used.\n * - __to__ (_Object=_): Ending position.\n * - __duration__ (_number=_): How many milliseconds to animate for.\n * - __delay__ (_delay=_): How many milliseconds to wait before starting the\n * tween.\n * - __start__ (_Function(Object, *)_): Function to execute when the tween\n * begins. Receives the state of the tween as the first parameter and\n * `attachment` as the second parameter.\n * - __step__ (_Function(Object, *, number)_): Function to execute on every\n * tick. Receives `{{#crossLink\n * \"Tweenable/get:method\"}}get(){{/crossLink}}` as the first parameter,\n * `attachment` as the second parameter, and the time elapsed since the\n * start of the tween as the third. This function is not called on the\n * final step of the animation, but `finish` is.\n * - __finish__ (_Function(Object, *)_): Function to execute upon tween\n * completion. Receives the state of the tween as the first parameter and\n * `attachment` as the second parameter.\n * - __easing__ (_Object.|string|Function=_): Easing curve\n * name(s) or function(s) to use for the tween.\n * - __attachment__ (_*_): Cached value that is passed to the\n * `step`/`start`/`finish` methods.\n * @chainable\n */\n Tweenable.prototype.setConfig = function(config) {\n config = config || {};\n this._configured = true;\n\n // Attach something to this Tweenable instance (e.g.: a DOM element, an\n // object, a string, etc.);\n this._attachment = config.attachment;\n\n // Init the internal state\n this._pausedAtTime = null;\n this._scheduleId = null;\n this._delay = config.delay || 0;\n this._start = config.start || noop;\n this._step = config.step || noop;\n this._finish = config.finish || noop;\n this._duration = config.duration || DEFAULT_DURATION;\n this._currentState = shallowCopy({}, config.from) || this.get();\n this._originalState = this.get();\n this._targetState = shallowCopy({}, config.to) || this.get();\n\n var self = this;\n this._timeoutHandler = function() {\n timeoutHandler(self,\n self._timestamp,\n self._delay,\n self._duration,\n self._currentState,\n self._originalState,\n self._targetState,\n self._easing,\n self._step,\n self._scheduleFunction);\n };\n\n // Aliases used below\n var currentState = this._currentState;\n var targetState = this._targetState;\n\n // Ensure that there is always something to tween to.\n defaults(targetState, currentState);\n\n this._easing = composeEasingObject(\n currentState, config.easing || DEFAULT_EASING);\n\n this._filterArgs = [currentState, this._originalState, targetState, this._easing];\n\n applyFilter(this, 'tweenCreated');\n return this;\n };\n\n /**\n * @method get\n * @return {Object} The current state.\n */\n Tweenable.prototype.get = function() {\n return shallowCopy({}, this._currentState);\n };\n\n /**\n * @method set\n * @param {Object} state The current state.\n */\n Tweenable.prototype.set = function(state) {\n this._currentState = state;\n };\n\n /**\n * Pause a tween. Paused tweens can be resumed from the point at which they\n * were paused. This is different from `{{#crossLink\n * \"Tweenable/stop:method\"}}{{/crossLink}}`, as that method\n * causes a tween to start over when it is resumed.\n * @method pause\n * @chainable\n */\n Tweenable.prototype.pause = function() {\n this._pausedAtTime = now();\n this._isPaused = true;\n return this;\n };\n\n /**\n * Resume a paused tween.\n * @method resume\n * @chainable\n */\n Tweenable.prototype.resume = function() {\n if (this._isPaused) {\n this._timestamp += now() - this._pausedAtTime;\n }\n\n this._isPaused = false;\n this._isTweening = true;\n\n this._timeoutHandler();\n\n return this;\n };\n\n /**\n * Move the state of the animation to a specific point in the tween's\n * timeline. If the animation is not running, this will cause the `step`\n * handlers to be called.\n * @method seek\n * @param {millisecond} millisecond The millisecond of the animation to seek\n * to. This must not be less than `0`.\n * @chainable\n */\n Tweenable.prototype.seek = function(millisecond) {\n millisecond = Math.max(millisecond, 0);\n var currentTime = now();\n\n if ((this._timestamp + millisecond) === 0) {\n return this;\n }\n\n this._timestamp = currentTime - millisecond;\n\n if (!this.isPlaying()) {\n this._isTweening = true;\n this._isPaused = false;\n\n // If the animation is not running, call timeoutHandler to make sure that\n // any step handlers are run.\n timeoutHandler(this,\n this._timestamp,\n this._delay,\n this._duration,\n this._currentState,\n this._originalState,\n this._targetState,\n this._easing,\n this._step,\n this._scheduleFunction,\n currentTime);\n\n this.pause();\n }\n\n return this;\n };\n\n /**\n * Stops and cancels a tween.\n * @param {boolean=} gotoEnd If `false` or omitted, the tween just stops at\n * its current state, and the `finish` handler is not invoked. If `true`,\n * the tweened object's values are instantly set to the target values, and\n * `finish` is invoked.\n * @method stop\n * @chainable\n */\n Tweenable.prototype.stop = function(gotoEnd) {\n this._isTweening = false;\n this._isPaused = false;\n this._timeoutHandler = noop;\n\n (root.cancelAnimationFrame || root.webkitCancelAnimationFrame || root.oCancelAnimationFrame || root.msCancelAnimationFrame || root.mozCancelRequestAnimationFrame || root.clearTimeout)(this._scheduleId);\n\n if (gotoEnd) {\n applyFilter(this, 'beforeTween');\n tweenProps(\n 1,\n this._currentState,\n this._originalState,\n this._targetState,\n 1,\n 0,\n this._easing);\n applyFilter(this, 'afterTween');\n applyFilter(this, 'afterTweenEnd');\n this._finish.call(this, this._currentState, this._attachment);\n }\n\n return this;\n };\n\n /**\n * @method isPlaying\n * @return {boolean} Whether or not a tween is running.\n */\n Tweenable.prototype.isPlaying = function() {\n return this._isTweening && !this._isPaused;\n };\n\n /**\n * Set a custom schedule function.\n *\n * If a custom function is not set,\n * [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame)\n * is used if available, otherwise\n * [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)\n * is used.\n * @method setScheduleFunction\n * @param {Function(Function,number)} scheduleFunction The function to be\n * used to schedule the next frame to be rendered.\n */\n Tweenable.prototype.setScheduleFunction = function(scheduleFunction) {\n this._scheduleFunction = scheduleFunction;\n };\n\n /**\n * `delete` all \"own\" properties. Call this when the `Tweenable` instance\n * is no longer needed to free memory.\n * @method dispose\n */\n Tweenable.prototype.dispose = function() {\n var prop;\n for (prop in this) {\n if (this.hasOwnProperty(prop)) {\n delete this[prop];\n }\n }\n };\n\n /**\n * Filters are used for transforming the properties of a tween at various\n * points in a Tweenable's life cycle. See the README for more info on this.\n * @private\n */\n Tweenable.prototype.filter = {};\n\n /**\n * This object contains all of the tweens available to Shifty. It is\n * extensible - simply attach properties to the `Tweenable.prototype.formula`\n * Object following the same format as `linear`.\n *\n * `pos` should be a normalized `number` (between 0 and 1).\n * @property formula\n * @type {Object(function)}\n */\n Tweenable.prototype.formula = {\n linear: function(pos) {\n return pos;\n }\n };\n\n formula = Tweenable.prototype.formula;\n\n shallowCopy(Tweenable, {\n 'now': now,\n 'each': each,\n 'tweenProps': tweenProps,\n 'tweenProp': tweenProp,\n 'applyFilter': applyFilter,\n 'shallowCopy': shallowCopy,\n 'defaults': defaults,\n 'composeEasingObject': composeEasingObject\n });\n\n // `root` is provided in the intro/outro files.\n\n // A hook used for unit testing.\n if (typeof SHIFTY_DEBUG_NOW === 'function') {\n root.timeoutHandler = timeoutHandler;\n }\n\n // Bootstrap Tweenable appropriately for the environment.\n if (typeof exports === 'object') {\n // CommonJS\n module.exports = Tweenable;\n } else if (typeof define === 'function' && define.amd) {\n // AMD\n define(function() {\n return Tweenable;\n });\n } else if (typeof root.Tweenable === 'undefined') {\n // Browser: Make `Tweenable` globally accessible.\n root.Tweenable = Tweenable;\n }\n\n return Tweenable;\n\n }());\n\n /*!\n * All equations are adapted from Thomas Fuchs'\n * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js).\n *\n * Based on Easing Equations (c) 2003 [Robert\n * Penner](http://www.robertpenner.com/), all rights reserved. This work is\n * [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html).\n */\n\n /*!\n * TERMS OF USE - EASING EQUATIONS\n * Open source under the BSD License.\n * Easing Equations (c) 2003 Robert Penner, all rights reserved.\n */\n\n ;\n (function() {\n\n Tweenable.shallowCopy(Tweenable.prototype.formula, {\n easeInQuad: function(pos) {\n return Math.pow(pos, 2);\n },\n\n easeOutQuad: function(pos) {\n return -(Math.pow((pos - 1), 2) - 1);\n },\n\n easeInOutQuad: function(pos) {\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(pos, 2);\n }\n return -0.5 * ((pos -= 2) * pos - 2);\n },\n\n easeInCubic: function(pos) {\n return Math.pow(pos, 3);\n },\n\n easeOutCubic: function(pos) {\n return (Math.pow((pos - 1), 3) + 1);\n },\n\n easeInOutCubic: function(pos) {\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(pos, 3);\n }\n return 0.5 * (Math.pow((pos - 2), 3) + 2);\n },\n\n easeInQuart: function(pos) {\n return Math.pow(pos, 4);\n },\n\n easeOutQuart: function(pos) {\n return -(Math.pow((pos - 1), 4) - 1);\n },\n\n easeInOutQuart: function(pos) {\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(pos, 4);\n }\n return -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);\n },\n\n easeInQuint: function(pos) {\n return Math.pow(pos, 5);\n },\n\n easeOutQuint: function(pos) {\n return (Math.pow((pos - 1), 5) + 1);\n },\n\n easeInOutQuint: function(pos) {\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(pos, 5);\n }\n return 0.5 * (Math.pow((pos - 2), 5) + 2);\n },\n\n easeInSine: function(pos) {\n return -Math.cos(pos * (Math.PI / 2)) + 1;\n },\n\n easeOutSine: function(pos) {\n return Math.sin(pos * (Math.PI / 2));\n },\n\n easeInOutSine: function(pos) {\n return (-0.5 * (Math.cos(Math.PI * pos) - 1));\n },\n\n easeInExpo: function(pos) {\n return (pos === 0) ? 0 : Math.pow(2, 10 * (pos - 1));\n },\n\n easeOutExpo: function(pos) {\n return (pos === 1) ? 1 : -Math.pow(2, - 10 * pos) + 1;\n },\n\n easeInOutExpo: function(pos) {\n if (pos === 0) {\n return 0;\n }\n if (pos === 1) {\n return 1;\n }\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(2, 10 * (pos - 1));\n }\n return 0.5 * (-Math.pow(2, - 10 * --pos) + 2);\n },\n\n easeInCirc: function(pos) {\n return -(Math.sqrt(1 - (pos * pos)) - 1);\n },\n\n easeOutCirc: function(pos) {\n return Math.sqrt(1 - Math.pow((pos - 1), 2));\n },\n\n easeInOutCirc: function(pos) {\n if ((pos /= 0.5) < 1) {\n return -0.5 * (Math.sqrt(1 - pos * pos) - 1);\n }\n return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1);\n },\n\n easeOutBounce: function(pos) {\n if ((pos) < (1 / 2.75)) {\n return (7.5625 * pos * pos);\n } else if (pos < (2 / 2.75)) {\n return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);\n } else if (pos < (2.5 / 2.75)) {\n return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);\n } else {\n return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);\n }\n },\n\n easeInBack: function(pos) {\n var s = 1.70158;\n return (pos) * pos * ((s + 1) * pos - s);\n },\n\n easeOutBack: function(pos) {\n var s = 1.70158;\n return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1;\n },\n\n easeInOutBack: function(pos) {\n var s = 1.70158;\n if ((pos /= 0.5) < 1) {\n return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));\n }\n return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);\n },\n\n elastic: function(pos) {\n // jshint maxlen:90\n return -1 * Math.pow(4, - 8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1;\n },\n\n swingFromTo: function(pos) {\n var s = 1.70158;\n return ((pos /= 0.5) < 1) ? 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) : 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);\n },\n\n swingFrom: function(pos) {\n var s = 1.70158;\n return pos * pos * ((s + 1) * pos - s);\n },\n\n swingTo: function(pos) {\n var s = 1.70158;\n return (pos -= 1) * pos * ((s + 1) * pos + s) + 1;\n },\n\n bounce: function(pos) {\n if (pos < (1 / 2.75)) {\n return (7.5625 * pos * pos);\n } else if (pos < (2 / 2.75)) {\n return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);\n } else if (pos < (2.5 / 2.75)) {\n return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);\n } else {\n return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);\n }\n },\n\n bouncePast: function(pos) {\n if (pos < (1 / 2.75)) {\n return (7.5625 * pos * pos);\n } else if (pos < (2 / 2.75)) {\n return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);\n } else if (pos < (2.5 / 2.75)) {\n return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);\n } else {\n return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);\n }\n },\n\n easeFromTo: function(pos) {\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(pos, 4);\n }\n return -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);\n },\n\n easeFrom: function(pos) {\n return Math.pow(pos, 4);\n },\n\n easeTo: function(pos) {\n return Math.pow(pos, 0.25);\n }\n });\n\n }());\n\n // jshint maxlen:100\n /**\n * The Bezier magic in this file is adapted/copied almost wholesale from\n * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js),\n * which was adapted from Apple code (which probably came from\n * [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)).\n * Special thanks to Apple and Thomas Fuchs for much of this code.\n */\n\n /**\n * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice,\n * this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the documentation\n * and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder(s) nor the names of any\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */;\n (function() {\n // port of webkit cubic bezier handling by http://www.netzgesta.de/dev/\n function cubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {\n var ax = 0,\n bx = 0,\n cx = 0,\n ay = 0,\n by = 0,\n cy = 0;\n\n function sampleCurveX(t) {\n return ((ax * t + bx) * t + cx) * t;\n }\n\n function sampleCurveY(t) {\n return ((ay * t + by) * t + cy) * t;\n }\n\n function sampleCurveDerivativeX(t) {\n return (3.0 * ax * t + 2.0 * bx) * t + cx;\n }\n\n function solveEpsilon(duration) {\n return 1.0 / (200.0 * duration);\n }\n\n function solve(x, epsilon) {\n return sampleCurveY(solveCurveX(x, epsilon));\n }\n\n function fabs(n) {\n if (n >= 0) {\n return n;\n } else {\n return 0 - n;\n }\n }\n\n function solveCurveX(x, epsilon) {\n var t0, t1, t2, x2, d2, i;\n for (t2 = x, i = 0; i < 8; i++) {\n x2 = sampleCurveX(t2) - x;\n if (fabs(x2) < epsilon) {\n return t2;\n }\n d2 = sampleCurveDerivativeX(t2);\n if (fabs(d2) < 1e-6) {\n break;\n }\n t2 = t2 - x2 / d2;\n }\n t0 = 0.0;\n t1 = 1.0;\n t2 = x;\n if (t2 < t0) {\n return t0;\n }\n if (t2 > t1) {\n return t1;\n }\n while (t0 < t1) {\n x2 = sampleCurveX(t2);\n if (fabs(x2 - x) < epsilon) {\n return t2;\n }\n if (x > x2) {\n t0 = t2;\n } else {\n t1 = t2;\n }\n t2 = (t1 - t0) * 0.5 + t0;\n }\n return t2; // Failure.\n }\n cx = 3.0 * p1x;\n bx = 3.0 * (p2x - p1x) - cx;\n ax = 1.0 - cx - bx;\n cy = 3.0 * p1y;\n by = 3.0 * (p2y - p1y) - cy;\n ay = 1.0 - cy - by;\n return solve(t, solveEpsilon(duration));\n }\n /**\n * getCubicBezierTransition(x1, y1, x2, y2) -> Function\n *\n * Generates a transition easing function that is compatible\n * with WebKit's CSS transitions `-webkit-transition-timing-function`\n * CSS property.\n *\n * The W3C has more information about CSS3 transition timing functions:\n * http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag\n *\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @return {function}\n * @private\n */\n function getCubicBezierTransition(x1, y1, x2, y2) {\n return function(pos) {\n return cubicBezierAtTime(pos, x1, y1, x2, y2, 1);\n };\n }\n // End ported code\n\n /**\n * Create a Bezier easing function and attach it to `{{#crossLink\n * \"Tweenable/formula:property\"}}Tweenable#formula{{/crossLink}}`. This\n * function gives you total control over the easing curve. Matthew Lein's\n * [Ceaser](http://matthewlein.com/ceaser/) is a useful tool for visualizing\n * the curves you can make with this function.\n * @method setBezierFunction\n * @param {string} name The name of the easing curve. Overwrites the old\n * easing function on `{{#crossLink\n * \"Tweenable/formula:property\"}}Tweenable#formula{{/crossLink}}` if it\n * exists.\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @return {function} The easing function that was attached to\n * Tweenable.prototype.formula.\n */\n Tweenable.setBezierFunction = function(name, x1, y1, x2, y2) {\n var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2);\n cubicBezierTransition.displayName = name;\n cubicBezierTransition.x1 = x1;\n cubicBezierTransition.y1 = y1;\n cubicBezierTransition.x2 = x2;\n cubicBezierTransition.y2 = y2;\n\n return Tweenable.prototype.formula[name] = cubicBezierTransition;\n };\n\n\n /**\n * `delete` an easing function from `{{#crossLink\n * \"Tweenable/formula:property\"}}Tweenable#formula{{/crossLink}}`. Be\n * careful with this method, as it `delete`s whatever easing formula matches\n * `name` (which means you can delete standard Shifty easing functions).\n * @method unsetBezierFunction\n * @param {string} name The name of the easing function to delete.\n * @return {function}\n */\n Tweenable.unsetBezierFunction = function(name) {\n delete Tweenable.prototype.formula[name];\n };\n\n })();\n\n ;\n (function() {\n\n function getInterpolatedValues(\n from, current, targetState, position, easing, delay) {\n return Tweenable.tweenProps(\n position, current, from, targetState, 1, delay, easing);\n }\n\n // Fake a Tweenable and patch some internals. This approach allows us to\n // skip uneccessary processing and object recreation, cutting down on garbage\n // collection pauses.\n var mockTweenable = new Tweenable();\n mockTweenable._filterArgs = [];\n\n /**\n * Compute the midpoint of two Objects. This method effectively calculates a\n * specific frame of animation that `{{#crossLink\n * \"Tweenable/tween:method\"}}{{/crossLink}}` does many times over the course\n * of a full tween.\n *\n * var interpolatedValues = Tweenable.interpolate({\n * width: '100px',\n * opacity: 0,\n * color: '#fff'\n * }, {\n * width: '200px',\n * opacity: 1,\n * color: '#000'\n * }, 0.5);\n *\n * console.log(interpolatedValues);\n * // {opacity: 0.5, width: \"150px\", color: \"rgb(127,127,127)\"}\n *\n * @static\n * @method interpolate\n * @param {Object} from The starting values to tween from.\n * @param {Object} targetState The ending values to tween to.\n * @param {number} position The normalized position value (between `0.0` and\n * `1.0`) to interpolate the values between `from` and `to` for. `from`\n * represents `0` and `to` represents `1`.\n * @param {Object.|string|Function} easing The easing\n * curve(s) to calculate the midpoint against. You can reference any easing\n * function attached to `Tweenable.prototype.formula`, or provide the easing\n * function(s) directly. If omitted, this defaults to \"linear\".\n * @param {number=} opt_delay Optional delay to pad the beginning of the\n * interpolated tween with. This increases the range of `position` from (`0`\n * through `1`) to (`0` through `1 + opt_delay`). So, a delay of `0.5` would\n * increase all valid values of `position` to numbers between `0` and `1.5`.\n * @return {Object}\n */\n Tweenable.interpolate = function(\n from, targetState, position, easing, opt_delay) {\n\n var current = Tweenable.shallowCopy({}, from);\n var delay = opt_delay || 0;\n var easingObject = Tweenable.composeEasingObject(\n from, easing || 'linear');\n\n mockTweenable.set({});\n\n // Alias and reuse the _filterArgs array instead of recreating it.\n var filterArgs = mockTweenable._filterArgs;\n filterArgs.length = 0;\n filterArgs[0] = current;\n filterArgs[1] = from;\n filterArgs[2] = targetState;\n filterArgs[3] = easingObject;\n\n // Any defined value transformation must be applied\n Tweenable.applyFilter(mockTweenable, 'tweenCreated');\n Tweenable.applyFilter(mockTweenable, 'beforeTween');\n\n var interpolatedValues = getInterpolatedValues(\n from, current, targetState, position, easingObject, delay);\n\n // Transform values back into their original format\n Tweenable.applyFilter(mockTweenable, 'afterTween');\n\n return interpolatedValues;\n };\n\n }());\n\n /**\n * This module adds string interpolation support to Shifty.\n *\n * The Token extension allows Shifty to tween numbers inside of strings. Among\n * other things, this allows you to animate CSS properties. For example, you\n * can do this:\n *\n * var tweenable = new Tweenable();\n * tweenable.tween({\n * from: { transform: 'translateX(45px)' },\n * to: { transform: 'translateX(90xp)' }\n * });\n *\n * `translateX(45)` will be tweened to `translateX(90)`. To demonstrate:\n *\n * var tweenable = new Tweenable();\n * tweenable.tween({\n * from: { transform: 'translateX(45px)' },\n * to: { transform: 'translateX(90px)' },\n * step: function (state) {\n * console.log(state.transform);\n * }\n * });\n *\n * The above snippet will log something like this in the console:\n *\n * translateX(60.3px)\n * ...\n * translateX(76.05px)\n * ...\n * translateX(90px)\n *\n * Another use for this is animating colors:\n *\n * var tweenable = new Tweenable();\n * tweenable.tween({\n * from: { color: 'rgb(0,255,0)' },\n * to: { color: 'rgb(255,0,255)' },\n * step: function (state) {\n * console.log(state.color);\n * }\n * });\n *\n * The above snippet will log something like this:\n *\n * rgb(84,170,84)\n * ...\n * rgb(170,84,170)\n * ...\n * rgb(255,0,255)\n *\n * This extension also supports hexadecimal colors, in both long (`#ff00ff`)\n * and short (`#f0f`) forms. Be aware that hexadecimal input values will be\n * converted into the equivalent RGB output values. This is done to optimize\n * for performance.\n *\n * var tweenable = new Tweenable();\n * tweenable.tween({\n * from: { color: '#0f0' },\n * to: { color: '#f0f' },\n * step: function (state) {\n * console.log(state.color);\n * }\n * });\n *\n * This snippet will generate the same output as the one before it because\n * equivalent values were supplied (just in hexadecimal form rather than RGB):\n *\n * rgb(84,170,84)\n * ...\n * rgb(170,84,170)\n * ...\n * rgb(255,0,255)\n *\n * ## Easing support\n *\n * Easing works somewhat differently in the Token extension. This is because\n * some CSS properties have multiple values in them, and you might need to\n * tween each value along its own easing curve. A basic example:\n *\n * var tweenable = new Tweenable();\n * tweenable.tween({\n * from: { transform: 'translateX(0px) translateY(0px)' },\n * to: { transform: 'translateX(100px) translateY(100px)' },\n * easing: { transform: 'easeInQuad' },\n * step: function (state) {\n * console.log(state.transform);\n * }\n * });\n *\n * The above snippet will create values like this:\n *\n * translateX(11.56px) translateY(11.56px)\n * ...\n * translateX(46.24px) translateY(46.24px)\n * ...\n * translateX(100px) translateY(100px)\n *\n * In this case, the values for `translateX` and `translateY` are always the\n * same for each step of the tween, because they have the same start and end\n * points and both use the same easing curve. We can also tween `translateX`\n * and `translateY` along independent curves:\n *\n * var tweenable = new Tweenable();\n * tweenable.tween({\n * from: { transform: 'translateX(0px) translateY(0px)' },\n * to: { transform: 'translateX(100px) translateY(100px)' },\n * easing: { transform: 'easeInQuad bounce' },\n * step: function (state) {\n * console.log(state.transform);\n * }\n * });\n *\n * The above snippet will create values like this:\n *\n * translateX(10.89px) translateY(82.35px)\n * ...\n * translateX(44.89px) translateY(86.73px)\n * ...\n * translateX(100px) translateY(100px)\n *\n * `translateX` and `translateY` are not in sync anymore, because `easeInQuad`\n * was specified for `translateX` and `bounce` for `translateY`. Mixing and\n * matching easing curves can make for some interesting motion in your\n * animations.\n *\n * The order of the space-separated easing curves correspond the token values\n * they apply to. If there are more token values than easing curves listed,\n * the last easing curve listed is used.\n * @submodule Tweenable.token\n */\n\n // token function is defined above only so that dox-foundation sees it as\n // documentation and renders it. It is never used, and is optimized away at\n // build time.\n\n ;\n (function(Tweenable) {\n\n /**\n * @typedef {{\n * formatString: string\n * chunkNames: Array.\n * }}\n * @private\n */\n var formatManifest;\n\n // CONSTANTS\n\n var R_NUMBER_COMPONENT = /(\\d|\\-|\\.)/;\n var R_FORMAT_CHUNKS = /([^\\-0-9\\.]+)/g;\n var R_UNFORMATTED_VALUES = /[0-9.\\-]+/g;\n var R_RGB = new RegExp('rgb\\\\(' + R_UNFORMATTED_VALUES.source + (/,\\s*/.source) + R_UNFORMATTED_VALUES.source + (/,\\s*/.source) + R_UNFORMATTED_VALUES.source + '\\\\)', 'g');\n var R_RGB_PREFIX = /^.*\\(/;\n var R_HEX = /#([0-9]|[a-f]){3,6}/gi;\n var VALUE_PLACEHOLDER = 'VAL';\n\n // HELPERS\n\n /**\n * @param {Array.number} rawValues\n * @param {string} prefix\n *\n * @return {Array.}\n * @private\n */\n function getFormatChunksFrom(rawValues, prefix) {\n var accumulator = [];\n\n var rawValuesLength = rawValues.length;\n var i;\n\n for (i = 0; i < rawValuesLength; i++) {\n accumulator.push('_' + prefix + '_' + i);\n }\n\n return accumulator;\n }\n\n /**\n * @param {string} formattedString\n *\n * @return {string}\n * @private\n */\n function getFormatStringFrom(formattedString) {\n var chunks = formattedString.match(R_FORMAT_CHUNKS);\n\n if (!chunks) {\n // chunks will be null if there were no tokens to parse in\n // formattedString (for example, if formattedString is '2'). Coerce\n // chunks to be useful here.\n chunks = ['', ''];\n\n // If there is only one chunk, assume that the string is a number\n // followed by a token...\n // NOTE: This may be an unwise assumption.\n } else if (chunks.length === 1 ||\n // ...or if the string starts with a number component (\".\", \"-\", or a\n // digit)...\n formattedString[0].match(R_NUMBER_COMPONENT)) {\n // ...prepend an empty string here to make sure that the formatted number\n // is properly replaced by VALUE_PLACEHOLDER\n chunks.unshift('');\n }\n\n return chunks.join(VALUE_PLACEHOLDER);\n }\n\n /**\n * Convert all hex color values within a string to an rgb string.\n *\n * @param {Object} stateObject\n *\n * @return {Object} The modified obj\n * @private\n */\n function sanitizeObjectForHexProps(stateObject) {\n Tweenable.each(stateObject, function(prop) {\n var currentProp = stateObject[prop];\n\n if (typeof currentProp === 'string' && currentProp.match(R_HEX)) {\n stateObject[prop] = sanitizeHexChunksToRGB(currentProp);\n }\n });\n }\n\n /**\n * @param {string} str\n *\n * @return {string}\n * @private\n */\n function sanitizeHexChunksToRGB(str) {\n return filterStringChunks(R_HEX, str, convertHexToRGB);\n }\n\n /**\n * @param {string} hexString\n *\n * @return {string}\n * @private\n */\n function convertHexToRGB(hexString) {\n var rgbArr = hexToRGBArray(hexString);\n return 'rgb(' + rgbArr[0] + ',' + rgbArr[1] + ',' + rgbArr[2] + ')';\n }\n\n var hexToRGBArray_returnArray = [];\n /**\n * Convert a hexadecimal string to an array with three items, one each for\n * the red, blue, and green decimal values.\n *\n * @param {string} hex A hexadecimal string.\n *\n * @returns {Array.} The converted Array of RGB values if `hex` is a\n * valid string, or an Array of three 0's.\n * @private\n */\n function hexToRGBArray(hex) {\n\n hex = hex.replace(/#/, '');\n\n // If the string is a shorthand three digit hex notation, normalize it to\n // the standard six digit notation\n if (hex.length === 3) {\n hex = hex.split('');\n hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n }\n\n hexToRGBArray_returnArray[0] = hexToDec(hex.substr(0, 2));\n hexToRGBArray_returnArray[1] = hexToDec(hex.substr(2, 2));\n hexToRGBArray_returnArray[2] = hexToDec(hex.substr(4, 2));\n\n return hexToRGBArray_returnArray;\n }\n\n /**\n * Convert a base-16 number to base-10.\n *\n * @param {Number|String} hex The value to convert\n *\n * @returns {Number} The base-10 equivalent of `hex`.\n * @private\n */\n function hexToDec(hex) {\n return parseInt(hex, 16);\n }\n\n /**\n * Runs a filter operation on all chunks of a string that match a RegExp\n *\n * @param {RegExp} pattern\n * @param {string} unfilteredString\n * @param {function(string)} filter\n *\n * @return {string}\n * @private\n */\n function filterStringChunks(pattern, unfilteredString, filter) {\n var pattenMatches = unfilteredString.match(pattern);\n var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER);\n\n if (pattenMatches) {\n var pattenMatchesLength = pattenMatches.length;\n var currentChunk;\n\n for (var i = 0; i < pattenMatchesLength; i++) {\n currentChunk = pattenMatches.shift();\n filteredString = filteredString.replace(\n VALUE_PLACEHOLDER, filter(currentChunk));\n }\n }\n\n return filteredString;\n }\n\n /**\n * Check for floating point values within rgb strings and rounds them.\n *\n * @param {string} formattedString\n *\n * @return {string}\n * @private\n */\n function sanitizeRGBChunks(formattedString) {\n return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk);\n }\n\n /**\n * @param {string} rgbChunk\n *\n * @return {string}\n * @private\n */\n function sanitizeRGBChunk(rgbChunk) {\n var numbers = rgbChunk.match(R_UNFORMATTED_VALUES);\n var numbersLength = numbers.length;\n var sanitizedString = rgbChunk.match(R_RGB_PREFIX)[0];\n\n for (var i = 0; i < numbersLength; i++) {\n sanitizedString += parseInt(numbers[i], 10) + ',';\n }\n\n sanitizedString = sanitizedString.slice(0, - 1) + ')';\n\n return sanitizedString;\n }\n\n /**\n * @param {Object} stateObject\n *\n * @return {Object} An Object of formatManifests that correspond to\n * the string properties of stateObject\n * @private\n */\n function getFormatManifests(stateObject) {\n var manifestAccumulator = {};\n\n Tweenable.each(stateObject, function(prop) {\n var currentProp = stateObject[prop];\n\n if (typeof currentProp === 'string') {\n var rawValues = getValuesFrom(currentProp);\n\n manifestAccumulator[prop] = {\n 'formatString': getFormatStringFrom(currentProp),\n 'chunkNames': getFormatChunksFrom(rawValues, prop)\n };\n }\n });\n\n return manifestAccumulator;\n }\n\n /**\n * @param {Object} stateObject\n * @param {Object} formatManifests\n * @private\n */\n function expandFormattedProperties(stateObject, formatManifests) {\n Tweenable.each(formatManifests, function(prop) {\n var currentProp = stateObject[prop];\n var rawValues = getValuesFrom(currentProp);\n var rawValuesLength = rawValues.length;\n\n for (var i = 0; i < rawValuesLength; i++) {\n stateObject[formatManifests[prop].chunkNames[i]] = +rawValues[i];\n }\n\n delete stateObject[prop];\n });\n }\n\n /**\n * @param {Object} stateObject\n * @param {Object} formatManifests\n * @private\n */\n function collapseFormattedProperties(stateObject, formatManifests) {\n Tweenable.each(formatManifests, function(prop) {\n var currentProp = stateObject[prop];\n var formatChunks = extractPropertyChunks(\n stateObject, formatManifests[prop].chunkNames);\n var valuesList = getValuesList(\n formatChunks, formatManifests[prop].chunkNames);\n currentProp = getFormattedValues(\n formatManifests[prop].formatString, valuesList);\n stateObject[prop] = sanitizeRGBChunks(currentProp);\n });\n }\n\n /**\n * @param {Object} stateObject\n * @param {Array.} chunkNames\n *\n * @return {Object} The extracted value chunks.\n * @private\n */\n function extractPropertyChunks(stateObject, chunkNames) {\n var extractedValues = {};\n var currentChunkName, chunkNamesLength = chunkNames.length;\n\n for (var i = 0; i < chunkNamesLength; i++) {\n currentChunkName = chunkNames[i];\n extractedValues[currentChunkName] = stateObject[currentChunkName];\n delete stateObject[currentChunkName];\n }\n\n return extractedValues;\n }\n\n var getValuesList_accumulator = [];\n /**\n * @param {Object} stateObject\n * @param {Array.} chunkNames\n *\n * @return {Array.}\n * @private\n */\n function getValuesList(stateObject, chunkNames) {\n getValuesList_accumulator.length = 0;\n var chunkNamesLength = chunkNames.length;\n\n for (var i = 0; i < chunkNamesLength; i++) {\n getValuesList_accumulator.push(stateObject[chunkNames[i]]);\n }\n\n return getValuesList_accumulator;\n }\n\n /**\n * @param {string} formatString\n * @param {Array.} rawValues\n *\n * @return {string}\n * @private\n */\n function getFormattedValues(formatString, rawValues) {\n var formattedValueString = formatString;\n var rawValuesLength = rawValues.length;\n\n for (var i = 0; i < rawValuesLength; i++) {\n formattedValueString = formattedValueString.replace(\n VALUE_PLACEHOLDER, + rawValues[i].toFixed(4));\n }\n\n return formattedValueString;\n }\n\n /**\n * Note: It's the duty of the caller to convert the Array elements of the\n * return value into numbers. This is a performance optimization.\n *\n * @param {string} formattedString\n *\n * @return {Array.|null}\n * @private\n */\n function getValuesFrom(formattedString) {\n return formattedString.match(R_UNFORMATTED_VALUES);\n }\n\n /**\n * @param {Object} easingObject\n * @param {Object} tokenData\n * @private\n */\n function expandEasingObject(easingObject, tokenData) {\n Tweenable.each(tokenData, function(prop) {\n var currentProp = tokenData[prop];\n var chunkNames = currentProp.chunkNames;\n var chunkLength = chunkNames.length;\n\n var easing = easingObject[prop];\n var i;\n\n if (typeof easing === 'string') {\n var easingChunks = easing.split(' ');\n var lastEasingChunk = easingChunks[easingChunks.length - 1];\n\n for (i = 0; i < chunkLength; i++) {\n easingObject[chunkNames[i]] = easingChunks[i] || lastEasingChunk;\n }\n\n } else {\n for (i = 0; i < chunkLength; i++) {\n easingObject[chunkNames[i]] = easing;\n }\n }\n\n delete easingObject[prop];\n });\n }\n\n /**\n * @param {Object} easingObject\n * @param {Object} tokenData\n * @private\n */\n function collapseEasingObject(easingObject, tokenData) {\n Tweenable.each(tokenData, function(prop) {\n var currentProp = tokenData[prop];\n var chunkNames = currentProp.chunkNames;\n var chunkLength = chunkNames.length;\n\n var firstEasing = easingObject[chunkNames[0]];\n var typeofEasings = typeof firstEasing;\n\n if (typeofEasings === 'string') {\n var composedEasingString = '';\n\n for (var i = 0; i < chunkLength; i++) {\n composedEasingString += ' ' + easingObject[chunkNames[i]];\n delete easingObject[chunkNames[i]];\n }\n\n easingObject[prop] = composedEasingString.substr(1);\n } else {\n easingObject[prop] = firstEasing;\n }\n });\n }\n\n Tweenable.prototype.filter.token = {\n 'tweenCreated': function(currentState, fromState, toState, easingObject) {\n sanitizeObjectForHexProps(currentState);\n sanitizeObjectForHexProps(fromState);\n sanitizeObjectForHexProps(toState);\n this._tokenData = getFormatManifests(currentState);\n },\n\n 'beforeTween': function(currentState, fromState, toState, easingObject) {\n expandEasingObject(easingObject, this._tokenData);\n expandFormattedProperties(currentState, this._tokenData);\n expandFormattedProperties(fromState, this._tokenData);\n expandFormattedProperties(toState, this._tokenData);\n },\n\n 'afterTween': function(currentState, fromState, toState, easingObject) {\n collapseFormattedProperties(currentState, this._tokenData);\n collapseFormattedProperties(fromState, this._tokenData);\n collapseFormattedProperties(toState, this._tokenData);\n collapseEasingObject(easingObject, this._tokenData);\n }\n };\n\n }(Tweenable));\n\n }).call(null);\n\n }, {}],\n 2: [function(require, module, exports) {\n // Circle shaped progress bar\n\n var Shape = require('./shape');\n var utils = require('./utils');\n\n var Circle = function Circle(container, options) {\n // Use two arcs to form a circle\n // See this answer http://stackoverflow.com/a/10477334/1446092\n this._pathTemplate = 'M 50,50 m 0,-{radius}' + ' a {radius},{radius} 0 1 1 0,{2radius}' + ' a {radius},{radius} 0 1 1 0,-{2radius}';\n\n this.containerAspectRatio = 1;\n\n Shape.apply(this, arguments);\n };\n\n Circle.prototype = new Shape();\n Circle.prototype.constructor = Circle;\n\n Circle.prototype._pathString = function _pathString(opts) {\n var widthOfWider = opts.strokeWidth;\n if (opts.trailWidth && opts.trailWidth > opts.strokeWidth) {\n widthOfWider = opts.trailWidth;\n }\n\n var r = 50 - widthOfWider / 2;\n\n return utils.render(this._pathTemplate, {\n radius: r,\n '2radius': r * 2\n });\n };\n\n Circle.prototype._trailString = function _trailString(opts) {\n return this._pathString(opts);\n };\n\n module.exports = Circle;\n\n }, {\n \"./shape\": 7,\n \"./utils\": 8\n }],\n 3: [function(require, module, exports) {\n // Line shaped progress bar\n\n var Shape = require('./shape');\n var utils = require('./utils');\n\n var Line = function Line(container, options) {\n this._pathTemplate = 'M 0,{center} L 100,{center}';\n Shape.apply(this, arguments);\n };\n\n Line.prototype = new Shape();\n Line.prototype.constructor = Line;\n\n Line.prototype._initializeSvg = function _initializeSvg(svg, opts) {\n svg.setAttribute('viewBox', '0 0 100 ' + opts.strokeWidth);\n svg.setAttribute('preserveAspectRatio', 'none');\n };\n\n Line.prototype._pathString = function _pathString(opts) {\n return utils.render(this._pathTemplate, {\n center: opts.strokeWidth / 2\n });\n };\n\n Line.prototype._trailString = function _trailString(opts) {\n return this._pathString(opts);\n };\n\n module.exports = Line;\n\n }, {\n \"./shape\": 7,\n \"./utils\": 8\n }],\n 4: [function(require, module, exports) {\n module.exports = {\n // Higher level API, different shaped progress bars\n Line: require('./line'),\n Circle: require('./circle'),\n SemiCircle: require('./semicircle'),\n\n // Lower level API to use any SVG path\n Path: require('./path'),\n\n // Base-class for creating new custom shapes\n // to be in line with the API of built-in shapes\n // Undocumented.\n Shape: require('./shape'),\n\n // Internal utils, undocumented.\n utils: require('./utils')\n };\n\n }, {\n \"./circle\": 2,\n \"./line\": 3,\n \"./path\": 5,\n \"./semicircle\": 6,\n \"./shape\": 7,\n \"./utils\": 8\n }],\n 5: [function(require, module, exports) {\n // Lower level API to animate any kind of svg path\n\n var Tweenable = require('shifty');\n var utils = require('./utils');\n\n var EASING_ALIASES = {\n easeIn: 'easeInCubic',\n easeOut: 'easeOutCubic',\n easeInOut: 'easeInOutCubic'\n };\n\n var Path = function Path(path, opts) {\n // Throw a better error if not initialized with `new` keyword\n if (!(this instanceof Path)) {\n throw new Error('Constructor was called without new keyword');\n }\n\n // Default parameters for animation\n opts = utils.extend({\n duration: 800,\n easing: 'linear',\n from: {},\n to: {},\n step: function() {}\n }, opts);\n\n var element;\n if (utils.isString(path)) {\n element = document.querySelector(path);\n } else {\n element = path;\n }\n\n // Reveal .path as public attribute\n this.path = element;\n this._opts = opts;\n this._tweenable = null;\n\n // Set up the starting positions\n var length = this.path.getTotalLength();\n this.path.style.strokeDasharray = length + ' ' + length;\n this.set(0);\n };\n\n Path.prototype.value = function value() {\n var offset = this._getComputedDashOffset();\n var length = this.path.getTotalLength();\n\n var progress = 1 - offset / length;\n // Round number to prevent returning very small number like 1e-30, which\n // is practically 0\n return parseFloat(progress.toFixed(6), 10);\n };\n\n Path.prototype.set = function set(progress) {\n this.stop();\n\n this.path.style.strokeDashoffset = this._progressToOffset(progress);\n\n var step = this._opts.step;\n if (utils.isFunction(step)) {\n var easing = this._easing(this._opts.easing);\n var values = this._calculateTo(progress, easing);\n var reference = this._opts.shape || this;\n step(values, reference, this._opts.attachment);\n }\n };\n\n Path.prototype.stop = function stop() {\n this._stopTween();\n this.path.style.strokeDashoffset = this._getComputedDashOffset();\n };\n\n // Method introduced here:\n // http://jakearchibald.com/2013/animated-line-drawing-svg/\n Path.prototype.animate = function animate(progress, opts, cb) {\n opts = opts || {};\n\n if (utils.isFunction(opts)) {\n cb = opts;\n opts = {};\n }\n\n var passedOpts = utils.extend({}, opts);\n\n // Copy default opts to new object so defaults are not modified\n var defaultOpts = utils.extend({}, this._opts);\n opts = utils.extend(defaultOpts, opts);\n\n var shiftyEasing = this._easing(opts.easing);\n var values = this._resolveFromAndTo(progress, shiftyEasing, passedOpts);\n\n this.stop();\n\n // Trigger a layout so styles are calculated & the browser\n // picks up the starting position before animating\n this.path.getBoundingClientRect();\n\n var offset = this._getComputedDashOffset();\n var newOffset = this._progressToOffset(progress);\n\n var self = this;\n this._tweenable = new Tweenable();\n this._tweenable.tween({\n from: utils.extend({\n offset: offset\n }, values.from),\n to: utils.extend({\n offset: newOffset\n }, values.to),\n duration: opts.duration,\n easing: shiftyEasing,\n step: function(state) {\n self.path.style.strokeDashoffset = state.offset;\n var reference = opts.shape || self;\n opts.step(state, reference, opts.attachment);\n },\n finish: function(state) {\n if (utils.isFunction(cb)) {\n cb();\n }\n }\n });\n };\n\n Path.prototype._getComputedDashOffset = function _getComputedDashOffset() {\n var computedStyle = window.getComputedStyle(this.path, null);\n return parseFloat(computedStyle.getPropertyValue('stroke-dashoffset'), 10);\n };\n\n Path.prototype._progressToOffset = function _progressToOffset(progress) {\n var length = this.path.getTotalLength();\n return length - progress * length;\n };\n\n // Resolves from and to values for animation.\n Path.prototype._resolveFromAndTo = function _resolveFromAndTo(progress, easing, opts) {\n if (opts.from && opts.to) {\n return {\n from: opts.from,\n to: opts.to\n };\n }\n\n return {\n from: this._calculateFrom(easing),\n to: this._calculateTo(progress, easing)\n };\n };\n\n // Calculate `from` values from options passed at initialization\n Path.prototype._calculateFrom = function _calculateFrom(easing) {\n return Tweenable.interpolate(this._opts.from, this._opts.to, this.value(), easing);\n };\n\n // Calculate `to` values from options passed at initialization\n Path.prototype._calculateTo = function _calculateTo(progress, easing) {\n return Tweenable.interpolate(this._opts.from, this._opts.to, progress, easing);\n };\n\n Path.prototype._stopTween = function _stopTween() {\n if (this._tweenable !== null) {\n this._tweenable.stop();\n this._tweenable = null;\n }\n };\n\n Path.prototype._easing = function _easing(easing) {\n if (EASING_ALIASES.hasOwnProperty(easing)) {\n return EASING_ALIASES[easing];\n }\n\n return easing;\n };\n\n module.exports = Path;\n\n }, {\n \"./utils\": 8,\n \"shifty\": 1\n }],\n 6: [function(require, module, exports) {\n // Semi-SemiCircle shaped progress bar\n\n var Shape = require('./shape');\n var Circle = require('./circle');\n var utils = require('./utils');\n\n var SemiCircle = function SemiCircle(container, options) {\n // Use one arc to form a SemiCircle\n // See this answer http://stackoverflow.com/a/10477334/1446092\n this._pathTemplate = 'M 50,50 m -{radius},0' + ' a {radius},{radius} 0 1 1 {2radius},0';\n\n this.containerAspectRatio = 2;\n\n Shape.apply(this, arguments);\n };\n\n SemiCircle.prototype = new Shape();\n SemiCircle.prototype.constructor = SemiCircle;\n\n SemiCircle.prototype._initializeSvg = function _initializeSvg(svg, opts) {\n svg.setAttribute('viewBox', '0 0 100 50');\n };\n\n SemiCircle.prototype._initializeTextContainer = function _initializeTextContainer(\n opts,\n container,\n textContainer) {\n if (opts.text.style) {\n // Reset top style\n textContainer.style.top = 'auto';\n textContainer.style.bottom = '0';\n\n if (opts.text.alignToBottom) {\n utils.setStyle(textContainer, 'transform', 'translate(-50%, 0)');\n } else {\n utils.setStyle(textContainer, 'transform', 'translate(-50%, 50%)');\n }\n }\n };\n\n // Share functionality with Circle, just have different path\n SemiCircle.prototype._pathString = Circle.prototype._pathString;\n SemiCircle.prototype._trailString = Circle.prototype._trailString;\n\n module.exports = SemiCircle;\n\n }, {\n \"./circle\": 2,\n \"./shape\": 7,\n \"./utils\": 8\n }],\n 7: [function(require, module, exports) {\n // Base object for different progress bar shapes\n\n var Path = require('./path');\n var utils = require('./utils');\n\n var DESTROYED_ERROR = 'Object is destroyed';\n\n var Shape = function Shape(container, opts) {\n // Throw a better error if progress bars are not initialized with `new`\n // keyword\n if (!(this instanceof Shape)) {\n throw new Error('Constructor was called without new keyword');\n }\n\n // Prevent calling constructor without parameters so inheritance\n // works correctly. To understand, this is how Shape is inherited:\n //\n // Line.prototype = new Shape();\n //\n // We just want to set the prototype for Line.\n if (arguments.length === 0) {\n return;\n }\n\n // Default parameters for progress bar creation\n this._opts = utils.extend({\n color: '#555',\n strokeWidth: 1.0,\n trailColor: null,\n trailWidth: null,\n fill: null,\n text: {\n style: {\n color: null,\n position: 'absolute',\n left: '50%',\n top: '50%',\n padding: 0,\n margin: 0,\n transform: {\n prefix: true,\n value: 'translate(-50%, -50%)'\n }\n },\n autoStyleContainer: true,\n alignToBottom: true,\n value: null,\n className: 'progressbar-text'\n },\n svgStyle: {\n display: 'block',\n width: '100%'\n },\n warnings: false\n }, opts, true); // Use recursive extend\n\n // If user specifies e.g. svgStyle or text style, the whole object\n // should replace the defaults to make working with styles easier\n if (utils.isObject(opts) && opts.svgStyle !== undefined) {\n this._opts.svgStyle = opts.svgStyle;\n }\n if (utils.isObject(opts) && utils.isObject(opts.text) && opts.text.style !== undefined) {\n this._opts.text.style = opts.text.style;\n }\n\n var svgView = this._createSvgView(this._opts);\n\n var element;\n if (utils.isString(container)) {\n element = document.querySelector(container);\n } else {\n element = container;\n }\n\n if (!element) {\n throw new Error('Container does not exist: ' + container);\n }\n\n this._container = element;\n this._container.appendChild(svgView.svg);\n if (this._opts.warnings) {\n this._warnContainerAspectRatio(this._container);\n }\n\n if (this._opts.svgStyle) {\n utils.setStyles(svgView.svg, this._opts.svgStyle);\n }\n\n // Expose public attributes before Path initialization\n this.svg = svgView.svg;\n this.path = svgView.path;\n this.trail = svgView.trail;\n this.text = null;\n\n var newOpts = utils.extend({\n attachment: undefined,\n shape: this\n }, this._opts);\n this._progressPath = new Path(svgView.path, newOpts);\n\n if (utils.isObject(this._opts.text) && this._opts.text.value !== null) {\n this.setText(this._opts.text.value);\n }\n };\n\n Shape.prototype.animate = function animate(progress, opts, cb) {\n if (this._progressPath === null) {\n throw new Error(DESTROYED_ERROR);\n }\n\n this._progressPath.animate(progress, opts, cb);\n };\n\n Shape.prototype.stop = function stop() {\n if (this._progressPath === null) {\n throw new Error(DESTROYED_ERROR);\n }\n\n // Don't crash if stop is called inside step function\n if (this._progressPath === undefined) {\n return;\n }\n\n this._progressPath.stop();\n };\n\n Shape.prototype.destroy = function destroy() {\n if (this._progressPath === null) {\n throw new Error(DESTROYED_ERROR);\n }\n\n this.stop();\n this.svg.parentNode.removeChild(this.svg);\n this.svg = null;\n this.path = null;\n this.trail = null;\n this._progressPath = null;\n\n if (this.text !== null) {\n this.text.parentNode.removeChild(this.text);\n this.text = null;\n }\n };\n\n Shape.prototype.set = function set(progress) {\n if (this._progressPath === null) {\n throw new Error(DESTROYED_ERROR);\n }\n\n this._progressPath.set(progress);\n };\n\n Shape.prototype.value = function value() {\n if (this._progressPath === null) {\n throw new Error(DESTROYED_ERROR);\n }\n\n if (this._progressPath === undefined) {\n return 0;\n }\n\n return this._progressPath.value();\n };\n\n Shape.prototype.setText = function setText(newText) {\n if (this._progressPath === null) {\n throw new Error(DESTROYED_ERROR);\n }\n\n if (this.text === null) {\n // Create new text node\n this.text = this._createTextContainer(this._opts, this._container);\n this._container.appendChild(this.text);\n }\n\n // Remove previous text and add new\n if (utils.isObject(newText)) {\n utils.removeChildren(this.text);\n this.text.appendChild(newText);\n } else {\n this.text.innerHTML = newText;\n }\n };\n\n Shape.prototype._createSvgView = function _createSvgView(opts) {\n var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n this._initializeSvg(svg, opts);\n\n var trailPath = null;\n // Each option listed in the if condition are 'triggers' for creating\n // the trail path\n if (opts.trailColor || opts.trailWidth) {\n trailPath = this._createTrail(opts);\n svg.appendChild(trailPath);\n }\n\n var path = this._createPath(opts);\n svg.appendChild(path);\n\n return {\n svg: svg,\n path: path,\n trail: trailPath\n };\n };\n\n Shape.prototype._initializeSvg = function _initializeSvg(svg, opts) {\n svg.setAttribute('viewBox', '0 0 100 100');\n };\n\n Shape.prototype._createPath = function _createPath(opts) {\n var pathString = this._pathString(opts);\n return this._createPathElement(pathString, opts);\n };\n\n Shape.prototype._createTrail = function _createTrail(opts) {\n // Create path string with original passed options\n var pathString = this._trailString(opts);\n\n // Prevent modifying original\n var newOpts = utils.extend({}, opts);\n\n // Defaults for parameters which modify trail path\n if (!newOpts.trailColor) {\n newOpts.trailColor = '#eee';\n }\n if (!newOpts.trailWidth) {\n newOpts.trailWidth = newOpts.strokeWidth;\n }\n\n newOpts.color = newOpts.trailColor;\n newOpts.strokeWidth = newOpts.trailWidth;\n\n // When trail path is set, fill must be set for it instead of the\n // actual path to prevent trail stroke from clipping\n newOpts.fill = null;\n\n return this._createPathElement(pathString, newOpts);\n };\n\n Shape.prototype._createPathElement = function _createPathElement(pathString, opts) {\n var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('d', pathString);\n path.setAttribute('stroke', opts.color);\n path.setAttribute('stroke-width', opts.strokeWidth);\n\n if (opts.fill) {\n path.setAttribute('fill', opts.fill);\n } else {\n path.setAttribute('fill-opacity', '0');\n }\n\n return path;\n };\n\n Shape.prototype._createTextContainer = function _createTextContainer(opts, container) {\n var textContainer = document.createElement('div');\n textContainer.className = opts.text.className;\n\n var textStyle = opts.text.style;\n if (textStyle) {\n if (opts.text.autoStyleContainer) {\n container.style.position = 'relative';\n }\n\n utils.setStyles(textContainer, textStyle);\n // Default text color to progress bar's color\n if (!textStyle.color) {\n textContainer.style.color = opts.color;\n }\n }\n\n this._initializeTextContainer(opts, container, textContainer);\n return textContainer;\n };\n\n // Give custom shapes possibility to modify text element\n Shape.prototype._initializeTextContainer = function(opts, container, element) {\n // By default, no-op\n // Custom shapes should respect API options, such as text.style\n };\n\n Shape.prototype._pathString = function _pathString(opts) {\n throw new Error('Override this function for each progress bar');\n };\n\n Shape.prototype._trailString = function _trailString(opts) {\n throw new Error('Override this function for each progress bar');\n };\n\n Shape.prototype._warnContainerAspectRatio = function _warnContainerAspectRatio(container) {\n if (!this.containerAspectRatio) {\n return;\n }\n\n var computedStyle = window.getComputedStyle(container, null);\n var width = parseFloat(computedStyle.getPropertyValue('width'), 10);\n var height = parseFloat(computedStyle.getPropertyValue('height'), 10);\n if (!utils.floatEquals(this.containerAspectRatio, width / height)) {\n console.warn('Incorrect aspect ratio of container', '#' + container.id, 'detected:',\n computedStyle.getPropertyValue('width') + '(width)', '/',\n computedStyle.getPropertyValue('height') + '(height)', '=',\n width / height);\n\n console.warn('Aspect ratio of should be',\n this.containerAspectRatio);\n }\n };\n\n module.exports = Shape;\n\n }, {\n \"./path\": 5,\n \"./utils\": 8\n }],\n 8: [function(require, module, exports) {\n // Utility functions\n\n var PREFIXES = 'Webkit Moz O ms'.split(' ');\n var FLOAT_COMPARISON_EPSILON = 0.001;\n\n // Copy all attributes from source object to destination object.\n // destination object is mutated.\n function extend(destination, source, recursive) {\n destination = destination || {};\n source = source || {};\n recursive = recursive || false;\n\n for (var attrName in source) {\n if (source.hasOwnProperty(attrName)) {\n var destVal = destination[attrName];\n var sourceVal = source[attrName];\n if (recursive && isObject(destVal) && isObject(sourceVal)) {\n destination[attrName] = extend(destVal, sourceVal, recursive);\n } else {\n destination[attrName] = sourceVal;\n }\n }\n }\n\n return destination;\n }\n\n // Renders templates with given variables. Variables must be surrounded with\n // braces without any spaces, e.g. {variable}\n // All instances of variable placeholders will be replaced with given content\n // Example:\n // render('Hello, {message}!', {message: 'world'})\n function render(template, vars) {\n var rendered = template;\n\n for (var key in vars) {\n if (vars.hasOwnProperty(key)) {\n var val = vars[key];\n var regExpString = '\\\\{' + key + '\\\\}';\n var regExp = new RegExp(regExpString, 'g');\n\n rendered = rendered.replace(regExp, val);\n }\n }\n\n return rendered;\n }\n\n function setStyle(element, style, value) {\n var elStyle = element.style; // cache for performance\n\n for (var i = 0; i < PREFIXES.length; ++i) {\n var prefix = PREFIXES[i];\n elStyle[prefix + capitalize(style)] = value;\n }\n\n elStyle[style] = value;\n }\n\n function setStyles(element, styles) {\n forEachObject(styles, function(styleValue, styleName) {\n // Allow disabling some individual styles by setting them\n // to null or undefined\n if (styleValue === null || styleValue === undefined) {\n return;\n }\n\n // If style's value is {prefix: true, value: '50%'},\n // Set also browser prefixed styles\n if (isObject(styleValue) && styleValue.prefix === true) {\n setStyle(element, styleName, styleValue.value);\n } else {\n element.style[styleName] = styleValue;\n }\n });\n }\n\n function capitalize(text) {\n return text.charAt(0).toUpperCase() + text.slice(1);\n }\n\n function isString(obj) {\n return typeof obj === 'string' || obj instanceof String;\n }\n\n function isFunction(obj) {\n return typeof obj === 'function';\n }\n\n function isArray(obj) {\n return Object.prototype.toString.call(obj) === '[object Array]';\n }\n\n // Returns true if `obj` is object as in {a: 1, b: 2}, not if it's function or\n // array\n function isObject(obj) {\n if (isArray(obj)) {\n return false;\n }\n\n var type = typeof obj;\n return type === 'object' && !! obj;\n }\n\n function forEachObject(object, callback) {\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n var val = object[key];\n callback(val, key);\n }\n }\n }\n\n function floatEquals(a, b) {\n return Math.abs(a - b) < FLOAT_COMPARISON_EPSILON;\n }\n\n // https://coderwall.com/p/nygghw/don-t-use-innerhtml-to-empty-dom-elements\n function removeChildren(el) {\n while (el.firstChild) {\n el.removeChild(el.firstChild);\n }\n }\n\n module.exports = {\n extend: extend,\n render: render,\n setStyle: setStyle,\n setStyles: setStyles,\n capitalize: capitalize,\n isString: isString,\n isFunction: isFunction,\n isObject: isObject,\n forEachObject: forEachObject,\n floatEquals: floatEquals,\n removeChildren: removeChildren\n };\n\n }, {}]\n }, {}, [4])(4)\n}); \n/*!\n * Copyright 2011 Twitter, Inc.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n\nvar Hogan = {};\n\n(function (Hogan) {\n Hogan.Template = function (codeObj, text, compiler, options) {\n codeObj = codeObj || {};\n this.r = codeObj.code || this.r;\n this.c = compiler;\n this.options = options || {};\n this.text = text || '';\n this.partials = codeObj.partials || {};\n this.subs = codeObj.subs || {};\n this.buf = '';\n }\n\n Hogan.Template.prototype = {\n // render: replaced by generated code.\n r: function (context, partials, indent) { return ''; },\n\n // variable escaping\n v: hoganEscape,\n\n // triple stache\n t: coerceToString,\n\n render: function render(context, partials, indent) {\n return this.ri([context], partials || {}, indent);\n },\n\n // render internal -- a hook for overrides that catches partials too\n ri: function (context, partials, indent) {\n return this.r(context, partials, indent);\n },\n\n // ensurePartial\n ep: function(symbol, partials) {\n var partial = this.partials[symbol];\n\n // check to see that if we've instantiated this partial before\n var template = partials[partial.name];\n if (partial.instance && partial.base == template) {\n return partial.instance;\n }\n\n if (typeof template == 'string') {\n if (!this.c) {\n throw new Error(\"No compiler available.\");\n }\n template = this.c.compile(template, this.options);\n }\n\n if (!template) {\n return null;\n }\n\n // We use this to check whether the partials dictionary has changed\n this.partials[symbol].base = template;\n\n if (partial.subs) {\n // Make sure we consider parent template now\n if (!partials.stackText) partials.stackText = {};\n for (key in partial.subs) {\n if (!partials.stackText[key]) {\n partials.stackText[key] = (this.activeSub !== undefined && partials.stackText[this.activeSub]) ? partials.stackText[this.activeSub] : this.text;\n }\n }\n template = createSpecializedPartial(template, partial.subs, partial.partials,\n this.stackSubs, this.stackPartials, partials.stackText);\n }\n this.partials[symbol].instance = template;\n\n return template;\n },\n\n // tries to find a partial in the current scope and render it\n rp: function(symbol, context, partials, indent) {\n var partial = this.ep(symbol, partials);\n if (!partial) {\n return '';\n }\n\n return partial.ri(context, partials, indent);\n },\n\n // render a section\n rs: function(context, partials, section) {\n var tail = context[context.length - 1];\n\n if (!isArray(tail)) {\n section(context, partials, this);\n return;\n }\n\n for (var i = 0; i < tail.length; i++) {\n context.push(tail[i]);\n section(context, partials, this);\n context.pop();\n }\n },\n\n // maybe start a section\n s: function(val, ctx, partials, inverted, start, end, tags) {\n var pass;\n\n if (isArray(val) && val.length === 0) {\n return false;\n }\n\n if (typeof val == 'function') {\n val = this.ms(val, ctx, partials, inverted, start, end, tags);\n }\n\n pass = !!val;\n\n if (!inverted && pass && ctx) {\n ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);\n }\n\n return pass;\n },\n\n // find values with dotted names\n d: function(key, ctx, partials, returnFound) {\n var found,\n names = key.split('.'),\n val = this.f(names[0], ctx, partials, returnFound),\n doModelGet = this.options.modelGet,\n cx = null;\n\n if (key === '.' && isArray(ctx[ctx.length - 2])) {\n val = ctx[ctx.length - 1];\n } else {\n for (var i = 1; i < names.length; i++) {\n found = findInScope(names[i], val, doModelGet);\n if (found !== undefined) {\n cx = val;\n val = found;\n } else {\n val = '';\n }\n }\n }\n\n if (returnFound && !val) {\n return false;\n }\n\n if (!returnFound && typeof val == 'function') {\n ctx.push(cx);\n val = this.mv(val, ctx, partials);\n ctx.pop();\n }\n\n return val;\n },\n\n // find values with normal names\n f: function(key, ctx, partials, returnFound) {\n var val = false,\n v = null,\n found = false,\n doModelGet = this.options.modelGet;\n\n for (var i = ctx.length - 1; i >= 0; i--) {\n v = ctx[i];\n val = findInScope(key, v, doModelGet);\n if (val !== undefined) {\n found = true;\n break;\n }\n }\n\n if (!found) {\n return (returnFound) ? false : \"\";\n }\n\n if (!returnFound && typeof val == 'function') {\n val = this.mv(val, ctx, partials);\n }\n\n return val;\n },\n\n // higher order templates\n ls: function(func, cx, partials, text, tags) {\n var oldTags = this.options.delimiters;\n\n this.options.delimiters = tags;\n this.b(this.ct(coerceToString(func.call(cx, text)), cx, partials));\n this.options.delimiters = oldTags;\n\n return false;\n },\n\n // compile text\n ct: function(text, cx, partials) {\n if (this.options.disableLambda) {\n throw new Error('Lambda features disabled.');\n }\n return this.c.compile(text, this.options).render(cx, partials);\n },\n\n // template result buffering\n b: function(s) { this.buf += s; },\n\n fl: function() { var r = this.buf; this.buf = ''; return r; },\n\n // method replace section\n ms: function(func, ctx, partials, inverted, start, end, tags) {\n var textSource,\n cx = ctx[ctx.length - 1],\n result = func.call(cx);\n\n if (typeof result == 'function') {\n if (inverted) {\n return true;\n } else {\n textSource = (this.activeSub && this.subsText && this.subsText[this.activeSub]) ? this.subsText[this.activeSub] : this.text;\n return this.ls(result, cx, partials, textSource.substring(start, end), tags);\n }\n }\n\n return result;\n },\n\n // method replace variable\n mv: function(func, ctx, partials) {\n var cx = ctx[ctx.length - 1];\n var result = func.call(cx);\n\n if (typeof result == 'function') {\n return this.ct(coerceToString(result.call(cx)), cx, partials);\n }\n\n return result;\n },\n\n sub: function(name, context, partials, indent) {\n var f = this.subs[name];\n if (f) {\n this.activeSub = name;\n f(context, partials, this, indent);\n this.activeSub = false;\n }\n }\n\n };\n\n //Find a key in an object\n function findInScope(key, scope, doModelGet) {\n var val;\n\n if (scope && typeof scope == 'object') {\n\n if (scope[key] !== undefined) {\n val = scope[key];\n\n // try lookup with get for backbone or similar model data\n } else if (doModelGet && scope.get && typeof scope.get == 'function') {\n val = scope.get(key);\n }\n }\n\n return val;\n }\n\n function createSpecializedPartial(instance, subs, partials, stackSubs, stackPartials, stackText) {\n function PartialTemplate() {};\n PartialTemplate.prototype = instance;\n function Substitutions() {};\n Substitutions.prototype = instance.subs;\n var key;\n var partial = new PartialTemplate();\n partial.subs = new Substitutions();\n partial.subsText = {}; //hehe. substext.\n partial.buf = '';\n\n stackSubs = stackSubs || {};\n partial.stackSubs = stackSubs;\n partial.subsText = stackText;\n for (key in subs) {\n if (!stackSubs[key]) stackSubs[key] = subs[key];\n }\n for (key in stackSubs) {\n partial.subs[key] = stackSubs[key];\n }\n\n stackPartials = stackPartials || {};\n partial.stackPartials = stackPartials;\n for (key in partials) {\n if (!stackPartials[key]) stackPartials[key] = partials[key];\n }\n for (key in stackPartials) {\n partial.partials[key] = stackPartials[key];\n }\n\n return partial;\n }\n\n var rAmp = /&/g,\n rLt = //g,\n rApos = /\\'/g,\n rQuot = /\\\"/g,\n hChars = /[&<>\\\"\\']/;\n\n function coerceToString(val) {\n return String((val === null || val === undefined) ? '' : val);\n }\n\n function hoganEscape(str) {\n str = coerceToString(str);\n return hChars.test(str) ?\n str\n .replace(rAmp, '&')\n .replace(rLt, '<')\n .replace(rGt, '>')\n .replace(rApos, ''')\n .replace(rQuot, '"') :\n str;\n }\n\n var isArray = Array.isArray || function(a) {\n return Object.prototype.toString.call(a) === '[object Array]';\n };\n\n})(typeof exports !== 'undefined' ? exports : Hogan);\n\n\n\n(function (Hogan) {\n // Setup regex assignments\n // remove whitespace according to Mustache spec\n var rIsWhitespace = /\\S/,\n rQuot = /\\\"/g,\n rNewline = /\\n/g,\n rCr = /\\r/g,\n rSlash = /\\\\/g,\n rLineSep = /\\u2028/,\n rParagraphSep = /\\u2029/;\n\n Hogan.tags = {\n '#': 1, '^': 2, '<': 3, '$': 4,\n '/': 5, '!': 6, '>': 7, '=': 8, '_v': 9,\n '{': 10, '&': 11, '_t': 12\n };\n\n Hogan.scan = function scan(text, delimiters) {\n var len = text.length,\n IN_TEXT = 0,\n IN_TAG_TYPE = 1,\n IN_TAG = 2,\n state = IN_TEXT,\n tagType = null,\n tag = null,\n buf = '',\n tokens = [],\n seenTag = false,\n i = 0,\n lineStart = 0,\n otag = '{{',\n ctag = '}}';\n\n function addBuf() {\n if (buf.length > 0) {\n tokens.push({tag: '_t', text: new String(buf)});\n buf = '';\n }\n }\n\n function lineIsWhitespace() {\n var isAllWhitespace = true;\n for (var j = lineStart; j < tokens.length; j++) {\n isAllWhitespace =\n (Hogan.tags[tokens[j].tag] < Hogan.tags['_v']) ||\n (tokens[j].tag == '_t' && tokens[j].text.match(rIsWhitespace) === null);\n if (!isAllWhitespace) {\n return false;\n }\n }\n\n return isAllWhitespace;\n }\n\n function filterLine(haveSeenTag, noNewLine) {\n addBuf();\n\n if (haveSeenTag && lineIsWhitespace()) {\n for (var j = lineStart, next; j < tokens.length; j++) {\n if (tokens[j].text) {\n if ((next = tokens[j+1]) && next.tag == '>') {\n // set indent to token value\n next.indent = tokens[j].text.toString()\n }\n tokens.splice(j, 1);\n }\n }\n } else if (!noNewLine) {\n tokens.push({tag:'\\n'});\n }\n\n seenTag = false;\n lineStart = tokens.length;\n }\n\n function changeDelimiters(text, index) {\n var close = '=' + ctag,\n closeIndex = text.indexOf(close, index),\n delimiters = trim(\n text.substring(text.indexOf('=', index) + 1, closeIndex)\n ).split(' ');\n\n otag = delimiters[0];\n ctag = delimiters[delimiters.length - 1];\n\n return closeIndex + close.length - 1;\n }\n\n if (delimiters) {\n delimiters = delimiters.split(' ');\n otag = delimiters[0];\n ctag = delimiters[1];\n }\n\n for (i = 0; i < len; i++) {\n if (state == IN_TEXT) {\n if (tagChange(otag, text, i)) {\n --i;\n addBuf();\n state = IN_TAG_TYPE;\n } else {\n if (text.charAt(i) == '\\n') {\n filterLine(seenTag);\n } else {\n buf += text.charAt(i);\n }\n }\n } else if (state == IN_TAG_TYPE) {\n i += otag.length - 1;\n tag = Hogan.tags[text.charAt(i + 1)];\n tagType = tag ? text.charAt(i + 1) : '_v';\n if (tagType == '=') {\n i = changeDelimiters(text, i);\n state = IN_TEXT;\n } else {\n if (tag) {\n i++;\n }\n state = IN_TAG;\n }\n seenTag = i;\n } else {\n if (tagChange(ctag, text, i)) {\n tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,\n i: (tagType == '/') ? seenTag - otag.length : i + ctag.length});\n buf = '';\n i += ctag.length - 1;\n state = IN_TEXT;\n if (tagType == '{') {\n if (ctag == '}}') {\n i++;\n } else {\n cleanTripleStache(tokens[tokens.length - 1]);\n }\n }\n } else {\n buf += text.charAt(i);\n }\n }\n }\n\n filterLine(seenTag, true);\n\n return tokens;\n }\n\n function cleanTripleStache(token) {\n if (token.n.substr(token.n.length - 1) === '}') {\n token.n = token.n.substring(0, token.n.length - 1);\n }\n }\n\n function trim(s) {\n if (s.trim) {\n return s.trim();\n }\n\n return s.replace(/^\\s*|\\s*$/g, '');\n }\n\n function tagChange(tag, text, index) {\n if (text.charAt(index) != tag.charAt(0)) {\n return false;\n }\n\n for (var i = 1, l = tag.length; i < l; i++) {\n if (text.charAt(index + i) != tag.charAt(i)) {\n return false;\n }\n }\n\n return true;\n }\n\n // the tags allowed inside super templates\n var allowedInSuper = {'_t': true, '\\n': true, '$': true, '/': true};\n\n function buildTree(tokens, kind, stack, customTags) {\n var instructions = [],\n opener = null,\n tail = null,\n token = null;\n\n tail = stack[stack.length - 1];\n\n while (tokens.length > 0) {\n token = tokens.shift();\n\n if (tail && tail.tag == '<' && !(token.tag in allowedInSuper)) {\n throw new Error('Illegal content in < super tag.');\n }\n\n if (Hogan.tags[token.tag] <= Hogan.tags['$'] || isOpener(token, customTags)) {\n stack.push(token);\n token.nodes = buildTree(tokens, token.tag, stack, customTags);\n } else if (token.tag == '/') {\n if (stack.length === 0) {\n throw new Error('Closing tag without opener: /' + token.n);\n }\n opener = stack.pop();\n if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {\n throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);\n }\n opener.end = token.i;\n return instructions;\n } else if (token.tag == '\\n') {\n token.last = (tokens.length == 0) || (tokens[0].tag == '\\n');\n }\n\n instructions.push(token);\n }\n\n if (stack.length > 0) {\n throw new Error('missing closing tag: ' + stack.pop().n);\n }\n\n return instructions;\n }\n\n function isOpener(token, tags) {\n for (var i = 0, l = tags.length; i < l; i++) {\n if (tags[i].o == token.n) {\n token.tag = '#';\n return true;\n }\n }\n }\n\n function isCloser(close, open, tags) {\n for (var i = 0, l = tags.length; i < l; i++) {\n if (tags[i].c == close && tags[i].o == open) {\n return true;\n }\n }\n }\n\n function stringifySubstitutions(obj) {\n var items = [];\n for (var key in obj) {\n items.push('\"' + esc(key) + '\": function(c,p,t,i) {' + obj[key] + '}');\n }\n return \"{ \" + items.join(\",\") + \" }\";\n }\n\n function stringifyPartials(codeObj) {\n var partials = [];\n for (var key in codeObj.partials) {\n partials.push('\"' + esc(key) + '\":{name:\"' + esc(codeObj.partials[key].name) + '\", ' + stringifyPartials(codeObj.partials[key]) + \"}\");\n }\n return \"partials: {\" + partials.join(\",\") + \"}, subs: \" + stringifySubstitutions(codeObj.subs);\n }\n\n Hogan.stringify = function(codeObj, text, options) {\n return \"{code: function (c,p,i) { \" + Hogan.wrapMain(codeObj.code) + \" },\" + stringifyPartials(codeObj) + \"}\";\n }\n\n var serialNo = 0;\n Hogan.generate = function(tree, text, options) {\n serialNo = 0;\n var context = { code: '', subs: {}, partials: {} };\n Hogan.walk(tree, context);\n\n if (options.asString) {\n return this.stringify(context, text, options);\n }\n\n return this.makeTemplate(context, text, options);\n }\n\n Hogan.wrapMain = function(code) {\n return 'var t=this;t.b(i=i||\"\");' + code + 'return t.fl();';\n }\n\n Hogan.template = Hogan.Template;\n\n Hogan.makeTemplate = function(codeObj, text, options) {\n var template = this.makePartials(codeObj);\n template.code = new Function('c', 'p', 'i', this.wrapMain(codeObj.code));\n return new this.template(template, text, this, options);\n }\n\n Hogan.makePartials = function(codeObj) {\n var key, template = {subs: {}, partials: codeObj.partials, name: codeObj.name};\n for (key in template.partials) {\n template.partials[key] = this.makePartials(template.partials[key]);\n }\n for (key in codeObj.subs) {\n template.subs[key] = new Function('c', 'p', 't', 'i', codeObj.subs[key]);\n }\n return template;\n }\n\n function esc(s) {\n return s.replace(rSlash, '\\\\\\\\')\n .replace(rQuot, '\\\\\\\"')\n .replace(rNewline, '\\\\n')\n .replace(rCr, '\\\\r')\n .replace(rLineSep, '\\\\u2028')\n .replace(rParagraphSep, '\\\\u2029');\n }\n\n function chooseMethod(s) {\n return (~s.indexOf('.')) ? 'd' : 'f';\n }\n\n function createPartial(node, context) {\n var prefix = \"<\" + (context.prefix || \"\");\n var sym = prefix + node.n + serialNo++;\n context.partials[sym] = {name: node.n, partials: {}};\n context.code += 't.b(t.rp(\"' + esc(sym) + '\",c,p,\"' + (node.indent || '') + '\"));';\n return sym;\n }\n\n Hogan.codegen = {\n '#': function(node, context) {\n context.code += 'if(t.s(t.' + chooseMethod(node.n) + '(\"' + esc(node.n) + '\",c,p,1),' +\n 'c,p,0,' + node.i + ',' + node.end + ',\"' + node.otag + \" \" + node.ctag + '\")){' +\n 't.rs(c,p,' + 'function(c,p,t){';\n Hogan.walk(node.nodes, context);\n context.code += '});c.pop();}';\n },\n\n '^': function(node, context) {\n context.code += 'if(!t.s(t.' + chooseMethod(node.n) + '(\"' + esc(node.n) + '\",c,p,1),c,p,1,0,0,\"\")){';\n Hogan.walk(node.nodes, context);\n context.code += '};';\n },\n\n '>': createPartial,\n '<': function(node, context) {\n var ctx = {partials: {}, code: '', subs: {}, inPartial: true};\n Hogan.walk(node.nodes, ctx);\n var template = context.partials[createPartial(node, context)];\n template.subs = ctx.subs;\n template.partials = ctx.partials;\n },\n\n '$': function(node, context) {\n var ctx = {subs: {}, code: '', partials: context.partials, prefix: node.n};\n Hogan.walk(node.nodes, ctx);\n context.subs[node.n] = ctx.code;\n if (!context.inPartial) {\n context.code += 't.sub(\"' + esc(node.n) + '\",c,p,i);';\n }\n },\n\n '\\n': function(node, context) {\n context.code += write('\"\\\\n\"' + (node.last ? '' : ' + i'));\n },\n\n '_v': function(node, context) {\n context.code += 't.b(t.v(t.' + chooseMethod(node.n) + '(\"' + esc(node.n) + '\",c,p,0)));';\n },\n\n '_t': function(node, context) {\n context.code += write('\"' + esc(node.text) + '\"');\n },\n\n '{': tripleStache,\n\n '&': tripleStache\n }\n\n function tripleStache(node, context) {\n context.code += 't.b(t.t(t.' + chooseMethod(node.n) + '(\"' + esc(node.n) + '\",c,p,0)));';\n }\n\n function write(s) {\n return 't.b(' + s + ');';\n }\n\n Hogan.walk = function(nodelist, context) {\n var func;\n for (var i = 0, l = nodelist.length; i < l; i++) {\n func = Hogan.codegen[nodelist[i].tag];\n func && func(nodelist[i], context);\n }\n return context;\n }\n\n Hogan.parse = function(tokens, text, options) {\n options = options || {};\n return buildTree(tokens, '', [], options.sectionTags || []);\n }\n\n Hogan.cache = {};\n\n Hogan.cacheKey = function(text, options) {\n return [text, !!options.asString, !!options.disableLambda, options.delimiters, !!options.modelGet].join('||');\n }\n\n Hogan.compile = function(text, options) {\n options = options || {};\n var key = Hogan.cacheKey(text, options);\n var template = this.cache[key];\n\n if (template) {\n var partials = template.partials;\n for (var name in partials) {\n delete partials[name].instance;\n }\n return template;\n }\n\n template = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options);\n return this.cache[key] = template;\n }\n})(typeof exports !== 'undefined' ? exports : Hogan);\n\n\n(function (exports){\n \"use strict\";\n\n function Timer(callback, delay) {\n this.callback = callback;\n this.originalDelay = delay;\n this.delay = delay;\n this.timerId = null;\n }\n\n Timer.prototype.start = function(delay) {\n var self = this;\n\n if (!this.callback) {\n daumtools.error('Timer requires a function parameter');\n return;\n }\n\n if (!delay) {\n this.clear();\n } else {\n this.delay = delay;\n }\n\n this.startTime = new Date().getTime();\n this.timerId = setTimeout(function() {\n self.callback();\n self.timerId = null;\n }, this.delay || 0);\n this.paused = false;\n };\n\n Timer.prototype.pause = function() {\n if (!this.timerId || this.paused) {\n return;\n }\n clearTimeout(this.timerId);\n this.timerId = null;\n\n this.paused = true;\n this.delay = this.startTime + this.delay - new Date().getTime();\n };\n\n Timer.prototype.resume = function() {\n if (!this.paused) {\n return;\n }\n this.start(this.delay);\n };\n\n Timer.prototype.clear = function() {\n clearTimeout(this.timerId);\n this.timerId = null;\n this.delay = this.originalDelay;\n };\n\n exports.Timer = Timer;\n})(window.daumtools = (typeof window.daumtools === 'undefined') ? {} : window.daumtools);\n\n/* jshint browser: true\n */\n\n(function(exports) {\n 'use strict';\n\n function StopWatch() {\n this.watches = {};\n }\n\n function getMeasuringTime(name) {\n var time = 0;\n if (this.watches[name]) {\n if (this.watches[name].timestamp !== 0) {\n time = performance.now() - this.watches[name].timestamp;\n }\n time += this.watches[name].accumulationTime;\n }\n\n return parseInt(time.toFixed(0), 10);\n }\n\n StopWatch.prototype.start = function(name) {\n if (!this.watches[name]) {\n this.watches[name] = { timestamp: performance.now(), accumulationTime: 0, isPaused: false };\n }\n };\n\n StopWatch.prototype.has = function(name) {\n return getMeasuringTime.call(this, name);\n };\n\n StopWatch.prototype.pause = function(name) {\n if (this.watches[name] && !this.watches[name].isPaused) {\n var time = performance.now() - this.watches[name].timestamp;\n this.watches[name].accumulationTime += time;\n this.watches[name].timestamp = 0;\n this.watches[name].isPaused = true;\n }\n };\n\n StopWatch.prototype.resume = function(name) {\n if (this.watches[name] && this.watches[name].isPaused) {\n this.watches[name].timestamp = performance.now();\n this.watches[name].isPaused = false;\n }\n };\n\n StopWatch.prototype.stop = function(name) {\n var time = getMeasuringTime.call(this, name);\n if (this.watches[name]) {\n delete this.watches[name];\n }\n\n return time;\n };\n\n exports.StopWatch = new StopWatch();\n})((window.daumtools = typeof window.daumtools === 'undefined' ? {} : window.daumtools));\n\n(function(exports) {\n 'use strict';\n\n function Interval(callback, delay) {\n this.callback = callback;\n this.delay = delay;\n this.isRunning = false;\n }\n\n Interval.prototype.start = function() {\n this.IntervalId = setInterval(this.callback, this.delay);\n this.isRunning = true;\n };\n\n Interval.prototype.stop = function() {\n clearInterval(this.IntervalId);\n this.isRunning = false;\n this.IntervalId = null;\n };\n\n exports.Interval = Interval;\n})((window.daumtools = typeof window.daumtools === 'undefined' ? {} : window.daumtools));\n\n(function(){var d;window.AmCharts?d=window.AmCharts:(d={},window.AmCharts=d,d.themes={},d.maps={},d.inheriting={},d.charts=[],d.onReadyArray=[],d.useUTC=!1,d.updateRate=60,d.uid=0,d.lang={},d.translations={},d.mapTranslations={},d.windows={},d.initHandlers=[],d.amString=\"am\",d.pmString=\"pm\");d.Class=function(a){var b=function(){arguments[0]!==d.inheriting&&(this.events={},this.construct.apply(this,arguments))};a.inherits?(b.prototype=new a.inherits(d.inheriting),b.base=a.inherits.prototype,delete a.inherits):\n(b.prototype.createEvents=function(){for(var a=0;ad.IEversion&&0b)return a;g=-1;for(a=(k=a.split(/\\r\\n|\\n|\\r/)).length;++gb;k[g]+=d.trim(h.slice(0,f))+((h=h.slice(f)).length?c:\"\"))f=2==e||(f=h.slice(0,b+1).match(/\\S*(\\s)?$/))[1]?b:f.input.length-f[0].length||1==e&&b||f.input.length+(f=h.slice(b).match(/^\\S*/))[0].length;h=d.trim(h)}return k.join(c)};d.trim=function(a){return a.replace(/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\"\")};d.wrappedText=function(a,b,c,e,g,f,h,k){var l=d.text(a,b,c,e,g,f,h);if(l){var m=l.getBBox();if(m.width>k){var n=\"\\n\";d.isModern||(n=\"
\");k=Math.floor(k/(m.width/\nb.length));2c&&(a=c);return a};d.isDefined=function(a){return void 0===a?!1:!0};d.stripNumbers=function(a){return a.replace(/[0-9]+/g,\"\")};d.roundTo=function(a,b){if(0>b)return a;var c=Math.pow(10,b);return Math.round(a*c)/c};d.toFixed=function(a,b){var c=!1;0>a&&(c=!0,a=Math.abs(a));var e=String(Math.round(a*Math.pow(10,b)));if(0=h[b].contains){var l=a-Math.floor(a/h[b].contains)*h[b].contains;\"ss\"==b?(l=d.formatNumber(l,f),1==l.split(k)[0].length&&(l=\"0\"+l)):l=d.roundTo(l,f.precision);(\"mm\"==b||\"hh\"==b)&&10>l&&(l=\"0\"+l);c=l+\"\"+e[b]+\"\"+c;a=Math.floor(a/h[b].contains);b=h[b].nextInterval;return d.formatDuration(a,\nb,c,e,g,f)}\"ss\"==b&&(a=d.formatNumber(a,f),1==a.split(k)[0].length&&(a=\"0\"+a));\"mm\"==b&&(a=d.roundTo(a,f.precision));(\"mm\"==b||\"hh\"==b)&&10>a&&(a=\"0\"+a);c=a+\"\"+e[b]+\"\"+c;if(h[g].count>h[b].count)for(a=h[b].count;aa?\"-\":\"\";a=Math.abs(a);var k=String(a),l=!1;-1!=k.indexOf(\"e\")&&(l=!0);0<=c&&!l&&(k=d.toFixed(a,c));var m=\"\";if(l)m=k;else{var k=k.split(\".\"),l=String(k[0]),n;for(n=l.length;0<=n;n-=3)m=n!=l.length?0!==n?l.substring(n-3,n)+b+m:l.substring(n-3,n)+m:l.substring(n-3,n);void 0!==k[1]&&(m=m+f+k[1]);void 0!==c&&0=c.x-5&&a<=c.x+c.width+5&&b>=c.y-5&&b<=c.y+c.height+5?\n!0:!1};d.isPercents=function(a){if(-1!=String(a).indexOf(\"%\"))return!0};d.formatValue=function(a,b,c,e,g,f,h,k){if(b){void 0===g&&(g=\"\");var l;for(l=0;la&&(h=\"-\");a=Math.abs(a);if(1=b[k].number&&(l=a/b[k].number,m=Number(e.precision),1>m&&(m=1),c=d.roundTo(l,m),m=d.formatNumber(c,{precision:-1,decimalSeparator:e.decimalSeparator,\nthousandsSeparator:e.thousandsSeparator}),!g||l==c)){f=h+\"\"+m+\"\"+b[k].prefix;break}}else for(k=0;k\"==a&&(a=\"easeOutSine\");\"<\"==a&&(a=\"easeInSine\");\"elastic\"==a&&(a=\"easeOutElastic\");return a};d.getObjById=function(a,b){var c,e;for(e=0;e\"));return a};d.fixBrakes=function(a){if(d.isModern){var b=RegExp(\"
\",\"g\");a&&(a=a.replace(b,\"\\n\"))}else a=d.fixNewLines(a);return a};d.deleteObject=function(a,b){if(a){if(void 0===b||null===b)b=20;if(0!==b)if(\"[object Array]\"===Object.prototype.toString.call(a))for(var c=0;cb)return e/2*b*b+c;b--;return-e/2*(b*(b-2)-1)+c};d.easeInSine=function(a,b,c,e,d){return-e*\nMath.cos(b/d*(Math.PI/2))+e+c};d.easeOutSine=function(a,b,c,e,d){return e*Math.sin(b/d*(Math.PI/2))+c};d.easeOutElastic=function(a,b,c,e,d){a=1.70158;var f=0,h=e;if(0===b)return c;if(1==(b/=d))return c+e;f||(f=.3*d);hb?Math.abs(b)-1:Math.abs(b);var d;for(d=0;db?Number(\"0.\"+c+String(a)):Number(String(a)+c)};d.setCN=function(a,b,c,e){if(a.addClassNames&&b&&(b=b.node)&&c){var d=b.getAttribute(\"class\");a=a.classNamePrefix+\"-\";e&&(a=\"\");d?b.setAttribute(\"class\",d+\" \"+a+c):b.setAttribute(\"class\",a+c)}};d.removeCN=function(a,b,c){b&&(b=b.node)&&c&&(b=b.classList)&&b.remove(a.classNamePrefix+\"-\"+c)};d.parseDefs=function(a,b){for(var c in a){var e=typeof a[c];if(0a&&(a=3)):a=this.width/this.minHorizontalGap,this.gridCountR=Math.max(a,1)):this.gridCountR=this.gridCount;this.axisWidth=this.axisLine.axisWidth;this.addTitle()},\nsetOrientation:function(a){this.orientation=a?\"H\":\"V\"},addTitle:function(){var a=this.title;this.titleLabel=null;if(a){var b=this.chart,c=this.titleColor;void 0===c&&(c=b.color);var e=this.titleFontSize;isNaN(e)&&(e=b.fontSize+1);a=d.text(b.container,a,c,b.fontFamily,e,this.titleAlign,this.titleBold);d.setCN(b,a,this.bcn+\"title\");this.titleLabel=a}},positionTitle:function(){var a=this.titleLabel;if(a){var b,c,e=this.labelsSet,g={};0this.autoRotateCount&&!isNaN(this.autoRotateAngle)&&(this.labelRotationR=this.autoRotateAngle),a=k;a<=B;a++){p=q+y*(a+Math.floor((D-q)/y))-C;\"DD\"==A&&(p+=36E5);p=d.resetDateToMin(new Date(p),A,u,t).getTime();\"MM\"==A&&(g=(p-l)/y,1.5<=(p-l)/y&&(p=p-(g-1)*y+d.getPeriodDuration(\"DD\",3),p=d.resetDateToMin(new Date(p),A,1).getTime(),C+=y));g=(p-this.startTime)*\nthis.stepWidth;if(\"radar\"==b.type){if(g=this.axisWidth-g,0>g||g>this.axisWidth)continue}else this.rotate?\"date\"==this.type&&\"middle\"==this.gridPosition&&(I=-y*this.stepWidth/2):\"date\"==this.type&&(g=this.axisWidth-g);f=!1;this.nextPeriod[h]&&(f=this.checkPeriodChange(this.nextPeriod[h],1,p,l,h));l=!1;f&&this.markPeriodChange?(f=this.dateFormatsObject[this.nextPeriod[h]],this.twoLineMode&&(f=this.dateFormatsObject[h]+\"\\n\"+f,f=d.fixBrakes(f)),l=!0):f=this.dateFormatsObject[h];r||(l=!1);this.currentDateFormat=\nf;f=d.formatDate(new Date(p),f,b);if(a==k&&!c||a==B&&!e)f=\" \";this.labelFunction&&(f=this.labelFunction(f,new Date(p),this,A,u,m).toString());this.boldLabels&&(l=!0);m=new this.axisItemRenderer(this,g,f,!1,n,I,!1,l);this.pushAxisItem(m);m=l=p;if(!isNaN(w))for(g=1;gb||b>this.height)return;if(isNaN(b)){this.hideBalloon();return}b=this.adjustBalloonCoordinate(b,e);e=this.coordinateToValue(b)}else{if(0>a||a>this.width)return;\nif(isNaN(a)){this.hideBalloon();return}a=this.adjustBalloonCoordinate(a,e);e=this.coordinateToValue(a)}var f;if(d=this.chart.chartCursor)f=d.index;if(this.balloon&&void 0!==e&&this.balloon.enabled){if(this.balloonTextFunction){if(\"date\"==this.type||!0===this.parseDates)e=new Date(e);e=this.balloonTextFunction(e)}else this.balloonText?e=this.formatBalloonText(this.balloonText,f,c):isNaN(e)||(e=this.formatValue(e,c));if(a!=this.prevBX||b!=this.prevBY)this.balloon.setPosition(a,b),this.prevBX=a,this.prevBY=\nb,e&&this.balloon.showBalloon(e)}},adjustBalloonCoordinate:function(a){return a},createBalloon:function(){var a=this.chart,b=a.chartCursor;b&&(b=b.cursorPosition,\"mouse\"!=b&&(this.stickBalloonToCategory=!0),\"start\"==b&&(this.stickBalloonToStart=!0),\"ValueAxis\"==this.cname&&(this.stickBalloonToCategory=!1));this.balloon&&(this.balloon.destroy&&this.balloon.destroy(),d.extend(this.balloon,a.balloon,!0))},setBalloonBounds:function(){var a=this.balloon;if(a){var b=this.chart;a.cornerRadius=0;a.shadowAlpha=\n0;a.borderThickness=1;a.borderAlpha=1;a.adjustBorderColor=!1;a.showBullet=!1;this.balloon=a;a.chart=b;a.mainSet=b.plotBalloonsSet;a.pointerWidth=this.tickLength;if(this.parseDates||\"date\"==this.type)a.pointerWidth=0;a.className=this.id;b=\"V\";\"V\"==this.orientation&&(b=\"H\");this.stickBalloonToCategory||(a.animationDuration=0);var c,e,d,f,h=this.inside,k=this.width,l=this.height;switch(this.position){case \"bottom\":c=0;e=k;h?(d=0,f=l):(d=l,f=l+1E3);break;case \"top\":c=0;e=k;h?(d=0,f=l):(d=-1E3,f=0);break;\ncase \"left\":d=0;f=l;h?(c=0,e=k):(c=-1E3,e=0);break;case \"right\":d=0,f=l,h?(c=0,e=k):(c=k,e=k+1E3)}a.drop||(a.pointerOrientation=b);a.setBounds(c,d,e,f)}}})})();(function(){var d=window.AmCharts;d.ValueAxis=d.Class({inherits:d.AxisBase,construct:function(a){this.cname=\"ValueAxis\";this.createEvents(\"axisChanged\",\"logarithmicAxisFailed\",\"axisZoomed\",\"axisIntZoomed\");d.ValueAxis.base.construct.call(this,a);this.dataChanged=!0;this.stackType=\"none\";this.position=\"left\";this.unitPosition=\"right\";this.includeAllValues=this.recalculateToPercents=this.includeHidden=this.includeGuidesInMinMax=this.integersOnly=!1;this.durationUnits={DD:\"d. \",hh:\":\",mm:\":\",ss:\"\"};\nthis.scrollbar=!1;this.baseValue=0;this.radarCategoriesEnabled=!0;this.axisFrequency=1;this.gridType=\"polygons\";this.useScientificNotation=!1;this.axisTitleOffset=10;this.pointPosition=\"axis\";this.minMaxMultiplier=1;this.logGridLimit=2;this.totalTextOffset=this.treatZeroAs=0;this.minPeriod=\"ss\";this.relativeStart=0;this.relativeEnd=1;d.applyTheme(this,a,this.cname)},updateData:function(){0>=this.gridCountR&&(this.gridCountR=1);this.totals=[];this.data=this.chart.chartData;var a=this.chart;\"xy\"!=a.type&&\n(this.stackGraphs(\"smoothedLine\"),this.stackGraphs(\"line\"),this.stackGraphs(\"column\"),this.stackGraphs(\"step\"));this.recalculateToPercents&&this.recalculate();if(this.synchronizationMultiplier&&this.synchronizeWith)d.isString(this.synchronizeWith)&&(this.synchronizeWith=a.getValueAxisById(this.synchronizeWith)),this.synchronizeWith&&(this.synchronizeWithAxis(this.synchronizeWith),this.foundGraphs=!0);else if(this.foundGraphs=!1,this.getMinMax(),0===this.start&&this.end==this.data.length-1&&isNaN(this.minZoom)&&\nisNaN(this.maxZoom)||isNaN(this.fullMin)&&isNaN(this.fullMax))this.fullMin=this.min,this.fullMax=this.max,\"date\"!=this.type&&this.strictMinMax&&(isNaN(this.minimum)||(this.fullMin=this.minimum),isNaN(this.maximum)||(this.fullMax=this.maximum)),this.logarithmic&&(this.fullMin=this.logMin,0===this.fullMin&&(this.fullMin=this.treatZeroAs)),\"date\"==this.type&&(this.minimumDate||(this.fullMin=this.minRR),this.maximumDate||(this.fullMax=this.maxRR),this.strictMinMax&&(this.minimumDate&&(this.fullMin=this.minimumDate.getTime()),\nthis.maximumDate&&(this.fullMax=this.maximumDate.getTime())))},draw:function(){d.ValueAxis.base.draw.call(this);var a=this.chart,b=this.set;this.labelRotationR=this.labelRotation;d.setCN(a,this.set,\"value-axis value-axis-\"+this.id);d.setCN(a,this.labelsSet,\"value-axis value-axis-\"+this.id);d.setCN(a,this.axisLine.axisSet,\"value-axis value-axis-\"+this.id);var c=this.type;\"duration\"==c&&(this.duration=\"ss\");!0===this.dataChanged&&(this.updateData(),this.dataChanged=!1);\"date\"==c&&(this.logarithmic=\n!1,this.min=this.minRR,this.max=this.maxRR,this.reversed=!1,this.getDateMinMax());if(this.logarithmic){var e=this.treatZeroAs,g=this.getExtremes(0,this.data.length-1).min;!isNaN(this.minimum)&&this.minimum=g||0>=this.minimum){this.fire({type:\"logarithmicAxisFailed\",chart:a});return}}this.grid0=null;var f,h,k=a.dx,l=a.dy,e=!1,g=this.logarithmic;if(isNaN(this.min)||\nisNaN(this.max)||!this.foundGraphs||Infinity==this.min||-Infinity==this.max)e=!0;else{\"date\"==this.type&&this.min==this.max&&(this.max+=this.minDuration(),this.min-=this.minDuration());var m=this.labelFrequency,n=this.showFirstLabel,q=this.showLastLabel,p=1,t=0;this.minCalc=this.min;this.maxCalc=this.max;if(this.strictMinMax&&(isNaN(this.minimum)||(this.min=this.minimum),isNaN(this.maximum)||(this.max=this.maximum),this.min==this.max))return;isNaN(this.minZoom)||(this.minReal=this.min=this.minZoom);\nisNaN(this.maxZoom)||(this.max=this.maxZoom);if(this.logarithmic){h=this.fullMin;var r=this.fullMax;isNaN(this.minimum)||(h=this.minimum);isNaN(this.maximum)||(r=this.maximum);var r=Math.log(r)*Math.LOG10E-Math.log(h)*Math.LOG10E,w=Math.log(this.max)/Math.LN10-Math.log(h)*Math.LOG10E;this.relativeStart=d.roundTo((Math.log(this.minReal)/Math.LN10-Math.log(h)*Math.LOG10E)/r,5);this.relativeEnd=d.roundTo(w/r,5)}else this.relativeStart=d.roundTo(d.fitToBounds((this.min-this.fullMin)/(this.fullMax-this.fullMin),\n0,1),5),this.relativeEnd=d.roundTo(d.fitToBounds((this.max-this.fullMin)/(this.fullMax-this.fullMin),0,1),5);var r=Math.round((this.maxCalc-this.minCalc)/this.step)+1,z;!0===g?(z=Math.log(this.max)*Math.LOG10E-Math.log(this.minReal)*Math.LOG10E,this.stepWidth=this.axisWidth/z,z>this.logGridLimit&&(r=Math.ceil(Math.log(this.max)*Math.LOG10E)+1,t=Math.round(Math.log(this.minReal)*Math.LOG10E),r>this.gridCountR&&(p=Math.ceil(r/this.gridCountR)))):this.stepWidth=this.axisWidth/(this.max-this.min);var x=\n0;1>this.step&&-1this.maxDecCount&&(x=this.maxDecCount);w=this.precision;isNaN(w)||(x=w);isNaN(this.maxZoom)&&(this.max=d.roundTo(this.max,this.maxDecCount),this.min=d.roundTo(this.min,this.maxDecCount));h={};h.precision=x;h.decimalSeparator=a.nf.decimalSeparator;h.thousandsSeparator=a.nf.thousandsSeparator;this.numberFormatter=h;var u;this.exponential=!1;for(h=t;h=this.autoRotateCount&&!isNaN(this.autoRotateAngle)&&(this.labelRotationR=\nthis.autoRotateAngle),c=this.minCalc,g&&(r++,c=this.maxCalc-r*x),this.gridCountReal=r,h=this.startCount=t;hthis.logGridLimit){if(t=Math.pow(10,h),t>this.max)continue}else if(0>=t&&(t=c+x*h+x/2,0>=t))continue;u=this.formatValue(t,!1,h);Math.round(h/m)!=h/m&&(u=void 0);if(0===h&&!n||h==r-1&&!q)u=\" \";f=this.getCoordinate(t);var B;this.rotate&&this.autoWrap&&\n(B=this.stepWidth*x-10);u=new this.axisItemRenderer(this,f,u,void 0,B,void 0,void 0,this.boldLabels);this.pushAxisItem(u);if(t==this.baseValue&&\"radar\"!=a.type){var D,C,I=this.width,H=this.height;\"H\"==this.orientation?0<=f&&f<=I+1&&(D=[f,f,f+k],C=[H,0,l]):0<=f&&f<=H+1&&(D=[0,I,I+k],C=[f,f,f+l]);D&&(f=d.fitToBounds(2*this.gridAlpha,0,1),isNaN(this.zeroGridAlpha)||(f=this.zeroGridAlpha),f=d.line(a.container,D,C,this.gridColor,f,1,this.dashLength),f.translate(this.x,this.y),this.grid0=f,a.axesSet.push(f),\nf.toBack(),d.setCN(a,f,this.bcn+\"zero-grid-\"+this.id),d.setCN(a,f,this.bcn+\"zero-grid\"))}if(!isNaN(y)&&0this.logGridLimit&&(y=Math.pow(10,h+p)),f=9,y=(y-t)/f);I=this.gridAlpha;this.gridAlpha=this.minorGridAlpha;for(H=1;Hl&&0>k||(k=new this.guideFillRenderer(this,l,k,C),this.pushAxisItem(k,y),y=k.graphics(),C.graphics=y,this.addEventListeners(y,\nC));this.fillAlpha=D}u=this.baseValue;this.min>this.baseValue&&this.max>this.baseValue&&(u=this.min);this.minc&&(f.precision=Math.abs(c)),b&&1b&&c.shift();for(var e=Math.floor(Math.log(Math.abs(a))*Math.LOG10E),d=0;da){if(h=Math.pow(10,-h)*f,h==Math.round(h))return f}else if(f==Math.round(f))return f}return 1},stackGraphs:function(a){var b=this.stackType;\n\"stacked\"==b&&(b=\"regular\");\"line\"==b&&(b=\"none\");\"100% stacked\"==b&&(b=\"100%\");this.stackType=b;var c=[],e=[],g=[],f=[],h,k=this.chart.graphs,l,m,n,q,p,t=this.baseValue,r=!1;if(\"line\"==a||\"step\"==a||\"smoothedLine\"==a)r=!0;if(r&&(\"regular\"==b||\"100%\"==b))for(q=0;qh?(m.values.close=h,isNaN(e[p])?m.values.open=t:(m.values.close+=e[p],m.values.open=e[p]),e[p]=m.values.close):(m.values.close=h,isNaN(g[p])?m.values.open=t:(m.values.close+=g[p],m.values.open=g[p]),g[p]=m.values.close)))}}for(p=this.start;p<=this.end;p++)for(q=0;qc?(m.values.close=d.fitToBounds(c+e[p],-100,100),m.values.open=e[p],e[p]=m.values.close):(m.values.close=d.fitToBounds(c+g[p],-100,100),m.values.open=g[p],g[p]=m.values.close)))))},\nrecalculate:function(){var a=this.chart,b=a.graphs,c;for(c=0;c\nq&&h++}if(m=a.recalculateFromDate)m=d.getDate(m,a.dataDateFormat,\"fff\"),h=a.getClosestIndex(a.chartData,\"time\",m.getTime(),!0,0,a.chartData.length),k=a.chartData.length-1;for(m=h;m<=k&&(h=this.data[m].axes[this.id].graphs[e.id],f=h.values[g],e.recalculateValue&&(f=h.dataContext[e.valueField+e.recalculateValue]),isNaN(f));m++);this.recBaseValue=f;for(g=l;g<=k;g++){h=this.data[g].axes[this.id].graphs[e.id];h.percents={};var l=h.values,p;for(p in l)h.percents[p]=\"percents\"!=p?l[p]/f*100-100:l[p]}}}},\ngetMinMax:function(){var a=!1,b=this.chart,c=b.graphs,e;for(e=0;ethis.max&&(this.max=c.toValue),c.value>this.max&&(this.max=c.value);isNaN(this.minimum)||(this.min=this.minimum);isNaN(this.maximum)||(this.max=this.maximum);\"date\"==this.type&&this.getDateMinMax();this.min>this.max&&(a=this.max,this.max=this.min,\nthis.min=a);isNaN(this.minZoom)||(this.min=this.minZoom);isNaN(this.maxZoom)||(this.max=this.maxZoom);this.minCalc=this.min;this.maxCalc=this.max;this.minReal=this.min;this.maxReal=this.max;0===this.min&&0===this.max&&(this.max=9);this.min>this.max&&(this.min=this.max-1);a=this.min;b=this.max;c=this.max-this.min;e=0===c?Math.pow(10,Math.floor(Math.log(Math.abs(this.max))*Math.LOG10E))/10:Math.pow(10,Math.floor(Math.log(Math.abs(c))*Math.LOG10E))/10;isNaN(this.maximum)&&(this.max=Math.ceil(this.max/\ne)*e+e);isNaN(this.minimum)&&(this.min=Math.floor(this.min/e)*e-e);0>this.min&&0<=a&&(this.min=0);0=b&&(this.max=0);\"100%\"==this.stackType&&(this.min=0>this.min?-100:0,this.max=0>this.max?0:100);c=this.max-this.min;e=Math.pow(10,Math.floor(Math.log(Math.abs(c))*Math.LOG10E))/10;this.step=Math.ceil(c/this.gridCountR/e)*e;c=Math.pow(10,Math.floor(Math.log(Math.abs(this.step))*Math.LOG10E));c=d.fixStepE(c);e=Math.ceil(this.step/c);5=e&&2c?(this.maxDecCount=Math.abs(Math.log(Math.abs(c))*Math.LOG10E),this.maxDecCount=Math.round(this.maxDecCount),this.step=d.roundTo(this.step,this.maxDecCount+1)):this.maxDecCount=0;this.min=this.step*Math.floor(this.min/this.step);this.max=this.step*Math.ceil(this.max/this.step);0>this.min&&0<=a&&(this.min=0);0=b&&(this.max=0);1e&&(e=l);else for(var m in k)k.hasOwnProperty(m)&&\"percents\"!=m&&\"total\"!=m&&\"error\"!=m&&(l=k[m],le&&(e=l))}}}return{min:c,max:e}},zoomOut:function(a){this.maxZoom=this.minZoom=NaN;this.zoomToRelativeValues(0,1,a)},zoomToRelativeValues:function(a,b,c){if(this.reversed){var e=a;a=1-b;b=1-e}var d=this.fullMax,e=this.fullMin,f=e+(d-e)*a,h=e+(d-e)*b;0<=this.minimum&&0>f&&(f=0);this.logarithmic&&(isNaN(this.minimum)||(e=this.minimum),isNaN(this.maximum)||(d=this.maximum),d=Math.log(d)*\nMath.LOG10E-Math.log(e)*Math.LOG10E,f=Math.pow(10,d*a+Math.log(e)*Math.LOG10E),h=Math.pow(10,d*b+Math.log(e)*Math.LOG10E));return this.zoomToValues(f,h,c)},zoomToValues:function(a,b,c){if(bn?(v=X+ha*Math.sin(V)-B-3+2,G+=-ha*Math.cos(V)-Qa*Math.sin(V)-4):v-=B+r+3+3,v-=aa):(0n?(v=X+B+3-ha/2*Math.sin(V)+2,G+=ha/2*Math.cos(V)):v+=B+u+3+3,v+=aa)):(v+=na+r/2-ea,G+=ma,J?(0xa+2||0>r))ca.remove(),ca=null}else{0<=b&&b<=X+1&&(0X+1||vc&&\"object\"==typeof n&&(n=n.join(\",\").split(\",\").reverse());\"V\"==h?(h=d.rect(l,a.width,c,n,m),h.translate(g,b-k+f)):(h=d.rect(l,\nc,a.height,n,m),h.translate(b-k+g,f));d.setCN(a.chart,h,\"guide-fill\");e.id&&d.setCN(a.chart,h,\"guide-fill-\"+e.id);this.set=l.set([h])},graphics:function(){return this.set},getLabel:function(){}})})();(function(){var d=window.AmCharts;d.AmChart=d.Class({construct:function(a){this.svgIcons=this.tapToActivate=!0;this.theme=a;this.classNamePrefix=\"amcharts\";this.addClassNames=!1;this.version=\"3.21.15\";d.addChart(this);this.createEvents(\"buildStarted\",\"dataUpdated\",\"init\",\"rendered\",\"drawn\",\"failed\",\"resized\",\"animationFinished\");this.height=this.width=\"100%\";this.dataChanged=!0;this.chartCreated=!1;this.previousWidth=this.previousHeight=0;this.backgroundColor=\"#FFFFFF\";this.borderAlpha=this.backgroundAlpha=\n0;this.color=this.borderColor=\"#000000\";this.fontFamily=\"Verdana\";this.fontSize=11;this.usePrefixes=!1;this.autoResize=!0;this.autoDisplay=!1;this.addCodeCredits=this.accessible=!0;this.touchStartTime=this.touchClickDuration=0;this.precision=-1;this.percentPrecision=2;this.decimalSeparator=\".\";this.thousandsSeparator=\",\";this.labels=[];this.allLabels=[];this.titles=[];this.marginRight=this.marginLeft=this.autoMarginOffset=0;this.timeOuts=[];this.creditsPosition=\"top-left\";var b=document.createElement(\"div\"),\nc=b.style;c.overflow=\"hidden\";c.position=\"relative\";c.textAlign=\"left\";this.chartDiv=b;b=document.createElement(\"div\");c=b.style;c.overflow=\"hidden\";c.position=\"relative\";c.textAlign=\"left\";this.legendDiv=b;this.titleHeight=0;this.hideBalloonTime=150;this.handDrawScatter=2;this.cssScale=this.handDrawThickness=1;this.cssAngle=0;this.prefixesOfBigNumbers=[{number:1E3,prefix:\"k\"},{number:1E6,prefix:\"M\"},{number:1E9,prefix:\"G\"},{number:1E12,prefix:\"T\"},{number:1E15,prefix:\"P\"},{number:1E18,prefix:\"E\"},\n{number:1E21,prefix:\"Z\"},{number:1E24,prefix:\"Y\"}];this.prefixesOfSmallNumbers=[{number:1E-24,prefix:\"y\"},{number:1E-21,prefix:\"z\"},{number:1E-18,prefix:\"a\"},{number:1E-15,prefix:\"f\"},{number:1E-12,prefix:\"p\"},{number:1E-9,prefix:\"n\"},{number:1E-6,prefix:\"\\u03bc\"},{number:.001,prefix:\"m\"}];this.panEventsEnabled=!0;this.product=\"amcharts\";this.animations=[];this.balloon=new d.AmBalloon(this.theme);this.balloon.chart=this;this.processTimeout=0;this.processCount=1E3;this.animatable=[];this.langObj={};\nd.applyTheme(this,a,\"AmChart\")},drawChart:function(){0a||isNaN(a))a=0;this.chartDiv.style.height=a+\"px\"}}return a},updateWidth:function(){var a=this.divRealWidth,b=this.divRealHeight,c=this.legend;if(c){var e=this.legendDiv,d=e.offsetWidth;\nisNaN(c.width)||(d=c.width);c.ieW&&(d=c.ieW);var f=e.offsetHeight,e=e.style,h=this.chartDiv.style,k=c.position;if((\"right\"==k||\"left\"==k)&&void 0===c.divId){a-=d;if(0>a||isNaN(a))a=0;h.width=a+\"px\";this.balloon&&this.balloon.setBounds&&this.balloon.setBounds(2,2,a-2,this.realHeight);\"left\"==k?(h.left=d+\"px\",e.left=\"0px\"):(h.left=\"0px\",e.left=a+\"px\");b>f&&(e.top=(b-f)/2+\"px\")}}return a},getTitleHeight:function(){this.drawTitles(!0);return this.titleHeight},addTitle:function(a,b,c,e,d){isNaN(b)&&(b=\nthis.fontSize+2);a={text:a,size:b,color:c,alpha:e,bold:d,enabled:!0};this.titles.push(a);return a},handleWheel:function(a){var b=0;a||(a=window.event);a.wheelDelta?b=a.wheelDelta/120:a.detail&&(b=-a.detail/3);b&&this.handleWheelReal(b,a.shiftKey);a.preventDefault&&a.preventDefault()},handleWheelReal:function(){},handleDocTouchStart:function(){this.handleMouseMove();this.tmx=this.mouseX;this.tmy=this.mouseY;this.touchStartTime=(new Date).getTime()},handleDocTouchEnd:function(){-.5Math.abs(this.mouseX-this.tmx)&&4>Math.abs(this.mouseY-this.tmy)?(this.tapped=!0,this.panRequired&&this.panEventsEnabled&&this.chartDiv&&(this.chartDiv.style.msTouchAction=\"none\",this.chartDiv.style.touchAction=\"none\")):this.mouseIsOver||this.resetTouchStyle()):(this.tapped=!1,this.resetTouchStyle())},resetTouchStyle:function(){this.panEventsEnabled&&this.chartDiv&&(this.chartDiv.style.msTouchAction=\"auto\",this.chartDiv.style.touchAction=\n\"auto\")},checkTouchDuration:function(a){var b=this,c=(new Date).getTime();if(a)if(a.touches)b.isTouchEvent=!0;else if(!b.isTouchEvent)return!0;if(c-b.touchStartTime>b.touchClickDuration)return!0;setTimeout(function(){b.resetTouchDuration()},300)},resetTouchDuration:function(){this.isTouchEvent=!1},checkTouchMoved:function(){if(4a.valueAxis.minMaxMultiplier&&a.positiveClip(a.set));break;case \"radar\":a.createRadarGraph();break;case \"xy\":a.createXYGraph()}a.playedTO=setTimeout(function(){a.setAnimationPlayed.call(a)},500*a.chart.startDuration)}},\nsetAnimationPlayed:function(){this.animationPlayed=!0},createXYGraph:function(){var a=[],b=[],c=this.xAxis,e=this.yAxis;this.pmh=e.height;this.pmw=c.width;this.pmy=this.pmx=0;var d;for(d=this.start;d<=this.end;d++){var f=this.data[d].axes[c.id].graphs[this.id],h=f.values,k=h.x,l=h.y,h=c.getCoordinate(k,this.noRounding),m=e.getCoordinate(l,this.noRounding);if(!isNaN(k)&&!isNaN(l)&&(a.push(h),b.push(m),f.x=h,f.y=m,k=this.createBullet(f,h,m,d),l=this.labelText)){var l=this.createLabel(f,l),n=0;k&&(n=\nk.size);this.positionLabel(f,h,m,l,n)}}this.drawLineGraph(a,b);this.launchAnimation()},createRadarGraph:function(){var a=this.valueAxis.stackType,b=[],c=[],e=[],d=[],f,h,k,l,m;for(m=this.start;m<=this.end;m++){var n=this.data[m].axes[this.valueAxis.id].graphs[this.id],q,p;\"none\"==a||\"3d\"==a?q=n.values.value:(q=n.values.close,p=n.values.open);if(isNaN(q))this.connect||(this.drawLineGraph(b,c,e,d),b=[],c=[],e=[],d=[]);else{var t=this.valueAxis.getCoordinate(q,this.noRounding)-this.height,t=t*this.valueAxis.rMultiplier,\nr=-360/(this.end-this.start+1)*m;\"middle\"==this.valueAxis.pointPosition&&(r-=180/(this.end-this.start+1));q=t*Math.sin(r/180*Math.PI);t*=Math.cos(r/180*Math.PI);b.push(q);c.push(t);if(!isNaN(p)){var w=this.valueAxis.getCoordinate(p,this.noRounding)-this.height,w=w*this.valueAxis.rMultiplier,z=w*Math.sin(r/180*Math.PI),r=w*Math.cos(r/180*Math.PI);e.push(z);d.push(r);isNaN(k)&&(k=z);isNaN(l)&&(l=r)}r=this.createBullet(n,q,t,m);n.x=q;n.y=t;if(z=this.labelText)z=this.createLabel(n,z),w=0,r&&(w=r.size),\nthis.positionLabel(n,q,t,z,w);isNaN(f)&&(f=q);isNaN(h)&&(h=t)}}b.push(f);c.push(h);isNaN(k)||(e.push(k),d.push(l));this.drawLineGraph(b,c,e,d);this.launchAnimation()},positionLabel:function(a,b,c,e,d){if(e){var f=this.chart,h=this.valueAxis,k=\"middle\",l=!1,m=this.labelPosition,n=e.getBBox(),q=this.chart.rotate,p=a.isNegative,t=this.fontSize;void 0===t&&(t=this.chart.fontSize);c-=n.height/2-t/2-1;void 0!==a.labelIsNegative&&(p=a.labelIsNegative);switch(m){case \"right\":m=q?p?\"left\":\"right\":\"right\";\nbreak;case \"top\":m=q?\"top\":p?\"bottom\":\"top\";break;case \"bottom\":m=q?\"bottom\":p?\"top\":\"bottom\";break;case \"left\":m=q?p?\"right\":\"left\":\"left\"}var t=a.columnGraphics,r=0,w=0;t&&(r=t.x,w=t.y);var z=this.labelOffset;switch(m){case \"right\":k=\"start\";b+=d/2+z;break;case \"top\":c=h.reversed?c+(d/2+n.height/2+z):c-(d/2+n.height/2+z);break;case \"bottom\":c=h.reversed?c-(d/2+n.height/2+z):c+(d/2+n.height/2+z);break;case \"left\":k=\"end\";b-=d/2+z;break;case \"inside\":\"column\"==this.type&&(l=!0,q?p?(k=\"end\",b=r-3-\nz):(k=\"start\",b=r+3+z):c=p?w+7+z:w-10-z);break;case \"middle\":\"column\"==this.type&&(l=!0,q?b-=(b-r)/2+z-3:c-=(c-w)/2+z-3)}\"auto\"!=this.labelAnchor&&(k=this.labelAnchor);e.attr({\"text-anchor\":k});this.labelRotation&&e.rotate(this.labelRotation);e.translate(b,c);!this.showAllValueLabels&&t&&l&&(n=e.getBBox(),n.height>a.columnHeight||n.width>a.columnWidth)&&(e.remove(),e=null);if(e&&\"radar\"!=f.type)if(q){if(0>c||c>this.height)e.remove(),e=null;!this.showAllValueLabels&&e&&(0>b||b>this.width)&&(e.remove(),\ne=null)}else{if(0>b||b>this.width)e.remove(),e=null;!this.showAllValueLabels&&e&&(0>c||c>this.height)&&(e.remove(),e=null)}e&&this.allBullets.push(e);return e}},getGradRotation:function(){var a=270;\"horizontal\"==this.gradientOrientation&&(a=0);return this.gradientRotation=a},createSerialGraph:function(){this.dashLengthSwitched=this.fillColorsSwitched=this.lineColorSwitched=void 0;var a=this.chart,b=this.id,c=this.index,e=this.data,g=this.chart.container,f=this.valueAxis,h=this.type,k=this.columnWidthReal,\nl=this.showBulletsAt;isNaN(this.columnWidth)||(k=this.columnWidth);isNaN(k)&&(k=.8);var m=this.useNegativeColorIfDown,n=this.width,q=this.height,p=this.y,t=this.rotate,r=this.columnCount,w=d.toCoordinate(this.cornerRadiusTop,k/2),z=this.connect,x=[],u=[],A,y,B,D,C=this.chart.graphs.length,I,H=this.dx/this.tcc,Q=this.dy/this.tcc,M=f.stackType,P=this.start,ia=this.end,J=this.scrollbar,aa=\"graph-column-\";J&&(aa=\"scrollbar-graph-column-\");var ma=this.categoryAxis,na=this.baseCoord,Pa=this.negativeBase,\nZ=this.columnIndex,da=this.lineThickness,X=this.lineAlpha,xa=this.lineColorR,ea=this.dashLength,fa=this.set,Ba,ga=this.getGradRotation(),V=this.chart.columnSpacing,Y=ma.cellWidth,Da=(Y*k-r)/r;V>Da&&(V=Da);var G,v,oa,ha=q,Qa=n,ca=0,tb=0,ub=0,vb=0,lb=0,mb=0,wb=this.fillColorsR,Ra=this.negativeFillColors,Ja=this.negativeLineColor,bb=this.fillAlphas,cb=this.negativeFillAlphas;\"object\"==typeof bb&&(bb=bb[0]);\"object\"==typeof cb&&(cb=cb[0]);var xb=this.noRounding;\"step\"==h&&(xb=!1);var nb=f.getCoordinate(f.min);\nf.logarithmic&&(nb=f.getCoordinate(f.minReal));this.minCoord=nb;this.resetBullet&&(this.bullet=\"none\");if(!(J||\"line\"!=h&&\"smoothedLine\"!=h&&\"step\"!=h||(1==e.length&&\"step\"!=h&&\"none\"==this.bullet&&(this.bullet=\"round\",this.resetBullet=!0),!Ra&&void 0==Ja||m))){var Ua=Pa;Ua>f.max&&(Ua=f.max);Uak&&(k=1);var Nb=this.fixedColumnWidth;isNaN(Nb)||(k=Nb);var L;if(\"line\"==h||\"step\"==h||\"smoothedLine\"==h){if(0W?!0:!1);if(!J)switch(this.showBalloonAt){case \"close\":v.y=F;break;case \"open\":v.y=\nN;break;case \"high\":v.y=ta;break;case \"low\":v.y=ra}var ja=G.x[ma.id],Xa=this.periodSpan-1;\"step\"!=h||isNaN(G.cellWidth)||(Y=G.cellWidth);var wa=Math.floor(Y/2)+Math.floor(Xa*Y/2),Ga=wa,qb=0;\"left\"==this.stepDirection&&(qb=(2*Y+Xa*Y)/2,ja-=qb);\"center\"==this.stepDirection&&(qb=Y/2,ja-=qb);\"start\"==this.pointPosition&&(ja-=Y/2+Math.floor(Xa*Y/2),wa=0,Ga=Math.floor(Y)+Math.floor(Xa*Y));\"end\"==this.pointPosition&&(ja+=Y/2+Math.floor(Xa*Y/2),wa=Math.floor(Y)+Math.floor(Xa*Y),Ga=0);if(Ob){var Cb=this.columnWidth;\nisNaN(Cb)||(wa*=Cb,Ga*=Cb)}J||(v.x=ja);-1E5>ja&&(ja=-1E5);ja>n+1E5&&(ja=n+1E5);t?(E=F,O=N,N=F=ja,isNaN(ua)&&!this.fillToGraph&&(O=na),qa=ra,sa=ta):(O=E=ja,isNaN(ua)&&!this.fillToGraph&&(N=na));if(!Bb&&WTa?(Sa&&(Va=!0),Sa=!1):(Sa||(Va=!0),Sa=!0):v.isNegative=W=ob||Math.abs(F-eb)>=ob)x.push(E),u.push(F),db=E,eb=F;ya=E;Ea=F;ka=E;la=F;!Ma||isNaN(N)||isNaN(O)||(T.push(O),U.push(N));if(Va||void 0!=v.lineColor&&v.lineColor!=this.lineColorSwitched||void 0!=v.fillColors&&v.fillColors!=this.fillColorsSwitched||!isNaN(v.dashLength))this.drawLineGraph(x,u,T,U),x=[E],u=[F],T=[],U=[],!Ma||isNaN(N)||isNaN(O)||(T.push(O),U.push(N)),m?(Sa?(this.lineColorSwitched=\nxa,this.fillColorsSwitched=wb):(this.lineColorSwitched=Ja,this.fillColorsSwitched=Ra),void 0===this.bulletColor&&(this.bulletColorSwitched=xa)):(this.lineColorSwitched=v.lineColor,this.fillColorsSwitched=v.fillColors,void 0===this.bulletColor&&(this.bulletColorSwitched=this.lineColorSwitched)),this.dashLengthSwitched=v.dashLength;v.gap&&(this.drawLineGraph(x,u,T,U),x=[],u=[],T=[],U=[],eb=db=-1E3)}break;case \"smoothedLine\":if(isNaN(W))z||(this.drawSmoothedGraph(x,u,T,U),x=[],u=[],T=[],U=[]);else{if(Math.abs(E-\ndb)>=ob||Math.abs(F-eb)>=ob)x.push(E),u.push(F),db=E,eb=F;ya=E;Ea=F;ka=E;la=F;!Ma||isNaN(N)||isNaN(O)||(T.push(O),U.push(N));if(Va||void 0!=v.lineColor&&v.lineColor!=this.lineColorSwitched||void 0!=v.fillColors&&v.fillColors!=this.fillColorsSwitched||!isNaN(v.dashLength))this.drawSmoothedGraph(x,u,T,U),x=[E],u=[F],T=[],U=[],!Ma||isNaN(N)||isNaN(O)||(T.push(O),U.push(N)),this.lineColorSwitched=v.lineColor,this.fillColorsSwitched=v.fillColors,this.dashLengthSwitched=v.dashLength;v.gap&&(this.drawSmoothedGraph(x,\nu,T,U),x=[],u=[],T=[],U=[])}break;case \"step\":if(!isNaN(W)){t?(isNaN(A)||(x.push(A),u.push(F-wa)),u.push(F-wa),x.push(E),u.push(F+Ga),x.push(E),!Ma||isNaN(N)||isNaN(O)||(isNaN(B)||(T.push(B),U.push(N-wa)),T.push(O),U.push(N-wa),T.push(O),U.push(N+Ga))):(isNaN(y)||(u.push(y),x.push(E-wa)),x.push(E-wa),u.push(F),x.push(E+Ga),u.push(F),!Ma||isNaN(N)||isNaN(O)||(isNaN(D)||(T.push(O-wa),U.push(D)),T.push(O-wa),U.push(N),T.push(O+Ga),U.push(N)));A=E;y=F;B=O;D=N;ya=E;Ea=F;ka=E;la=F;if(Va||void 0!=v.lineColor||\nvoid 0!=v.fillColors||!isNaN(v.dashLength)){var Db=x[x.length-2],dc=u[u.length-2];x.pop();u.pop();T.pop();U.pop();this.drawLineGraph(x,u,T,U);x=[Db];u=[dc];T=[];U=[];Ma&&(T=[Db,Db+wa+Ga],U=[D,D]);t?(u.push(F+Ga),x.push(E)):(x.push(E+Ga),u.push(F));this.lineColorSwitched=v.lineColor;this.fillColorsSwitched=v.fillColors;this.dashLengthSwitched=v.dashLength;m&&(Sa?(this.lineColorSwitched=xa,this.fillColorsSwitched=wb):(this.lineColorSwitched=Ja,this.fillColorsSwitched=Ra))}if(Ob||v.gap)A=y=NaN,v.gap&&\n2>=x.length||this.drawLineGraph(x,u,T,U),x=[],u=[],T=[],U=[]}else if(!z){if(1>=this.periodSpan||1wa+Ga)A=y=NaN;this.drawLineGraph(x,u,T,U);x=[];u=[];T=[];U=[]}break;case \"column\":Ca=Ha;void 0!=v.lineColor&&(Ca=v.lineColor);if(!isNaN(W)){m||(v.isNegative=WRb&&rb>Rb)){var Aa;if(t){\"3d\"==M?(R=F-(r/2-this.depthCount+1)*(k+V)+V/2+Q*Z,S=O+H*Z,Aa=Z):(R=Math.floor(F-\n(r/2-Z)*(k+V)+V/2),S=O,Aa=0);K=k;ya=E;Ea=R+k/2;ka=E;la=R+k/2;R+K>q+Aa*Q&&(K=q-R+Aa*Q);Rba?!0:!1;0===ba&&1/W===1/-0&&(v.labelIsNegative=!0);isNaN(G.percentWidthValue)||(K=this.height*G.percentWidthValue/100,R=ja-K/2,Ea=R+K/2);K=d.roundTo(K,2);ba=d.roundTo(ba,2);Rn+Aa*H&&(K=n-S+Aa*H);Sq&&(K=q-R);0>R&&(K+=R,R=0);if(Rua?(Eb=[E,sa],Fb=[O,qa]):(Eb=[O,sa],Fb=[E,qa]);!isNaN(sa)&&!isNaN(qa)&&\nFn&&(K=n-S);0>S&&(K+=S,S=0);ba=F-N;if(S=ua&&(Wa=0);var va=new d.Cuboid(g,K,ba,H,\nQ,Na,Wa,da,Ca,X,ga,w,t,ea,gb,pb,aa),Gb,Hb;W>ua?(Gb=[F,ta],Hb=[N,ra]):(Gb=[N,ta],Hb=[F,ra]);!isNaN(ta)&&!isNaN(ra)&&EW?E-ac/2-2-kb-sb:E+ac/2+3+kb+sb):(ib=ya,jb=0>W?F+bc/2+kb+sb:F-bc/2-3-kb-sb);Oa.translate(ib,jb);f.totals[L]=Oa;t?(0>jb||jb>q)&&Oa.remove():(0>ib||ib>n)&&Oa.remove()}}}}}}}this.lastDataItem=v;if(\"line\"==h||\"step\"==h||\"smoothedLine\"==h)\"smoothedLine\"==h?this.drawSmoothedGraph(x,u,T,U):this.drawLineGraph(x,u,T,U),J||this.launchAnimation();this.bulletsHidden&&this.hideBullets();this.customBulletsHidden&&this.hideCustomBullets()},animateColumns:function(a,b){var c=this,e=c.chart.startDuration;\n0g.height&&(y=g.height),0>y&&(y=0));q=d.line(l,a,b,t,q,p,x,!1,!1,f);q.node.setAttribute(\"stroke-linejoin\",\"round\");d.setCN(k,q,g.bcn+\"stroke\");m.push(q);m.click(function(a){g.handleGraphEvent(a,\"clickGraph\")}).mouseover(function(a){g.handleGraphEvent(a,\n\"rollOverGraph\")}).mouseout(function(a){g.handleGraphEvent(a,\"rollOutGraph\")}).touchmove(function(a){g.chart.handleMouseMove(a)}).touchend(function(a){g.chart.handleTouchEnd(a)});void 0===z||g.useNegativeColorIfDown||(p=d.line(l,a,b,z,r,p,x,!1,!1,f),p.node.setAttribute(\"stroke-linejoin\",\"round\"),d.setCN(k,p,g.bcn+\"stroke\"),d.setCN(k,p,g.bcn+\"stroke-negative\"),n.push(p));if(0a&&(a=this.fillAlphas),0===a&&(a=this.bulletAlpha),0===a&&(a=1));return a},createBullet:function(a,b,c){if(!isNaN(b)&&!isNaN(c)&&(\"none\"!=this.bullet||this.customBullet||a.bullet||a.customBullet)){var e=this.chart,g=this.container,f=this.bulletOffset,h=this.bulletSize;isNaN(a.bulletSize)||\n(h=a.bulletSize);var k=a.values.value,l=this.maxValue,m=this.minValue,n=this.maxBulletSize,q=this.minBulletSize;isNaN(l)||(isNaN(k)||(h=(k-m)/(l-m)*(n-q)+q),m==l&&(h=n));l=h;this.bulletAxis&&(h=a.values.error,isNaN(h)||(k=h),h=this.bulletAxis.stepWidth*k);hb||b>this.width||c<-h/2||c>this.height)p.remove(),p=null;p&&(this.bulletSet.push(p),p.translate(b,c),this.addListeners(p,a),this.allBullets.push(p));a.bx=b;a.by=c;d.setCN(e,p,this.bcn+\"bullet\");a.className&&d.setCN(e,p,a.className,!0)}if(p){p.size=h||0;if(e=this.bulletHitAreaSize)g=d.circle(g,e,\"#FFFFFF\",.001,0),g.translate(b,c),a.hitBullet=g,this.bulletSet.push(g),this.addListeners(g,\na);a.bulletGraphics=p;void 0!==this.tabIndex&&p.setAttr(\"tabindex\",this.tabIndex)}else p={size:0};p.graphDataItem=a;return p}},showBullets:function(){var a=this.allBullets,b;this.bulletsHidden=!1;for(b=0;ba+k||gq+l)?(h.showBalloon(m),h.hide(0)):(h.followCursor(c),h.showBalloon(m)))):(this.hideBalloonReal(),h.hide(),this.resizeBullet(a,e,g))}else this.hideBalloonReal()}},resizeBullet:function(a,b,c){this.fixBulletSize();if(a&&d.isModern&&(1!=b||!isNaN(c))){var e=a.bulletGraphics;e&&!e.doNotScale&&(e.translate(a.bx,a.by,b),isNaN(c)||(e.setAttr(\"fill-opacity\",\nc),e.setAttr(\"stroke-opacity\",c)),this.resizedDItem=a)}}})})();(function(){var d=window.AmCharts;d.ChartCursor=d.Class({construct:function(a){this.cname=\"ChartCursor\";this.createEvents(\"changed\",\"zoomed\",\"onHideCursor\",\"onShowCursor\",\"draw\",\"selected\",\"moved\",\"panning\",\"zoomStarted\");this.enabled=!0;this.cursorAlpha=1;this.selectionAlpha=.2;this.cursorColor=\"#CC0000\";this.categoryBalloonAlpha=1;this.color=\"#FFFFFF\";this.type=\"cursor\";this.zoomed=!1;this.zoomable=!0;this.pan=!1;this.categoryBalloonDateFormat=\"MMM DD, YYYY\";this.categoryBalloonText=\"[[category]]\";\nthis.categoryBalloonEnabled=this.valueBalloonsEnabled=!0;this.rolledOver=!1;this.cursorPosition=\"middle\";this.bulletsEnabled=this.skipZoomDispatch=!1;this.bulletSize=8;this.selectWithoutZooming=this.oneBalloonOnly=!1;this.graphBulletSize=1.7;this.animationDuration=.3;this.zooming=!1;this.adjustment=0;this.avoidBalloonOverlapping=!0;this.leaveCursor=!1;this.leaveAfterTouch=!0;this.valueZoomable=!1;this.balloonPointerOrientation=\"horizontal\";this.hLineEnabled=this.vLineEnabled=!0;this.vZoomEnabled=\nthis.hZoomEnabled=!1;d.applyTheme(this,a,this.cname)},draw:function(){this.destroy();var a=this.chart;a.panRequired=!0;var b=a.container;this.rotate=a.rotate;this.container=b;this.prevLineHeight=this.prevLineWidth=NaN;b=b.set();b.translate(this.x,this.y);this.set=b;a.cursorSet.push(b);this.createElements();d.isString(this.limitToGraph)&&(this.limitToGraph=d.getObjById(a.graphs,this.limitToGraph),this.fullWidth=!1,this.cursorPosition=\"middle\");this.pointer=this.balloonPointerOrientation.substr(0,1).toUpperCase();\nthis.isHidden=!1;this.hideLines();this.valueLineAxis||(this.valueLineAxis=a.valueAxes[0])},createElements:function(){var a=this,b=a.chart,c=b.dx,e=b.dy,g=a.width,f=a.height,h,k,l=a.cursorAlpha,m=a.valueLineAlpha;a.rotate?(h=m,k=l):(k=m,h=l);\"xy\"==b.type&&(k=l,void 0!==m&&(k=m),h=l);a.vvLine=d.line(a.container,[c,0,0],[e,0,f],a.cursorColor,h,1);d.setCN(b,a.vvLine,\"cursor-line\");d.setCN(b,a.vvLine,\"cursor-line-vertical\");a.hhLine=d.line(a.container,[0,g,g+c],[0,0,e],a.cursorColor,k,1);d.setCN(b,a.hhLine,\n\"cursor-line\");d.setCN(b,a.hhLine,\"cursor-line-horizontal\");a.vLine=a.rotate?a.vvLine:a.hhLine;a.set.push(a.vvLine);a.set.push(a.hhLine);a.set.node.style.pointerEvents=\"none\";a.fullLines=a.container.set();b=b.cursorLineSet;b.push(a.fullLines);b.translate(a.x,a.y);b.clipRect(-1,-1,g+2,f+2);void 0!==a.tabIndex&&(b.setAttr(\"tabindex\",a.tabIndex),b.keyup(function(b){a.handleKeys(b)}).focus(function(b){a.showCursor()}).blur(function(b){a.hideCursor()}));a.set.clipRect(0,0,g,f)},handleKeys:function(a){var b=\nthis.prevIndex,c=this.chart;if(c){var e=c.chartData;e&&(isNaN(b)&&(b=e.length-1),37!=a.keyCode&&40!=a.keyCode||b--,39!=a.keyCode&&38!=a.keyCode||b++,b=d.fitToBounds(b,c.startIndex,c.endIndex),(a=this.chart.chartData[b])&&this.setPosition(a.x.categoryAxis),this.prevIndex=b)}},update:function(){var a=this.chart;if(a){var b=a.mouseX-this.x,c=a.mouseY-this.y;this.mouseX=b;this.mouseY=c;this.mouse2X=a.mouse2X-this.x;this.mouse2Y=a.mouse2Y-this.y;var e;if(a.chartData&&0document.documentMode&&(this.updateOnReleaseOnly=!0);this.dragIconHeight=this.dragIconWidth=35;this.dragIcon=\"dragIconRoundBig\";\nthis.dragCursorHover=\"cursor: move; cursor: grab; cursor: -moz-grab; cursor: -webkit-grab;\";this.dragCursorDown=\"cursor: move; cursor: grab; cursor: -moz-grabbing; cursor: -webkit-grabbing;\";this.vResizeCursor=\"ns-resize\";this.hResizeCursor=\"ew-resize\";this.enabled=!0;this.percentStart=this.offset=0;this.percentEnd=1;d.applyTheme(this,a,\"SimpleChartScrollbar\")},getPercents:function(){var a=this.getDBox(),b=a.x,c=a.y,e=a.width,a=a.height;this.rotate?(b=1-c/this.height,c=1-(c+a)/this.height):(c=b/this.width,\nb=(b+e)/this.width);this.percentStart=c;this.percentEnd=b},draw:function(){var a=this;a.destroy();if(a.enabled){var b=a.chart.container,c=a.rotate,e=a.chart;e.panRequired=!0;var g=b.set();a.set=g;c?d.setCN(e,g,\"scrollbar-vertical\"):d.setCN(e,g,\"scrollbar-horizontal\");e.scrollbarsSet.push(g);var f,h;c?(f=a.scrollbarHeight,h=e.plotAreaHeight):(h=a.scrollbarHeight,f=e.plotAreaWidth);a.width=f;if((a.height=h)&&f){var k=d.rect(b,f,h,a.backgroundColor,a.backgroundAlpha,1,a.backgroundColor,a.backgroundAlpha);\nd.setCN(e,k,\"scrollbar-bg\");a.bg=k;g.push(k);k=d.rect(b,f,h,\"#000\",.005);g.push(k);a.invisibleBg=k;k.click(function(){a.handleBgClick()}).mouseover(function(){a.handleMouseOver()}).mouseout(function(){a.handleMouseOut()}).touchend(function(){a.handleBgClick()});k=d.rect(b,f,h,a.selectedBackgroundColor,a.selectedBackgroundAlpha);d.setCN(e,k,\"scrollbar-bg-selected\");a.selectedBG=k;g.push(k);f=d.rect(b,f,h,\"#000\",.005);a.dragger=f;g.push(f);f.mousedown(function(b){a.handleDragStart(b)}).mouseup(function(){a.handleDragStop()}).mouseover(function(){a.handleDraggerOver()}).mouseout(function(){a.handleMouseOut()}).touchstart(function(b){a.handleDragStart(b)}).touchend(function(){a.handleDragStop()});\nh=e.pathToImages;var l,k=a.dragIcon.replace(/\\.[a-z]*$/i,\"\");d.isAbsolute(k)&&(h=\"\");c?(l=h+k+\"H\"+e.extension,h=a.dragIconWidth,c=a.dragIconHeight):(l=h+k+e.extension,c=a.dragIconWidth,h=a.dragIconHeight);k=b.image(l,0,0,c,h);d.setCN(e,k,\"scrollbar-grip-left\");l=b.image(l,0,0,c,h);d.setCN(e,l,\"scrollbar-grip-right\");var m=10,n=20;e.panEventsEnabled&&(m=25,n=a.scrollbarHeight);var q=d.rect(b,m,n,\"#000\",.005),p=d.rect(b,m,n,\"#000\",.005);p.translate(-(m-c)/2,-(n-h)/2);q.translate(-(m-c)/2,-(n-h)/2);\nc=b.set([k,p]);b=b.set([l,q]);a.iconLeft=c;g.push(a.iconLeft);a.iconRight=b;g.push(b);a.updateGripCursor(!1);e.makeAccessible(c,a.accessibleLabel);e.makeAccessible(b,a.accessibleLabel);e.makeAccessible(f,a.accessibleLabel);c.setAttr(\"role\",\"menuitem\");b.setAttr(\"role\",\"menuitem\");f.setAttr(\"role\",\"menuitem\");void 0!==a.tabIndex&&(c.setAttr(\"tabindex\",a.tabIndex),c.keyup(function(b){a.handleKeys(b,1,0)}));void 0!==a.tabIndex&&(f.setAttr(\"tabindex\",a.tabIndex),f.keyup(function(b){a.handleKeys(b,1,1)}));\nvoid 0!==a.tabIndex&&(b.setAttr(\"tabindex\",a.tabIndex),b.keyup(function(b){a.handleKeys(b,0,1)}));c.mousedown(function(){a.leftDragStart()}).mouseup(function(){a.leftDragStop()}).mouseover(function(){a.iconRollOver()}).mouseout(function(){a.iconRollOut()}).touchstart(function(){a.leftDragStart()}).touchend(function(){a.leftDragStop()});b.mousedown(function(){a.rightDragStart()}).mouseup(function(){a.rightDragStop()}).mouseover(function(){a.iconRollOver()}).mouseout(function(){a.iconRollOut()}).touchstart(function(){a.rightDragStart()}).touchend(function(){a.rightDragStop()});\nd.ifArray(e.chartData)?g.show():g.hide();a.hideDragIcons();a.clipDragger(!1)}g.translate(a.x,a.y);g.node.style.msTouchAction=\"none\";g.node.style.touchAction=\"none\"}},handleKeys:function(a,b,c){this.getPercents();var e=this.percentStart,d=this.percentEnd;if(this.rotate)var f=d,d=e,e=f;if(37==a.keyCode||40==a.keyCode)e-=.02*b,d-=.02*c;if(39==a.keyCode||38==a.keyCode)e+=.02*b,d+=.02*c;this.rotate&&(a=d,d=e,e=a);isNaN(d)||isNaN(e)||this.percentZoom(e,d,!0)},updateScrollbarSize:function(a,b){if(!isNaN(a)&&\n!isNaN(b)){a=Math.round(a);b=Math.round(b);var c=this.dragger,e,d,f,h,k;this.rotate?(e=0,d=a,f=this.width+1,h=b-a,c.setAttr(\"height\",b-a),c.setAttr(\"y\",d)):(e=a,d=0,f=b-a,h=this.height+1,k=b-a,c.setAttr(\"x\",e),c.setAttr(\"width\",k));this.clipAndUpdate(e,d,f,h)}},update:function(){var a,b=!1,c,e,d=this.x,f=this.y,h=this.dragger,k=this.getDBox();if(k){c=k.x+d;e=k.y+f;var l=k.width,k=k.height,m=this.rotate,n=this.chart,q=this.width,p=this.height,t=n.mouseX,n=n.mouseY;a=this.initialMouse;this.forceClip&&\nthis.clipDragger(!0);if(this.dragging){var r=this.initialCoord;if(m)a=r+(n-a),0>a&&(a=0),r=p-k,a>r&&(a=r),h.setAttr(\"y\",a);else{a=r+(t-a);0>a&&(a=0);r=q-l;if(a>r||isNaN(a))a=r;h.setAttr(\"x\",a)}this.clipDragger(!0)}if(this.resizingRight){if(m)if(a=n-e,!isNaN(this.maxHeight)&&a>this.maxHeight&&(a=this.maxHeight),a+e>p+f&&(a=p-e+f),0>a)this.resizingRight=!1,b=this.resizingLeft=!0;else{if(0===a||isNaN(a))a=.1;h.setAttr(\"height\",a)}else if(a=t-c,!isNaN(this.maxWidth)&&a>this.maxWidth&&(a=this.maxWidth),\na+c>q+d&&(a=q-c+d),0>a)this.resizingRight=!1,b=this.resizingLeft=!0;else{if(0===a||isNaN(a))a=.1;h.setAttr(\"width\",a)}this.clipDragger(!0)}if(this.resizingLeft){if(m)if(c=e,e=n,ep+f&&(e=p+f),a=!0===b?c-e:k+c-e,!isNaN(this.maxHeight)&&a>this.maxHeight&&(a=this.maxHeight,e=c),0>a)this.resizingRight=!0,this.resizingLeft=!1,h.setAttr(\"y\",c+k-f);else{if(0===a||isNaN(a))a=.1;h.setAttr(\"y\",e-f);h.setAttr(\"height\",a)}else if(e=t,eq+d&&(e=q+d),a=!0===\nb?c-e:l+c-e,!isNaN(this.maxWidth)&&a>this.maxWidth&&(a=this.maxWidth,e=c),0>a)this.resizingRight=!0,this.resizingLeft=!1,h.setAttr(\"x\",c+l-d);else{if(0===a||isNaN(a))a=.1;h.setAttr(\"x\",e-d);h.setAttr(\"width\",a)}this.clipDragger(!0)}}},stopForceClip:function(){this.animating=this.forceClip=!1},clipDragger:function(a){var b=this.getDBox();if(b){var c=b.x,e=b.y,d=b.width,b=b.height,f=!1;if(this.rotate){if(c=0,d=this.width+1,this.clipY!=e||this.clipH!=b)f=!0}else if(e=0,b=this.height+1,this.clipX!=c||\nthis.clipW!=d)f=!0;f&&this.clipAndUpdate(c,e,d,b);a&&(this.updateOnReleaseOnly||this.dispatchScrollbarEvent())}},maskGraphs:function(){},clipAndUpdate:function(a,b,c,e){this.clipX=a;this.clipY=b;this.clipW=c;this.clipH=e;this.selectedBG.setAttr(\"width\",c);this.selectedBG.setAttr(\"height\",e);this.selectedBG.translate(a,b);this.updateDragIconPositions();this.maskGraphs(a,b,c,e)},dispatchScrollbarEvent:function(){if(this.skipEvent)this.skipEvent=!1;else{var a=this.chart;a.hideBalloon();var b=this.getDBox(),\nc=b.x,e=b.y,d=b.width,b=b.height;this.getPercents();this.rotate?(c=e,d=this.height/b):d=this.width/d;a={type:\"zoomed\",position:c,chart:a,target:this,multiplier:d,relativeStart:this.percentStart,relativeEnd:this.percentEnd};if(this.percentStart!=this.prevPercentStart||this.percentEnd!=this.prevPercentEnd||this.prevMultiplier!=d)this.fire(a),this.prevPercentStart=this.percentStart,this.prevPercentEnd=this.percentEnd,this.prevMultiplier=d}},updateDragIconPositions:function(){var a=this.getDBox(),b=a.x,\nc=a.y,d=this.iconLeft,g=this.iconRight,f,h,k=this.scrollbarHeight;this.rotate?(f=this.dragIconWidth,h=this.dragIconHeight,d.translate((k-h)/2,c-f/2),g.translate((k-h)/2,c+a.height-f/2)):(f=this.dragIconHeight,h=this.dragIconWidth,d.translate(b-h/2,(k-f)/2),g.translate(b-h/2+a.width,(k-f)/2))},showDragIcons:function(){this.resizeEnabled&&(this.iconLeft.show(),this.iconRight.show())},hideDragIcons:function(){if(!this.resizingLeft&&!this.resizingRight&&!this.dragging){if(this.hideResizeGrips||!this.resizeEnabled)this.iconLeft.hide(),\nthis.iconRight.hide();this.removeCursors()}},removeCursors:function(){this.chart.setMouseCursor(\"auto\")},fireZoomEvent:function(a){this.fire({type:a,chart:this.chart,target:this})},percentZoom:function(a,b,c){a=d.fitToBounds(a,0,b);b=d.fitToBounds(b,a,1);if(this.dragger&&this.enabled){this.dragger.stop();isNaN(a)&&(a=0);isNaN(b)&&(b=1);var e,g;this.rotate?(e=this.height,b=e-e*b,g=e-e*a):(e=this.width,g=e*b,b=e*a);this.updateScrollbarSize(b,g);this.clipDragger(!1);this.getPercents();c&&this.dispatchScrollbarEvent()}},\ndestroy:function(){this.clear();d.remove(this.set);d.remove(this.iconRight);d.remove(this.iconLeft)},clear:function(){},handleDragStart:function(){if(this.enabled){this.fireZoomEvent(\"zoomStarted\");var a=this.chart;this.dragger.stop();this.removeCursors();d.isModern&&(this.dragger.node.style.cssText=this.dragCursorDown);this.dragging=!0;var b=this.getDBox();this.rotate?(this.initialCoord=b.y,this.initialMouse=a.mouseY):(this.initialCoord=b.x,this.initialMouse=a.mouseX)}},handleDragStop:function(){this.updateOnReleaseOnly&&\n(this.update(),this.skipEvent=!1,this.dispatchScrollbarEvent());this.dragging=!1;this.mouseIsOver&&this.removeCursors();d.isModern&&(this.dragger.node.style.cssText=this.dragCursorHover);this.update();this.fireZoomEvent(\"zoomEnded\")},handleDraggerOver:function(){this.handleMouseOver();d.isModern&&(this.dragger.node.style.cssText=this.dragCursorHover)},leftDragStart:function(){this.fireZoomEvent(\"zoomStarted\");this.dragger.stop();this.resizingLeft=!0;this.updateGripCursor(!0)},updateGripCursor:function(a){d.isModern&&\n(a=this.rotate?a?this.vResizeCursorDown:this.vResizeCursorHover:a?this.hResizeCursorDown:this.hResizeCursorHover)&&(this.iconRight&&(this.iconRight.node.style.cssText=a),this.iconLeft&&(this.iconLeft.node.style.cssText=a))},leftDragStop:function(){this.resizingLeft&&(this.resizingLeft=!1,this.mouseIsOver||this.removeCursors(),this.updateOnRelease(),this.fireZoomEvent(\"zoomEnded\"));this.updateGripCursor(!1)},rightDragStart:function(){this.fireZoomEvent(\"zoomStarted\");this.dragger.stop();this.resizingRight=\n!0;this.updateGripCursor(!0)},rightDragStop:function(){this.resizingRight&&(this.resizingRight=!1,this.mouseIsOver||this.removeCursors(),this.updateOnRelease(),this.fireZoomEvent(\"zoomEnded\"));this.updateGripCursor(!1)},iconRollOut:function(){this.removeCursors()},iconRollOver:function(){this.rotate?this.vResizeCursor&&this.chart.setMouseCursor(this.vResizeCursor):this.hResizeCursor&&this.chart.setMouseCursor(this.hResizeCursor);this.handleMouseOver()},getDBox:function(){if(this.dragger)return this.dragger.getBBox()},\nhandleBgClick:function(){var a=this;if(!a.resizingRight&&!a.resizingLeft){a.zooming=!0;var b,c,e=a.scrollDuration,g=a.dragger;b=a.getDBox();var f=b.height,h=b.width;c=a.chart;var k=a.y,l=a.x,m=a.rotate;m?(b=\"y\",c=c.mouseY-f/2-k,c=d.fitToBounds(c,0,a.height-f)):(b=\"x\",c=c.mouseX-h/2-l,c=d.fitToBounds(c,0,a.width-h));a.updateOnReleaseOnly?(a.skipEvent=!1,g.setAttr(b,c),a.dispatchScrollbarEvent(),a.clipDragger()):(a.animating=!0,c=Math.round(c),m?g.animate({y:c},e,\">\"):g.animate({x:c},e,\">\"),a.forceClip=\n!0,clearTimeout(a.forceTO),a.forceTO=setTimeout(function(){a.stopForceClip.call(a)},5E3*e))}},updateOnRelease:function(){this.updateOnReleaseOnly&&(this.update(),this.skipEvent=!1,this.dispatchScrollbarEvent())},handleReleaseOutside:function(){if(this.set){if(this.resizingLeft||this.resizingRight||this.dragging)this.dragging=this.resizingRight=this.resizingLeft=!1,this.updateOnRelease(),this.removeCursors();this.animating=this.mouseIsOver=!1;this.hideDragIcons();this.update()}},handleMouseOver:function(){this.mouseIsOver=\n!0;this.showDragIcons()},handleMouseOut:function(){this.mouseIsOver=!1;this.hideDragIcons();this.removeCursors()}})})();(function(){var d=window.AmCharts;d.ChartScrollbar=d.Class({inherits:d.SimpleChartScrollbar,construct:function(a){this.cname=\"ChartScrollbar\";d.ChartScrollbar.base.construct.call(this,a);this.graphLineColor=\"#BBBBBB\";this.graphLineAlpha=0;this.graphFillColor=\"#BBBBBB\";this.graphFillAlpha=1;this.selectedGraphLineColor=\"#888888\";this.selectedGraphLineAlpha=0;this.selectedGraphFillColor=\"#888888\";this.selectedGraphFillAlpha=1;this.gridCount=0;this.gridColor=\"#FFFFFF\";this.gridAlpha=.7;this.skipEvent=\nthis.autoGridCount=!1;this.color=\"#FFFFFF\";this.scrollbarCreated=!1;this.oppositeAxis=!0;this.accessibleLabel=\"Zoom chart using cursor arrows\";d.applyTheme(this,a,this.cname)},init:function(){var a=this.categoryAxis,b=this.chart,c=this.gridAxis;a||(\"CategoryAxis\"==this.gridAxis.cname?(this.catScrollbar=!0,a=new d.CategoryAxis,a.id=\"scrollbar\"):(a=new d.ValueAxis,a.data=b.chartData,a.id=c.id,a.type=c.type,a.maximumDate=c.maximumDate,a.minimumDate=c.minimumDate,a.minPeriod=c.minPeriod,a.minMaxField=\nc.minMaxField),this.categoryAxis=a);a.chart=b;var e=b.categoryAxis;e&&(a.firstDayOfWeek=e.firstDayOfWeek);a.dateFormats=c.dateFormats;a.markPeriodChange=c.markPeriodChange;a.boldPeriodBeginning=c.boldPeriodBeginning;a.labelFunction=c.labelFunction;a.axisItemRenderer=d.RecItem;a.axisRenderer=d.RecAxis;a.guideFillRenderer=d.RecFill;a.inside=!0;a.fontSize=this.fontSize;a.tickLength=0;a.axisAlpha=0;d.isString(this.graph)&&(this.graph=d.getObjById(b.graphs,this.graph));(a=this.graph)&&this.catScrollbar&&\n(c=this.valueAxis,c||(this.valueAxis=c=new d.ValueAxis,c.visible=!1,c.scrollbar=!0,c.axisItemRenderer=d.RecItem,c.axisRenderer=d.RecAxis,c.guideFillRenderer=d.RecFill,c.labelsEnabled=!1,c.chart=b),b=this.unselectedGraph,b||(b=new d.AmGraph,b.scrollbar=!0,this.unselectedGraph=b,b.negativeBase=a.negativeBase,b.noStepRisers=a.noStepRisers),b=this.selectedGraph,b||(b=new d.AmGraph,b.scrollbar=!0,this.selectedGraph=b,b.negativeBase=a.negativeBase,b.noStepRisers=a.noStepRisers));this.scrollbarCreated=!0},\ndraw:function(){var a=this;d.ChartScrollbar.base.draw.call(a);if(a.enabled){a.scrollbarCreated||a.init();var b=a.chart,c=b.chartData,e=a.categoryAxis,g=a.rotate,f=a.x,h=a.y,k=a.width,l=a.height,m=a.gridAxis,n=a.set;e.setOrientation(!g);e.parseDates=m.parseDates;\"ValueAxis\"==a.categoryAxis.cname&&(e.rotate=!g);e.equalSpacing=m.equalSpacing;e.minPeriod=m.minPeriod;e.startOnAxis=m.startOnAxis;e.width=k-1;e.height=l;e.gridCount=a.gridCount;e.gridColor=a.gridColor;e.gridAlpha=a.gridAlpha;e.color=a.color;\ne.tickLength=0;e.axisAlpha=0;e.autoGridCount=a.autoGridCount;e.parseDates&&!e.equalSpacing&&e.timeZoom(b.firstTime,b.lastTime);e.minimum=a.gridAxis.fullMin;e.maximum=a.gridAxis.fullMax;e.strictMinMax=!0;e.zoom(0,c.length-1);if((m=a.graph)&&a.catScrollbar){var q=a.valueAxis,p=m.valueAxis;q.id=p.id;q.rotate=g;q.setOrientation(g);q.width=k;q.height=l;q.dataProvider=c;q.reversed=p.reversed;q.logarithmic=p.logarithmic;q.gridAlpha=0;q.axisAlpha=0;n.push(q.set);g?(q.y=h,q.x=0):(q.x=f,q.y=0);var f=Infinity,\nh=-Infinity,t;for(t=0;th&&(h=z)}}Infinity!=f&&(q.minimum=f);-Infinity!=h&&(q.maximum=h+.1*(h-f));f==h&&(--q.minimum,q.maximum+=1);void 0!==a.minimum&&(q.minimum=a.minimum);void 0!==a.maximum&&(q.maximum=a.maximum);q.zoom(0,c.length-1);w=a.unselectedGraph;w.id=m.id;w.bcn=\"scrollbar-graph-\";w.rotate=g;w.chart=b;w.data=c;w.valueAxis=q;w.chart=m.chart;w.categoryAxis=\na.categoryAxis;w.periodSpan=m.periodSpan;w.valueField=m.valueField;w.openField=m.openField;w.closeField=m.closeField;w.highField=m.highField;w.lowField=m.lowField;w.lineAlpha=a.graphLineAlpha;w.lineColorR=a.graphLineColor;w.fillAlphas=a.graphFillAlpha;w.fillColorsR=a.graphFillColor;w.connect=m.connect;w.hidden=m.hidden;w.width=k;w.height=l;w.pointPosition=m.pointPosition;w.stepDirection=m.stepDirection;w.periodSpan=m.periodSpan;p=a.selectedGraph;p.id=m.id;p.bcn=w.bcn+\"selected-\";p.rotate=g;p.chart=\nb;p.data=c;p.valueAxis=q;p.chart=m.chart;p.categoryAxis=e;p.periodSpan=m.periodSpan;p.valueField=m.valueField;p.openField=m.openField;p.closeField=m.closeField;p.highField=m.highField;p.lowField=m.lowField;p.lineAlpha=a.selectedGraphLineAlpha;p.lineColorR=a.selectedGraphLineColor;p.fillAlphas=a.selectedGraphFillAlpha;p.fillColorsR=a.selectedGraphFillColor;p.connect=m.connect;p.hidden=m.hidden;p.width=k;p.height=l;p.pointPosition=m.pointPosition;p.stepDirection=m.stepDirection;p.periodSpan=m.periodSpan;\nb=a.graphType;b||(b=m.type);w.type=b;p.type=b;c=c.length-1;w.zoom(0,c);p.zoom(0,c);p.set.click(function(){a.handleBackgroundClick()}).mouseover(function(){a.handleMouseOver()}).mouseout(function(){a.handleMouseOut()});w.set.click(function(){a.handleBackgroundClick()}).mouseover(function(){a.handleMouseOver()}).mouseout(function(){a.handleMouseOut()});n.push(w.set);n.push(p.set)}n.push(e.set);n.push(e.labelsSet);a.bg.toBack();a.invisibleBg.toFront();a.dragger.toFront();a.iconLeft.toFront();a.iconRight.toFront()}},\ntimeZoom:function(a,b,c){this.startTime=a;this.endTime=b;this.timeDifference=b-a;this.skipEvent=!d.toBoolean(c);this.zoomScrollbar();this.dispatchScrollbarEvent()},zoom:function(a,b){this.start=a;this.end=b;this.skipEvent=!0;this.zoomScrollbar()},dispatchScrollbarEvent:function(){if(this.categoryAxis&&\"ValueAxis\"==this.categoryAxis.cname)d.ChartScrollbar.base.dispatchScrollbarEvent.call(this);else if(this.skipEvent)this.skipEvent=!1;else{var a=this.chart.chartData,b,c,e=this.dragger.getBBox();b=e.x;\nvar g=e.y,f=e.width,e=e.height,h=this.chart;this.rotate?(b=g,c=e):c=f;f={type:\"zoomed\",target:this};f.chart=h;var k=this.categoryAxis,l=this.stepWidth,e=h.minSelectedTime,m=h.maxSelectedTime,g=!1;if(k.parseDates&&!k.equalSpacing){if(a=h.lastTime,h=h.firstTime,k=Math.round(b/l)+h,b=this.dragging?k+this.timeDifference:Math.round((b+c)/l)+h,k>b&&(k=b),0m&&(b=Math.round(k+(b-k)/2),g=Math.round(m/2),k=b-g,b+=g,g=!0),b>a&&(b=\na),b-eb&&(b=k+e),k!=this.startTime||b!=this.endTime)this.startTime=k,this.endTime=b,f.start=k,f.end=b,f.startDate=new Date(k),f.endDate=new Date(b),this.fire(f)}else{m=l/2;k.startOnAxis||(b+=m,c-=m);e=k.xToIndex(b);k.startOnAxis||(b=k.getCoordinate(e)-m);b=k.xToIndex(b+c);if(e!=this.start||this.end!=b)k.startOnAxis&&(this.resizingRight&&e==b&&b++,this.resizingLeft&&e==b&&(0this.timeDifference&&\n(this.timeDifference=0)},handleBackgroundClick:function(){d.ChartScrollbar.base.handleBackgroundClick.call(this);this.dragging||(this.difference=this.end-this.start,this.timeDifference=this.endTime-this.startTime,0>this.timeDifference&&(this.timeDifference=0))}})})();(function(){var d=window.AmCharts;d.AmBalloon=d.Class({construct:function(a){this.cname=\"AmBalloon\";this.enabled=!0;this.fillColor=\"#FFFFFF\";this.fillAlpha=.8;this.borderThickness=2;this.borderColor=\"#FFFFFF\";this.borderAlpha=1;this.cornerRadius=0;this.maxWidth=220;this.horizontalPadding=8;this.verticalPadding=4;this.pointerWidth=6;this.pointerOrientation=\"V\";this.color=\"#000000\";this.adjustBorderColor=!0;this.show=this.follow=this.showBullet=!1;this.bulletSize=3;this.shadowAlpha=.4;this.shadowColor=\n\"#000000\";this.fadeOutDuration=this.animationDuration=.3;this.fixedPosition=!0;this.offsetY=6;this.offsetX=1;this.textAlign=\"center\";this.disableMouseEvents=!0;this.deltaSignX=this.deltaSignY=1;d.isModern||(this.offsetY*=1.5);this.sdy=this.sdx=0;d.applyTheme(this,a,this.cname)},draw:function(){var a=this.pointToX,b=this.pointToY;d.isModern||(this.drop=!1);var c=this.chart;d.VML&&(this.fadeOutDuration=0);this.xAnim&&c.stopAnim(this.xAnim);this.yAnim&&c.stopAnim(this.yAnim);this.sdy=this.sdx=0;if(!isNaN(a)){var e=\nthis.follow,g=c.container,f=this.set;d.remove(f);this.removeDiv();f=g.set();f.node.style.pointerEvents=\"none\";this.set=f;this.mainSet?(this.mainSet.push(this.set),this.sdx=this.mainSet.x,this.sdy=this.mainSet.y):c.balloonsSet.push(f);if(this.show){var h=this.l,k=this.t,l=this.r,m=this.b,n=this.balloonColor,q=this.fillColor,p=this.borderColor,t=q;void 0!=n&&(this.adjustBorderColor?t=p=n:q=n);var r=this.horizontalPadding,w=this.verticalPadding,z=this.pointerWidth,x=this.pointerOrientation,u=this.cornerRadius,\nA=c.fontFamily,y=this.fontSize;void 0==y&&(y=c.fontSize);var n=document.createElement(\"div\"),B=c.classNamePrefix;n.className=B+\"-balloon-div\";this.className&&(n.className=n.className+\" \"+B+\"-balloon-div-\"+this.className);B=n.style;this.disableMouseEvents&&(B.pointerEvents=\"none\");B.position=\"absolute\";var D=this.minWidth,C=document.createElement(\"div\");n.appendChild(C);var I=C.style;isNaN(D)||(I.minWidth=D-2*r+\"px\");I.textAlign=this.textAlign;I.maxWidth=this.maxWidth+\"px\";I.fontSize=y+\"px\";I.color=\nthis.color;I.fontFamily=A;C.innerHTML=this.text;c.chartDiv.appendChild(n);this.textDiv=n;var I=n.offsetWidth,H=n.offsetHeight;n.clientHeight&&(I=n.clientWidth,H=n.clientHeight);A=H+2*w;C=I+2*r;!isNaN(D)&&CA&&(z=A/2),y=b-A/2,a=m&&(y=m-A);yl&&(D=l-C);var k=y+w,m=D+r,M=this.shadowAlpha,P=this.shadowColor,r=this.borderThickness,ia=this.bulletSize,J,w=this.fillAlpha,aa=this.borderAlpha;this.showBullet&&(J=d.circle(g,ia,t,w),f.push(J));this.drop?(h=C/1.6,l=0,\"V\"==x&&(x=\"down\"),\"H\"==x&&(x=\"left\"),\"down\"==x&&(D=a+1,y=b-h-h/3),\"up\"==x&&(l=180,D=a+1,y=b+h+h/3),\"left\"==x&&(l=270,D=a+h+h/3+2,y=b),\"right\"==x&&(l=90,D=a-h-h/3+2,y=b),k=y-H/2+1,m=D-I/2-1,q=d.drop(g,h,l,q,w,r,p,aa)):0C-z&&(h=C-z),hA-z&&(x=A-z),xa?C:a-D,C,C,0,0,C]),0this.r-d.width&&(a=this.r-d.width);gthis.processCount&&(this.processCount=1);var b=a.length/this.processCount;this.parseCount=Math.ceil(b)-1;for(var c=0;ca.length&&(c=a.length);var g=this.graphs,f={},h=this.seriesIdField;h||(h=this.categoryField);var k=!1,l,m=this.categoryAxis,n,q,p;m&&(k=m.parseDates,n=m.forceShowField,p=m.classNameField,q=m.labelColorField,l=m.categoryFunction);var t,r,w={},z;k&&(t=d.extractPeriod(m.minPeriod),\nr=t.period,t=t.count,z=d.getPeriodDuration(r,t));var x={};this.lookupTable=x;var u,A=this.dataDateFormat,y={};for(u=b;u=z*P&&(y[M].gap=!0),b.forceGap){var P=0,ma;for(ma in J.values)P++;\n0b?this.colors[b]:a.lineColorR?a.lineColorR:d.randomColor();a.lineColorR=c}a.fillColorsR=a.fillColors?a.fillColors:a.lineColorR;a.bulletBorderColorR=a.bulletBorderColor?a.bulletBorderColor:a.useLineColorForBulletBorder?a.lineColorR:a.bulletColor;a.bulletColorR=a.bulletColor?a.bulletColor:a.lineColorR;\nif(c=this.patterns)a.pattern=c[b]},handleLegendEvent:function(a){var b=a.type;if(a=a.dataItem){var c=a.hidden,d=a.showBalloon;switch(b){case \"clickMarker\":this.textClickEnabled&&(d?this.hideGraphsBalloon(a):this.showGraphsBalloon(a));break;case \"clickLabel\":d?this.hideGraphsBalloon(a):this.showGraphsBalloon(a);break;case \"rollOverItem\":c||this.highlightGraph(a);break;case \"rollOutItem\":c||this.unhighlightGraph();break;case \"hideItem\":this.hideGraph(a);break;case \"showItem\":this.showGraph(a)}}},highlightGraph:function(a){var b=\nthis.graphs;if(b){var c,d=.2;this.legend&&(d=this.legend.rollOverGraphAlpha);if(1!=d)for(c=0;c=b&&(b=.001);if(void 0==g||0===g)g=.01;void 0===f&&(f=\"#000000\");void 0===h&&(h=0);e={fill:c,stroke:f,\"fill-opacity\":e,\"stroke-width\":g,\"stroke-opacity\":h};a=isNaN(l)?a.circle(0,0,b).attr(e):a.ellipse(0,0,b,l).attr(e);k&&a.gradient(\"radialGradient\",[c,d.adjustLuminosity(c,-.6)]);return a};d.text=function(a,b,c,e,g,f,h,k){f||(f=\"middle\");\"right\"==f&&(f=\"end\");\"left\"==f&&(f=\"start\");isNaN(k)&&(k=1);void 0!==b&&(b=String(b),d.isIE&&\n!d.isModern&&(b=b.replace(\"&\",\"&\"),b=b.replace(\"&\",\"&\")));c={fill:c,\"font-family\":e,\"font-size\":g+\"px\",opacity:k};!0===h&&(c[\"font-weight\"]=\"bold\");c[\"text-anchor\"]=f;return a.text(b,c)};d.polygon=function(a,b,c,e,g,f,h,k,l,m,n){isNaN(f)&&(f=.01);isNaN(k)&&(k=g);var q=e,p=!1;\"object\"==typeof q&&1b&&(b=Math.abs(b),t=-b);0>c&&(c=Math.abs(c),r=-c);t+=d.dx;r+=d.dy;g={fill:q,stroke:h,\"fill-opacity\":g,\"stroke-opacity\":k};void 0!==n&&0=x&&(g=x);var u=1/180*Math.PI,x=b+Math.sin(e*u)*k,A=c-Math.cos(e*u)*w,y=b+Math.sin(e*u)*f,B=c-Math.cos(e*u)*h,D=b+Math.sin((e+g)*u)*f,C=c-Math.cos((e+g)*u)*h,I=b+Math.sin((e+g)*u)*k,u=c-Math.cos((e+g)*u)*w,H={fill:d.adjustLuminosity(m.fill,-.2),\"stroke-opacity\":0,\"fill-opacity\":m[\"fill-opacity\"]},Q=0;180Math.abs(g)&&1>=Math.abs(D-y)&&1>=Math.abs(C-B)&&(M=!0));g=\"\";var P;q&&(H[\"fill-opacity\"]=0,H[\"stroke-opacity\"]=m[\"stroke-opacity\"]/2,H.stroke=m.stroke);if(0a.length&&(a=String(a[0])+String(a[0])+String(a[1])+String(a[1])+String(a[2])+String(a[2]));b=b||0;var c=\"#\",e,g;for(g=0;3>g;g++)e=parseInt(a.substr(2*g,2),16),e=Math.round(Math.min(Math.max(0,e+e*b),255)).toString(16),c+=(\"00\"+\ne).substr(e.length);return c}})();(function(){var d=window.AmCharts;d.Bezier=d.Class({construct:function(a,b,c,e,g,f,h,k,l,m,n){var q=a.chart,p=d.bezierX,t=d.bezierY;isNaN(q.bezierX)||(p=q.bezierX);isNaN(q.bezierY)||(t=q.bezierY);isNaN(p)&&(q.rotate?(p=20,t=4):(t=20,p=4));var r,w;\"object\"==typeof h&&1=a.length-2?(f.push({x:h.x,y:h.y}),f.push({x:k.x,y:k.y}),f.push({x:l.x,y:l.y}),f.push({x:l.x,y:l.y})):(f.push({x:h.x,y:h.y}),f.push({x:k.x,y:k.y}),f.push({x:l.x,y:l.y}),f.push({x:m.x,y:m.y}));h=[];k=Math.round;h.push({x:k(f[1].x),y:k(f[1].y)});h.push({x:k((-f[0].x+b*f[1].x+f[2].x)/b),y:k((-f[0].y+c*f[1].y+f[2].y)/c)});h.push({x:k((f[1].x+b*f[2].x-f[3].x)/b),y:k((f[1].y+c*f[2].y-f[3].y)/c)});h.push({x:k(f[2].x),y:k(f[2].y)});d+=\"C\"+h[1].x+\",\"+h[1].y+\",\"+\nh[2].x+\",\"+h[2].y+\",\"+h[3].x+\",\"+h[3].y+\" \"}else 1b&&(b=10);1>c&&(c=10);this.div=a;this.width=b;this.height=c;this.rBin=document.createElement(\"div\");d.hasSVG?(d.SVG=!0,b=this.createSvgElement(\"svg\"),a.appendChild(b),this.container=b,this.addDefs(e),this.R=new d.SVGRenderer(this)):d.isIE&&d.VMLRenderer&&\n(d.VML=!0,d.vmlStyleSheet||(document.namespaces.add(\"amvml\",\"urn:schemas-microsoft-com:vml\"),31>document.styleSheets.length?(b=document.createStyleSheet(),b.addRule(\".amvml\",\"behavior:url(#default#VML); display:inline-block; antialias:true\"),d.vmlStyleSheet=b):document.styleSheets[0].addRule(\".amvml\",\"behavior:url(#default#VML); display:inline-block; antialias:true\")),this.container=a,this.R=new d.VMLRenderer(this,e),this.R.disableSelection(a))},createSvgElement:function(a){return document.createElementNS(d.SVG_NS,\na)},circle:function(a,b,c,e){var g=new d.AmDObject(\"circle\",this);g.attr({r:c,cx:a,cy:b});this.addToContainer(g.node,e);return g},ellipse:function(a,b,c,e,g){var f=new d.AmDObject(\"ellipse\",this);f.attr({rx:c,ry:e,cx:a,cy:b});this.addToContainer(f.node,g);return f},setSize:function(a,b){0c&&(c=1);1>e&&(e=1);k.attr({x:a,y:b,width:c,height:e,rx:g,ry:g,\"stroke-width\":f});this.addToContainer(k.node,h);return k},image:function(a,b,c,e,g,f){var h=new d.AmDObject(\"image\",this);h.attr({x:b,y:c,width:e,height:g});this.R.path(h,a);this.addToContainer(h.node,f);return h},addToContainer:function(a,b){b||(b=this.container);b.appendChild(a)},text:function(a,b,c){return this.R.text(a,b,c)},path:function(a,b,c,e){var g=new d.AmDObject(\"path\",this);e||(e=\"100,100\");\ng.attr({cs:e});c?g.attr({dd:a}):g.attr({d:a});this.addToContainer(g.node,b);return g},set:function(a){return this.R.set(a)},remove:function(a){if(a){var b=this.rBin;b.appendChild(a);b.innerHTML=\"\"}},renderFix:function(){var a=this.container,b=a.style;b.top=\"0px\";b.left=\"0px\";try{var c=a.getBoundingClientRect(),d=c.left-Math.round(c.left),g=c.top-Math.round(c.top);d&&(b.left=d+\"px\");g&&(b.top=g+\"px\")}catch(f){}},update:function(){this.R.update()},addDefs:function(a){if(d.hasSVG){var b=this.createSvgElement(\"desc\"),\nc=this.container;c.setAttribute(\"version\",\"1.1\");c.style.position=\"absolute\";this.setSize(this.width,this.height);if(a.accessibleTitle){var e=this.createSvgElement(\"text\");c.appendChild(e);e.innerHTML=a.accessibleTitle;e.style.opacity=0}d.rtl&&(c.setAttribute(\"direction\",\"rtl\"),c.style.left=\"auto\",c.style.right=\"0px\");a&&(a.addCodeCredits&&b.appendChild(document.createTextNode(\"JavaScript chart by amCharts \"+a.version)),a.accessibleDescription&&(b.innerHTML=\"\",b.appendChild(document.createTextNode(a.accessibleDescription))),\nc.appendChild(b),a.defs&&(b=this.createSvgElement(\"defs\"),c.appendChild(b),d.parseDefs(a.defs,b),this.defs=b))}}})})();(function(){var d=window.AmCharts;d.AmDObject=d.Class({construct:function(a,b){this.D=b;this.R=b.R;this.node=this.R.create(this,a);this.y=this.x=0;this.scale=1},attr:function(a){this.R.attr(this,a);return this},getAttr:function(a){return this.node.getAttribute(a)},setAttr:function(a,b){this.R.setAttr(this,a,b);return this},clipRect:function(a,b,c,d){this.R.clipRect(this,a,b,c,d)},translate:function(a,b,c,d){d||(a=Math.round(a),b=Math.round(b));this.R.move(this,a,b,c);this.x=a;this.y=b;this.scale=\nc;this.angle&&this.rotate(this.angle)},rotate:function(a,b){this.R.rotate(this,a,b);this.angle=a},animate:function(a,b,c){for(var e in a)if(a.hasOwnProperty(e)){var g=e,f=a[e];c=d.getEffect(c);this.R.animate(this,g,f,b,c)}},push:function(a){if(a){var b=this.node;b.appendChild(a.node);var c=a.clipPath;c&&b.appendChild(c);(a=a.grad)&&b.appendChild(a)}},text:function(a){this.R.setText(this,a)},remove:function(){this.stop();this.R.remove(this)},clear:function(){var a=this.node;if(a.hasChildNodes())for(;1<=\na.childNodes.length;)a.removeChild(a.firstChild)},hide:function(){this.setAttr(\"visibility\",\"hidden\")},show:function(){this.setAttr(\"visibility\",\"visible\")},getBBox:function(){return this.R.getBBox(this)},toFront:function(){var a=this.node;if(a){this.prevNextNode=a.nextSibling;var b=a.parentNode;b&&b.appendChild(a)}},toPrevious:function(){var a=this.node;a&&this.prevNextNode&&(a=a.parentNode)&&a.insertBefore(this.prevNextNode,null)},toBack:function(){var a=this.node;if(a){this.prevNextNode=a.nextSibling;\nvar b=a.parentNode;if(b){var c=b.firstChild;c&&b.insertBefore(a,c)}}},mouseover:function(a){this.R.addListener(this,\"mouseover\",a);return this},mouseout:function(a){this.R.addListener(this,\"mouseout\",a);return this},click:function(a){this.R.addListener(this,\"click\",a);return this},dblclick:function(a){this.R.addListener(this,\"dblclick\",a);return this},mousedown:function(a){this.R.addListener(this,\"mousedown\",a);return this},mouseup:function(a){this.R.addListener(this,\"mouseup\",a);return this},touchmove:function(a){this.R.addListener(this,\n\"touchmove\",a);return this},touchstart:function(a){this.R.addListener(this,\"touchstart\",a);return this},touchend:function(a){this.R.addListener(this,\"touchend\",a);return this},keyup:function(a){this.R.addListener(this,\"keyup\",a);return this},focus:function(a){this.R.addListener(this,\"focus\",a);return this},blur:function(a){this.R.addListener(this,\"blur\",a);return this},contextmenu:function(a){this.node.addEventListener?this.node.addEventListener(\"contextmenu\",a,!0):this.R.addListener(this,\"contextmenu\",\na);return this},stop:function(){d.removeFromArray(this.R.animations,this.an_translate);d.removeFromArray(this.R.animations,this.an_y);d.removeFromArray(this.R.animations,this.an_x)},length:function(){return this.node.childNodes.length},gradient:function(a,b,c){this.R.gradient(this,a,b,c)},pattern:function(a,b,c){a&&this.R.pattern(this,a,b,c)}})})();(function(){var d=window.AmCharts;d.VMLRenderer=d.Class({construct:function(a,b){this.chart=b;this.D=a;this.cNames={circle:\"oval\",ellipse:\"oval\",rect:\"roundrect\",path:\"shape\"};this.styleMap={x:\"left\",y:\"top\",width:\"width\",height:\"height\",\"font-family\":\"fontFamily\",\"font-size\":\"fontSize\",visibility:\"visibility\"}},create:function(a,b){var c;if(\"group\"==b)c=document.createElement(\"div\"),a.type=\"div\";else if(\"text\"==b)c=document.createElement(\"div\"),a.type=\"text\";else if(\"image\"==b)c=document.createElement(\"img\"),\na.type=\"image\";else{a.type=\"shape\";a.shapeType=this.cNames[b];c=document.createElement(\"amvml:\"+this.cNames[b]);var d=document.createElement(\"amvml:stroke\");c.appendChild(d);a.stroke=d;var g=document.createElement(\"amvml:fill\");c.appendChild(g);a.fill=g;g.className=\"amvml\";d.className=\"amvml\";c.className=\"amvml\"}c.style.position=\"absolute\";c.style.top=0;c.style.left=0;return c},path:function(a,b){a.node.setAttribute(\"src\",b)},setAttr:function(a,b,c){if(void 0!==c){var e;8===document.documentMode&&\n(e=!0);var g=a.node,f=a.type,h=g.style;\"r\"==b&&(h.width=2*c,h.height=2*c);\"oval\"==a.shapeType&&(\"rx\"==b&&(h.width=2*c),\"ry\"==b&&(h.height=2*c));\"roundrect\"==a.shapeType&&(\"width\"!=b&&\"height\"!=b||--c);\"cursor\"==b&&(h.cursor=c);\"cx\"==b&&(h.left=c-d.removePx(h.width)/2);\"cy\"==b&&(h.top=c-d.removePx(h.height)/2);var k=this.styleMap[b];\"width\"==k&&0>c&&(c=0);void 0!==k&&(h[k]=c);\"text\"==f&&(\"text-anchor\"==b&&(a.anchor=c,k=g.clientWidth,\"end\"==c&&(h.marginLeft=-k+\"px\"),\"middle\"==c&&(h.marginLeft=-(k/2)+\n\"px\",h.textAlign=\"center\"),\"start\"==c&&(h.marginLeft=\"0px\")),\"fill\"==b&&(h.color=c),\"font-weight\"==b&&(h.fontWeight=c));if(h=a.children)for(k=0;kc&&(h=\"dot\"),3<=c&&6>=c&&(h=\"dash\"),6h&&(b+=h);0>k&&(c+=k)}return{x:b,y:c,width:d,height:g}},setText:function(a,b){var c=a.node;c&&(c.innerHTML=b);this.setAttr(a,\"text-anchor\",a.anchor)},addListener:function(a,b,c){a.node[\"on\"+b]=c},move:function(a,b,c){var e=a.node,g=e.style;\"text\"==a.type&&(c-=d.removePx(g.fontSize)/2-1);\"oval\"==a.shapeType&&(b-=d.removePx(g.width)/2,c-=d.removePx(g.height)/2);a=a.bw;isNaN(a)||(b-=a,c-=a);isNaN(b)||isNaN(c)||(e.style.left=b+\"px\",e.style.top=\nc+\"px\")},svgPathToVml:function(a){var b=a.split(\" \");a=\"\";var c,d=Math.round,g;for(g=0;gthis.fontSize&&(this.ly=g/2-1);0p&&(p=y);u=u.height;u>t&&(t=u)}var y=t=0,B=f,D=0,C=0;for(A=0;Aq&&0C&&(C=u.height);I.translate(H,D);y++;!isNaN(l)&&y>=l&&(y=0,t++,D=D+C+m,B=f,C=0);z.push(I)}u=z.getBBox();l=u.height+2*m-1;\"left\"==a||\"right\"==a?(n=u.width+2*f,k=n+b+c,h.style.width=k+\"px\",this.ieW=k):n=k-b-c-1;c=d.polygon(this.container,[0,n,n,0],[0,0,l,l],this.backgroundColor,this.backgroundAlpha,1,this.borderColor,this.borderAlpha);d.setCN(this.chart,\nc,\"legend-bg\");w.push(c);w.translate(b,e);c.toBack();b=f;if(\"top\"==a||\"bottom\"==a||\"absolute\"==a||\"outside\"==a)\"center\"==this.align?b=f+(n-u.width)/2:\"right\"==this.align&&(b=f+n-u.width);z.translate(b,m+1);this.titleHeight>l&&(l=this.titleHeight);e=l+e+g+1;0>e&&(e=0);\"absolute\"!=a&&\"outside\"!=a&&e>this.chart.divRealHeight&&(h.style.top=\"0px\");h.style.height=Math.round(e)+\"px\";r.setSize(this.divWidth,e)},createEntry:function(a){if(!1!==a.visibleInLegend&&!a.hideFromLegend){var b=this,c=b.chart,e=b.useGraphSettings,\ng=a.markerType;g&&(e=!1);a.legendEntryWidth=b.markerSize;g||(g=b.markerType);var f=a.color,h=a.alpha;a.legendKeyColor&&(f=a.legendKeyColor());a.legendKeyAlpha&&(h=a.legendKeyAlpha());var k;!0===a.hidden&&(k=f=b.markerDisabledColor);var l=a.pattern,m,n=a.customMarker;n||(n=b.customMarker);var q=b.container,p=b.markerSize,t=0,r=0,w=p/2;if(e){e=a.type;b.switchType=void 0;if(\"line\"==e||\"step\"==e||\"smoothedLine\"==e||\"ohlc\"==e)m=q.set(),a.hidden||(f=a.lineColorR,k=a.bulletBorderColorR),t=d.line(q,[0,2*\np],[p/2,p/2],f,a.lineAlpha,a.lineThickness,a.dashLength),d.setCN(c,t,\"graph-stroke\"),m.push(t),a.bullet&&(a.hidden||(f=a.bulletColorR),t=d.bullet(q,a.bullet,a.bulletSize,f,a.bulletAlpha,a.bulletBorderThickness,k,a.bulletBorderAlpha))&&(d.setCN(c,t,\"graph-bullet\"),t.translate(p+1,p/2),m.push(t)),w=0,t=p,r=p/3;else{a.getGradRotation&&(m=a.getGradRotation(),0===m&&(m=180));t=a.fillColorsR;!0===a.hidden&&(t=f);if(m=b.createMarker(\"rectangle\",t,a.fillAlphas,a.lineThickness,f,a.lineAlpha,m,l,a.dashLength))w=\np,m.translate(w,p/2);t=p}d.setCN(c,m,\"graph-\"+e);d.setCN(c,m,\"graph-\"+a.id)}else if(n)m=q.image(n,0,0,p,p);else{var z;isNaN(b.gradientRotation)||(z=180+b.gradientRotation);(m=b.createMarker(g,f,h,void 0,void 0,void 0,z,l))&&m.translate(p/2,p/2)}d.setCN(c,m,\"legend-marker\");b.addListeners(m,a);q=q.set([m]);b.switchable&&a.switchable&&q.setAttr(\"cursor\",\"pointer\");void 0!==a.id&&d.setCN(c,q,\"legend-item-\"+a.id);d.setCN(c,q,a.className,!0);k=b.switchType;var x;k&&\"none\"!=k&&0c&&(d=\"00\"+c);10<=c&&100>c&&(d=\"0\"+c);a=a.replace(/fff/g,d)}return a};d.extractPeriod=function(a){var b=d.stripNumbers(a),c=1;b!=a&&(c=Number(a.slice(0,a.indexOf(b))));return{period:b,count:c}};d.getDate=function(a,b,c){return a instanceof Date?d.newDate(a,c):b&&isNaN(a)?d.stringToDate(a,b):new Date(a)};d.daysInMonth=function(a){return(new Date(a.getYear(),a.getMonth()+\n1,0)).getDate()};d.newDate=function(a,b){return b&&-1==b.indexOf(\"fff\")?new Date(a):new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours(),a.getMinutes(),a.getSeconds(),a.getMilliseconds())};d.resetDateToMin=function(a,b,c,e){void 0===e&&(e=1);var g,f,h,k,l,m,n;d.useUTC?(g=a.getUTCFullYear(),f=a.getUTCMonth(),h=a.getUTCDate(),k=a.getUTCHours(),l=a.getUTCMinutes(),m=a.getUTCSeconds(),n=a.getUTCMilliseconds(),a=a.getUTCDay()):(g=a.getFullYear(),f=a.getMonth(),h=a.getDate(),k=a.getHours(),l=\na.getMinutes(),m=a.getSeconds(),n=a.getMilliseconds(),a=a.getDay());switch(b){case \"YYYY\":g=Math.floor(g/c)*c;f=0;h=1;n=m=l=k=0;break;case \"MM\":f=Math.floor(f/c)*c;h=1;n=m=l=k=0;break;case \"WW\":h=a>=e?h-a+e:h-(7+a)+e;n=m=l=k=0;break;case \"DD\":n=m=l=k=0;break;case \"hh\":k=Math.floor(k/c)*c;n=m=l=0;break;case \"mm\":l=Math.floor(l/c)*c;n=m=0;break;case \"ss\":m=Math.floor(m/c)*c;n=0;break;case \"fff\":n=Math.floor(n/c)*c}d.useUTC?(a=new Date,a.setUTCFullYear(g,f,h),a.setUTCHours(k,l,m,n)):a=new Date(g,f,h,\nk,l,m,n);return a};d.getPeriodDuration=function(a,b){void 0===b&&(b=1);var c;switch(a){case \"YYYY\":c=316224E5;break;case \"MM\":c=26784E5;break;case \"WW\":c=6048E5;break;case \"DD\":c=864E5;break;case \"hh\":c=36E5;break;case \"mm\":c=6E4;break;case \"ss\":c=1E3;break;case \"fff\":c=1}return c*b};d.intervals={s:{nextInterval:\"ss\",contains:1E3},ss:{nextInterval:\"mm\",contains:60,count:0},mm:{nextInterval:\"hh\",contains:60,count:1},hh:{nextInterval:\"DD\",contains:24,count:2},DD:{nextInterval:\"\",contains:Infinity,count:3}};\nd.getMaxInterval=function(a,b){var c=d.intervals;return a>=c[b].contains?(a=Math.round(a/c[b].contains),b=c[b].nextInterval,d.getMaxInterval(a,b)):\"ss\"==b?c[b].nextInterval:b};d.dayNames=\"Sunday Monday Tuesday Wednesday Thursday Friday Saturday\".split(\" \");d.shortDayNames=\"Sun Mon Tue Wed Thu Fri Sat\".split(\" \");d.monthNames=\"January February March April May June July August September October November December\".split(\" \");d.shortMonthNames=\"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec\".split(\" \");\nd.getWeekNumber=function(a){a=new Date(a);a.setHours(0,0,0);a.setDate(a.getDate()+4-(a.getDay()||7));var b=new Date(a.getFullYear(),0,1);return Math.ceil(((a-b)/864E5+1)/7)};d.stringToDate=function(a,b){var c={},e=[{pattern:\"YYYY\",period:\"year\"},{pattern:\"YY\",period:\"year\"},{pattern:\"MM\",period:\"month\"},{pattern:\"M\",period:\"month\"},{pattern:\"DD\",period:\"date\"},{pattern:\"D\",period:\"date\"},{pattern:\"JJ\",period:\"hours\"},{pattern:\"J\",period:\"hours\"},{pattern:\"HH\",period:\"hours\"},{pattern:\"H\",period:\"hours\"},\n{pattern:\"KK\",period:\"hours\"},{pattern:\"K\",period:\"hours\"},{pattern:\"LL\",period:\"hours\"},{pattern:\"L\",period:\"hours\"},{pattern:\"NN\",period:\"minutes\"},{pattern:\"N\",period:\"minutes\"},{pattern:\"SS\",period:\"seconds\"},{pattern:\"S\",period:\"seconds\"},{pattern:\"QQQ\",period:\"milliseconds\"},{pattern:\"QQ\",period:\"milliseconds\"},{pattern:\"Q\",period:\"milliseconds\"}],g=!0,f=b.indexOf(\"AA\");-1!=f&&(a.substr(f,2),\"pm\"==a.toLowerCase&&(g=!1));var f=b,h,k,l;for(l=0;lr&&(r=\"0\"+r);b=b.replace(/JJ/g,r);b=b.replace(/J/g,q);r=k;0===r&&(r=24,-1!=b.indexOf(\"H\")&&(f--,0===f&&(e=new Date(a),e.setDate(e.getDate()-1),g=e.getMonth(),f=e.getDate(),e=e.getFullYear())));a=g+1;9>g&&(a=\"0\"+a);q=f;10>f&&(q=\"0\"+f);var w=r;10>w&&(w=\"0\"+w);b=b.replace(/HH/g,w);b=b.replace(/H/g,r);r=k;11w&&(w=\"0\"+w);b=b.replace(/KK/g,w);b=b.replace(/K/g,r);r=k;0===r&&(r=12);12w&&(w=\"0\"+w);b=b.replace(/LL/g,w);b=b.replace(/L/g,r);\nr=l;10>r&&(r=\"0\"+r);b=b.replace(/NN/g,r);b=b.replace(/N/g,l);l=m;10>l&&(l=\"0\"+l);b=b.replace(/SS/g,l);b=b.replace(/S/g,m);m=n;10>m?m=\"00\"+m:100>m&&(m=\"0\"+m);l=n;10>l&&(l=\"00\"+l);b=b.replace(/A/g,\"@A@\");b=b.replace(/QQQ/g,m);b=b.replace(/QQ/g,l);b=b.replace(/Q/g,n);b=b.replace(/YYYY/g,\"@IIII@\");b=b.replace(/YY/g,\"@II@\");b=b.replace(/MMMM/g,\"@XXXX@\");b=b.replace(/MMM/g,\"@XXX@\");b=b.replace(/MM/g,\"@XX@\");b=b.replace(/M/g,\"@X@\");b=b.replace(/DD/g,\"@RR@\");b=b.replace(/D/g,\"@R@\");b=b.replace(/EEEE/g,\"@PPPP@\");\nb=b.replace(/EEE/g,\"@PPP@\");b=b.replace(/EE/g,\"@PP@\");b=b.replace(/E/g,\"@P@\");b=b.replace(/@IIII@/g,e);b=b.replace(/@II@/g,p);b=b.replace(/@XXXX@/g,c.monthNames[g]);b=b.replace(/@XXX@/g,c.shortMonthNames[g]);b=b.replace(/@XX@/g,a);b=b.replace(/@X@/g,g+1);b=b.replace(/@RR@/g,q);b=b.replace(/@R@/g,f);b=b.replace(/@PPPP@/g,c.dayNames[h]);b=b.replace(/@PPP@/g,c.shortDayNames[h]);b=b.replace(/@PP@/g,t);b=b.replace(/@P@/g,h);return b=12>k?b.replace(/@A@/g,c.amString):b.replace(/@A@/g,c.pmString)};d.changeDate=\nfunction(a,b,c,e,g){if(d.useUTC)return d.changeUTCDate(a,b,c,e,g);var f=-1;void 0===e&&(e=!0);void 0===g&&(g=!1);!0===e&&(f=1);switch(b){case \"YYYY\":a.setFullYear(a.getFullYear()+c*f);e||g||a.setDate(a.getDate()+1);break;case \"MM\":b=a.getMonth();var h=a.getFullYear();a.setMonth(b+c*f);var k=a.getMonth();if(e&&k-b>c)for(;a.getMonth()-b>c;)a.setDate(a.getDate()-1);h==a.getFullYear()&&a.getMonth()>b+c*f&&a.setDate(a.getDate()-1);e||g||a.setDate(a.getDate()+1);break;case \"DD\":a.setDate(a.getDate()+c*\nf);break;case \"WW\":a.setDate(a.getDate()+c*f*7);break;case \"hh\":a.setHours(a.getHours()+c*f);break;case \"mm\":a.setMinutes(a.getMinutes()+c*f);break;case \"ss\":a.setSeconds(a.getSeconds()+c*f);break;case \"fff\":a.setMilliseconds(a.getMilliseconds()+c*f)}return a};d.changeUTCDate=function(a,b,c,d,g){var f=-1;void 0===d&&(d=!0);void 0===g&&(g=!1);!0===d&&(f=1);switch(b){case \"YYYY\":a.setUTCFullYear(a.getUTCFullYear()+c*f);d||g||a.setUTCDate(a.getUTCDate()+1);break;case \"MM\":b=a.getUTCMonth();a.setUTCMonth(a.getUTCMonth()+\nc*f);a.getUTCMonth()>b+c*f&&a.setUTCDate(a.getUTCDate()-1);d||g||a.setUTCDate(a.getUTCDate()+1);break;case \"DD\":a.setUTCDate(a.getUTCDate()+c*f);break;case \"WW\":a.setUTCDate(a.getUTCDate()+c*f*7);break;case \"hh\":a.setUTCHours(a.getUTCHours()+c*f);break;case \"mm\":a.setUTCMinutes(a.getUTCMinutes()+c*f);break;case \"ss\":a.setUTCSeconds(a.getUTCSeconds()+c*f);break;case \"fff\":a.setUTCMilliseconds(a.getUTCMilliseconds()+c*f)}return a}})();\n\n(function(){var e=window.AmCharts;e.AmRectangularChart=e.Class({inherits:e.AmCoordinateChart,construct:function(a){e.AmRectangularChart.base.construct.call(this,a);this.theme=a;this.createEvents(\"zoomed\",\"changed\");this.marginRight=this.marginBottom=this.marginTop=this.marginLeft=20;this.depth3D=this.angle=0;this.plotAreaFillColors=\"#FFFFFF\";this.plotAreaFillAlphas=0;this.plotAreaBorderColor=\"#000000\";this.plotAreaBorderAlpha=0;this.maxZoomFactor=20;this.zoomOutButtonImageSize=19;this.zoomOutButtonImage=\n\"lens\";this.zoomOutText=\"Show all\";this.zoomOutButtonColor=\"#e5e5e5\";this.zoomOutButtonAlpha=0;this.zoomOutButtonRollOverAlpha=1;this.zoomOutButtonPadding=8;this.trendLines=[];this.autoMargins=!0;this.marginsUpdated=!1;this.autoMarginOffset=10;e.applyTheme(this,a,\"AmRectangularChart\")},initChart:function(){e.AmRectangularChart.base.initChart.call(this);this.updateDxy();!this.marginsUpdated&&this.autoMargins&&(this.resetMargins(),this.drawGraphs=!1);this.processScrollbars();this.updateMargins();this.updatePlotArea();\nthis.updateScrollbars();this.updateTrendLines();this.updateChartCursor();this.updateValueAxes();this.scrollbarOnly||this.updateGraphs()},drawChart:function(){e.AmRectangularChart.base.drawChart.call(this);this.drawPlotArea();if(e.ifArray(this.chartData)){var a=this.chartCursor;a&&a.draw()}},resetMargins:function(){var a={},b;if(\"xy\"==this.type){var c=this.xAxes,d=this.yAxes;for(b=0;b=g-c&&(this.marginRight=Math.round(k-g+c),!isNaN(this.minMarginRight)&&this.marginRighth-c&&(this.marginBottom=Math.round(this.marginBottom+b-h+c),!isNaN(this.minMarginBottom)&&\nthis.marginBottoma&&(d=a);break;case \"bottom\":a=h.y+h.height;ga&&(b=a)}}return{l:b,t:d,r:c,b:g}},drawZoomOutButton:function(){var a=this;if(!a.zbSet){var b=a.container.set();\na.zoomButtonSet.push(b);var c=a.color,d=a.fontSize,g=a.zoomOutButtonImageSize,h=a.zoomOutButtonImage.replace(/\\.[a-z]*$/i,\"\"),f=a.langObj.zoomOutText||a.zoomOutText,l=a.zoomOutButtonColor,k=a.zoomOutButtonAlpha,m=a.zoomOutButtonFontSize,p=a.zoomOutButtonPadding;isNaN(m)||(d=m);(m=a.zoomOutButtonFontColor)&&(c=m);var m=a.zoomOutButton,n;m&&(m.fontSize&&(d=m.fontSize),m.color&&(c=m.color),m.backgroundColor&&(l=m.backgroundColor),isNaN(m.backgroundAlpha)||(a.zoomOutButtonRollOverAlpha=m.backgroundAlpha));\nvar u=m=0,u=a.pathToImages;if(h){if(e.isAbsolute(h)||void 0===u)u=\"\";n=a.container.image(u+h+a.extension,0,0,g,g);e.setCN(a,n,\"zoom-out-image\");b.push(n);n=n.getBBox();m=n.width+5}void 0!==f&&(c=e.text(a.container,f,c,a.fontFamily,d,\"start\"),e.setCN(a,c,\"zoom-out-label\"),d=c.getBBox(),u=n?n.height/2-3:d.height/2,c.translate(m,u),b.push(c));n=b.getBBox();c=1;e.isModern||(c=0);l=e.rect(a.container,n.width+2*p+5,n.height+2*p-2,l,1,1,l,c);l.setAttr(\"opacity\",k);l.translate(-p,-p);e.setCN(a,l,\"zoom-out-bg\");\nb.push(l);l.toBack();a.zbBG=l;n=l.getBBox();b.translate(a.marginLeftReal+a.plotAreaWidth-n.width+p,a.marginTopReal+p);b.hide();b.mouseover(function(){a.rollOverZB()}).mouseout(function(){a.rollOutZB()}).click(function(){a.clickZB()}).touchstart(function(){a.rollOverZB()}).touchend(function(){a.rollOutZB();a.clickZB()});for(k=0;ka&&(a=1);1>b&&(b=1);this.plotAreaWidth=Math.round(a);this.plotAreaHeight=Math.round(b);\nthis.plotBalloonsSet.translate(c,d)},updateDxy:function(){this.dx=Math.round(this.depth3D*Math.cos(this.angle*Math.PI/180));this.dy=Math.round(-this.depth3D*Math.sin(this.angle*Math.PI/180));this.d3x=Math.round(this.columnSpacing3D*Math.cos(this.angle*Math.PI/180));this.d3y=Math.round(-this.columnSpacing3D*Math.sin(this.angle*Math.PI/180))},updateMargins:function(){var a=this.getTitleHeight();this.titleHeight=a;this.marginTopReal=this.marginTop-this.dy;this.fixMargins&&!this.fixMargins.top&&(this.marginTopReal+=\na);this.marginBottomReal=this.marginBottom;this.marginLeftReal=this.marginLeft;this.marginRightReal=this.marginRight},updateValueAxes:function(){var a=this.valueAxes,b;for(b=0;bd)var g=c,c=d,d=g;this.relativeZoomValueAxes(b,c,d);this.updateAfterValueZoom()},\nupdateAfterValueZoom:function(){this.zoomAxesAndGraphs();this.zoomScrollbar()},relativeZoomValueAxes:function(a,b,c){this.hideBalloonReal();b=e.fitToBounds(b,0,1);c=e.fitToBounds(c,0,1);if(b>c){var d=b;b=c;c=d}var d=1/this.maxZoomFactor,g=e.getDecimals(d)+4;c-bb&&(b=0,c=d));b=e.roundTo(b,g);c=e.roundTo(c,g);d=!1;if(a){for(g=0;gb.min-g*b.step&&(f+=g,g=0);0>=b.max&&0k&&(k=1);e*=k;f*=k;if(!d||c.equalSpacing)e=Math.round(e),f=Math.round(f);l=this.chartData.length;c=this.lastTime;k=this.firstTime;0>a?d?(l=this.endTime-this.startTime,d=this.startTime+e*g,g=this.endTime+f*g,0=c&&(g=c,d=c-l),this.zoomToDates(new Date(d),new Date(g))):(0=l-1&&(e=f=0),d=this.start+e,g=this.end+f,this.zoomToIndexes(d,g)):d?(l=this.endTime-this.startTime,d=this.startTime-\ne*g,g=this.endTime-f*g,0this.start&&(e=f=0),d=this.start-e,g=this.end-f,this.zoomToIndexes(d,g))}else this.handleMouseOut()}},validateData:function(a){this.marginsUpdated=!1;this.zoomOutOnDataUpdate&&!a&&(this.endTime=this.end=this.startTime=this.start=NaN);var b=a=!1,c=!1,d=this.chartScrollbar;d&&(d.dragging&&(a=!0,d.handleDragStop()),d.resizingRight&&(c=!0,d.rightDragStop()),d.resizingLeft&&(b=!0,d.leftDragStop()));\ne.AmSerialChart.base.validateData.call(this);a&&d.handleDragStart();c&&d.rightDragStart();b&&d.leftDragStart()},drawChart:function(){if(0c&&(a=b-c),a!=this.startTime&&b-a>c&&(b=a+c));var d=this.minSelectedTime;if(0l&&(a=l);bl&&(b=l);bthis.firstTime&&(a=!0),this.endTimec&&(a=b-c,d=!0),a!=this.start&&b-a>c&&(b=a+c,d=!0));if(d&&(d=this.chartScrollbar)&&d.dragger){var g=d.dragger.getBBox();\nd.maxWidth=g.width;d.maxHeight=g.height}if(a!=this.start||b!=this.end)d=this.chartData.length-1,isNaN(a)&&(a=0,isNaN(c)||(a=d-c)),isNaN(b)&&(b=d),bd&&(b=d),a>d&&(a=d-1),0>a&&(a=0),this.start=a,this.end=b,this.categoryAxis.zoom(a,b),this.zoomAxesAndGraphs(),this.zoomScrollbar(),this.fixCursor(),0!==a||b!=this.chartData.length-1?this.showZB(!0):this.showZB(!1),this.syncGrid(),this.updateColumnsDepth(),this.dispatchIndexZoomEvent()},updateGraphs:function(){e.AmSerialChart.base.updateGraphs.call(this);\nvar a=this.graphs,b;for(b=0;bb.depth?1:-1},zoomScrollbar:function(){var a=this.chartScrollbar,b=this.categoryAxis;if(a){if(!this.zoomedByScrollbar){var c=a.dragger;c&&c.stop()}this.zoomedByScrollbar=!1;b.parseDates&&!b.equalSpacing?a.timeZoom(this.startTime,\nthis.endTime):a.zoom(this.start,this.end)}this.zoomValueScrollbar(this.valueScrollbar)},updateTrendLines:function(){var a=this.trendLines,b;for(b=0;bg&&(g=0);e>a.length-1&&(e=a.length-1);var f=g+Math.round((e-g)/2),l=a[f][b];return c==l?f:1>=e-g?d?g:Math.abs(a[g][b]-c)a&&(a=0),b>d-1&&(b=d-1),d=this.categoryAxis,d.parseDates&&!d.equalSpacing?this.zoom(c[a].time,this.getEndTime(c[b].time)):this.zoom(a,\nb))}},zoomToDates:function(a,b){var c=this.chartData;if(c)if(this.categoryAxis.equalSpacing){var d=this.getClosestIndex(c,\"time\",a.getTime(),!0,0,c.length);b=e.resetDateToMin(b,this.categoryAxis.minPeriod,1);c=this.getClosestIndex(c,\"time\",b.getTime(),!1,0,c.length);this.zoom(d,c)}else this.zoom(a.getTime(),b.getTime())},zoomToCategoryValues:function(a,b){this.chartData&&this.zoom(this.getCategoryIndexByValue(a),this.getCategoryIndexByValue(b))},formatPeriodString:function(a,b){if(b){b.periodDataItem=\n{};b.periodPercentDataItem={};var c=[\"value\",\"open\",\"low\",\"high\",\"close\"],d=\"value open low high close average sum count\".split(\" \"),g=b.valueAxis,h=this.chartData,f=b.numberFormatter;f||(f=this.nf);for(var l=0;lD||D>A.graph.height)z=NaN}else if(0>D||D>A.graph.width)z=NaN;if(!isNaN(z)){isNaN(v)&&\n(v=z);x=z;if(isNaN(E)||E>z)E=z;if(isNaN(t)||tA)w=A;if(isNaN(y)||yb&&0===p&&(p=180):0>c&&270==p&&(p=90);this.gradientRotation=p;0===d&&0===e&&(this.cornerRadius=n);this.draw()},draw:function(){var a=this.set;a.clear();\nvar b=this.container,c=b.chart,d=this.w,g=this.h,h=this.dx,f=this.dy,l=this.colors,k=this.alpha,m=this.bwidth,p=this.bcolor,n=this.balpha,u=this.gradientRotation,v=this.cornerRadius,x=this.dashLength,E=this.pattern,t=this.topRadius,r=this.bcn,B=l,q=l;\"object\"==typeof l&&(B=l[0],q=l[l.length-1]);var w,y,C,F,D,A,z,L,M,Q=k;E&&(k=0);var G,H,I,J,K=this.rotate;if(0Math.abs(g)&&(g=0);1>Math.abs(d)&&(d=0);!isNaN(t)&&(0g&&(m=\" A\"),k+=m+Math.round(d/2-I)+\",\"+Math.round(g-J)+\",\"+Math.round(d/2+I)+\",\"+Math.round(g+J)+\",0,\"+g+\",\"+d+\",\"+g,k+=\" L\"+d+\",0\",k+=m+Math.round(d/\n2+G)+\",\"+Math.round(H)+\",\"+Math.round(d/2-G)+\",\"+Math.round(-H)+\",\"+d+\",0,0,0\"):(k+=\"A\"+I+\",\"+J+\",0,0,0,\"+(d-d/2*(1-t))+\",\"+g+\"L\"+d+\",0\",k+=\"A\"+G+\",\"+H+\",0,0,1,0,0\"),G=180),b=b.path(k).attr(l),b.gradient(\"linearGradient\",[B,e.adjustLuminosity(B,-.3),e.adjustLuminosity(B,-.3),B],G),K?b.translate(h/2,0):b.translate(0,f/2)):b=0===g?e.line(b,[0,d],[0,0],p,n,m,x):0===d?e.line(b,[0,0],[0,g],p,n,m,x):0g?[w,\nM,y,C,F,D,A,z,L,b]:[z,L,y,C,F,D,w,M,A,b]:K?0g?[w,b,z]:[z,b,w];e.setCN(c,b,r+\"front\");e.setCN(c,y,r+\"back\");e.setCN(c,z,r+\"top\");e.setCN(c,w,r+\"bottom\");e.setCN(c,F,r+\"left\");e.setCN(c,D,r+\"right\");for(w=0;wb&&(this.endTime=b);r=this.minorGridEnabled;x=this.gridAlpha;var y=0,C=0;if(this.widthField)for(b=this.start;b<=this.end;b++)if(t=this.data[b]){var F=Number(this.data[b].dataContext[this.widthField]);isNaN(F)||(y+=F,t.widthValue=F)}if(this.parseDates&&!this.equalSpacing)this.lastTime=a[a.length-1].time,this.maxTime=e.resetDateToMin(new Date(this.lastTime+1.05*u),this.minPeriod,\n1,q).getTime(),this.timeDifference=this.endTime-this.startTime,this.parseDatesDraw();else if(!this.parseDates){if(this.cellWidth=this.getStepWidth(f),ff&&(f=0),w=0,this.widthField&&(f=this.start,q=1),this.end-f+1>=this.autoRotateCount&&(this.labelRotationR=this.autoRotateAngle),b=f;b<=this.end+2;b++){l=!1;0<=b&&bthis.end&&\"start\"==this.tickPosition&&(n=\" \");this.rotate&&this.inside&&(l-=2);isNaN(v.widthValue)||(v.percentWidthValue=v.widthValue/y*100,a=this.rotate?this.height*v.widthValue/y:this.width*v.widthValue/y,f=C,C+=a,E=l=a/2);p=new this.axisItemRenderer(this,f,n,p,a,l,void 0,u,E,!1,v.labelColor,v.className);p.serialDataItem=\nv;this.pushAxisItem(p);this.gridAlpha=x}}else if(this.parseDates&&this.equalSpacing){h=this.start;this.startTime=this.data[this.start].time;this.endTime=this.data[this.end].time;this.timeDifference=this.endTime-this.startTime;b=this.choosePeriod(0);g=b.period;v=b.count;b=e.getPeriodDuration(g,v);bf&&(f=0);C=this.end+2;C>=this.data.length&&(C=this.data.length);a=!1;a=!k;this.previousPos=-1E3;20=F){f=this.getCoordinate(b-this.start);r=!1;this.nextPeriod[x]&&(r=this.checkPeriodChange(this.nextPeriod[x],1,t,n,x))&&e.resetDateToMin(new Date(t),this.nextPeriod[x],1,q).getTime()!=t&&(r=!1);u=!1;r&&this.markPeriodChange?(r=this.dateFormatsObject[this.nextPeriod[x]],u=!0):r=this.dateFormatsObject[x];n=e.formatDate(new Date(t),r,c);if(b==d&&!k||b==\nl&&!m)n=\" \";a?a=!1:(w||(u=!1),f-this.previousPos>this.safeDistance*Math.cos(this.labelRotationR*Math.PI/180)&&(this.labelFunction&&(n=this.labelFunction(n,new Date(t),this,g,v,E)),this.boldLabels&&(u=!0),p=new this.axisItemRenderer(this,f,n,void 0,void 0,void 0,void 0,u),r=p.graphics(),this.pushAxisItem(p),r=r.getBBox().width,e.isModern||(r-=f),this.previousPos=f+r));E=n=t}}for(b=k=0;bthis.height+1&&h--:l>this.width+1&&\nh--;0>l&&h++;return h=e.fitToBounds(h,0,b.length-1)},dateToCoordinate:function(a){return this.parseDates&&!this.equalSpacing?(a.getTime()-this.startTime)*this.stepWidth:this.parseDates&&this.equalSpacing?(a=this.chart.getClosestIndex(this.data,\"time\",a.getTime(),!1,0,this.data.length-1),this.getCoordinate(a-this.start)):NaN},categoryToCoordinate:function(a){if(this.chart){if(this.parseDates)return this.dateToCoordinate(new Date(a));a=this.chart.getCategoryIndexByValue(a);if(!isNaN(a))return this.getCoordinate(a-\nthis.start)}else return NaN},coordinateToDate:function(a){return this.equalSpacing?(a=this.xToIndex(a),new Date(this.data[a].time)):new Date(this.startTime+a/this.stepWidth)},coordinateToValue:function(a){a=this.xToIndex(a);if(a=this.data[a])return this.parseDates?a.time:a.category},getCoordinate:function(a){a*=this.stepWidth;this.startOnAxis||(a+=this.stepWidth/2);return Math.round(a)},formatValue:function(a,b){b||(b=this.currentDateFormat);this.parseDates&&(a=e.formatDate(new Date(a),b,this.chart));\nreturn a},showBalloonAt:function(a,b){void 0===b&&(b=this.parseDates?this.dateToCoordinate(new Date(a)):this.categoryToCoordinate(a));return this.adjustBalloonCoordinate(b)},formatBalloonText:function(a,b,c){var d=\"\",g=\"\",h=this.chart,f=this.data[b];if(f)if(this.parseDates)d=e.formatDate(f.category,c,h),b=e.changeDate(new Date(f.category),this.minPeriod,1),g=e.formatDate(b,c,h),-1!=d.indexOf(\"fff\")&&(d=e.formatMilliseconds(d,f.category),g=e.formatMilliseconds(g,b));else{var l;this.data[b+1]&&(l=this.data[b+\n1]);d=e.fixNewLines(f.category);l&&(g=e.fixNewLines(l.category))}a=a.replace(/\\[\\[category\\]\\]/g,String(d));return a=a.replace(/\\[\\[toCategory\\]\\]/g,String(g))},adjustBalloonCoordinate:function(a,b){var c=this.xToIndex(a),d=this.chart.chartCursor;if(this.stickBalloonToCategory){var e=this.data[c];e&&(a=e.x[this.id]);this.stickBalloonToStart&&(a-=this.cellWidth/2);var h=0;if(d){var f=d.limitToGraph;if(f){var l=f.valueAxis.id;f.hidden||(h=e.axes[l].graphs[f.id].y)}this.rotate?(\"left\"==this.position?\n(f&&(h-=d.width),0h&&(h=0),d.fixHLine(a,h)):(\"top\"==this.position?(f&&(h-=d.height),0h&&(h=0),d.fullWidth&&(a+=1),d.fixVLine(a,h))}}d&&!b&&(d.setIndex(c),this.parseDates&&d.setTimestamp(this.coordinateToDate(a).getTime()));return a}})})();\n\n(function(){var k=window.AmCharts;k.AmSlicedChart=k.Class({inherits:k.AmChart,construct:function(a){this.createEvents(\"rollOverSlice\",\"rollOutSlice\",\"clickSlice\",\"pullOutSlice\",\"pullInSlice\",\"rightClickSlice\");k.AmSlicedChart.base.construct.call(this,a);this.colors=\"#FF0F00 #FF6600 #FF9E01 #FCD202 #F8FF01 #B0DE09 #04D215 #0D8ECF #0D52D1 #2A0CD0 #8A0CCF #CD0D74 #754DEB #DDDDDD #999999 #333333 #000000 #57032A #CA9726 #990000 #4B0C25\".split(\" \");this.alpha=1;this.groupPercent=0;this.groupedTitle=\"Other\";\nthis.groupedPulled=!1;this.groupedAlpha=1;this.marginLeft=0;this.marginBottom=this.marginTop=10;this.marginRight=0;this.hoverAlpha=1;this.outlineColor=\"#FFFFFF\";this.outlineAlpha=0;this.outlineThickness=1;this.startAlpha=0;this.startDuration=1;this.startEffect=\"bounce\";this.sequencedAnimation=!0;this.pullOutDuration=1;this.pullOutEffect=\"bounce\";this.pullOnHover=this.pullOutOnlyOne=!1;this.labelsEnabled=!0;this.labelTickColor=\"#000000\";this.labelTickAlpha=.2;this.hideLabelsPercent=0;this.urlTarget=\n\"_self\";this.autoMarginOffset=10;this.gradientRatio=[];this.maxLabelWidth=200;this.accessibleLabel=\"[[title]]: [[percents]]% [[value]] [[description]]\";k.applyTheme(this,a,\"AmSlicedChart\")},initChart:function(){k.AmSlicedChart.base.initChart.call(this);this.dataChanged&&(this.parseData(),this.dispatchDataUpdated=!0,this.dataChanged=!1,this.setLegendData(this.chartData));this.drawChart()},handleLegendEvent:function(a){var b=a.type,c=a.dataItem,d=this.legend;if(c.wedge&&c){var g=c.hidden;a=a.event;\nswitch(b){case \"clickMarker\":g||d.switchable||this.clickSlice(c,a);break;case \"clickLabel\":g||this.clickSlice(c,a,!1);break;case \"rollOverItem\":g||this.rollOverSlice(c,!1,a);break;case \"rollOutItem\":g||this.rollOutSlice(c,a);break;case \"hideItem\":this.hideSlice(c,a);break;case \"showItem\":this.showSlice(c,a)}}},invalidateVisibility:function(){this.recalculatePercents();this.initChart();var a=this.legend;a&&a.invalidateSize()},addEventListeners:function(a,b){var c=this;a.mouseover(function(a){c.rollOverSlice(b,\n!0,a)}).mouseout(function(a){c.rollOutSlice(b,a)}).touchend(function(a){c.rollOverSlice(b,a)}).mouseup(function(a){c.clickSlice(b,a)}).contextmenu(function(a){c.handleRightClick(b,a)}).focus(function(a){c.rollOverSlice(b,a)}).blur(function(a){c.rollOutSlice(b,a)})},formatString:function(a,b,c){a=k.formatValue(a,b,[\"value\"],this.nf,\"\",this.usePrefixes,this.prefixesOfSmallNumbers,this.prefixesOfBigNumbers);var d=this.pf.precision;isNaN(this.tempPrec)||(this.pf.precision=this.tempPrec);a=k.formatValue(a,\nb,[\"percents\"],this.pf);a=k.massReplace(a,{\"[[title]]\":b.title,\"[[description]]\":b.description});this.pf.precision=d;-1!=a.indexOf(\"[[\")&&(a=k.formatDataContextValue(a,b.dataContext));a=c?k.fixNewLines(a):k.fixBrakes(a);return a=k.cleanFromEmpty(a)},startSlices:function(){var a;for(a=0;athis.hoverAlpha&&a.wedge&&a.wedge.attr({opacity:this.hoverAlpha});var d=a.balloonX,g=a.balloonY;a.pulled&&(d+=a.pullX,g+=a.pullY);var f=this.formatString(this.balloonText,a,!0),h=this.balloonFunction;h&&(f=h(a,f));h=k.adjustLuminosity(a.color,-.15);f?this.showBalloon(f,h,b,d,g):this.hideBalloon();0===a.value&&this.hideBalloon();this.fire({type:\"rollOverSlice\",\ndataItem:a,chart:this,event:c})}},rollOutSlice:function(a,b){isNaN(a)||(a=this.chartData[a]);a.wedge&&a.wedge.attr({opacity:1});this.hideBalloon();this.fire({type:\"rollOutSlice\",dataItem:a,chart:this,event:b})},clickSlice:function(a,b,c){this.checkTouchDuration(b)&&(isNaN(a)||(a=this.chartData[a]),a.pulled?this.pullSlice(a,0):this.pullSlice(a,1),k.getURL(a.url,this.urlTarget),c||this.fire({type:\"clickSlice\",dataItem:a,chart:this,event:b}))},handleRightClick:function(a,b){isNaN(a)||(a=this.chartData[a]);\nthis.fire({type:\"rightClickSlice\",dataItem:a,chart:this,event:b})},drawTicks:function(){var a=this.chartData,b;for(b=0;bb&&(b=g);d.remove()}return b}})})();(function(){var k=window.AmCharts;k.AmPieChart=k.Class({inherits:k.AmSlicedChart,construct:function(a){this.type=\"pie\";k.AmPieChart.base.construct.call(this,a);this.cname=\"AmPieChart\";this.pieBrightnessStep=30;this.minRadius=10;this.depth3D=0;this.startAngle=90;this.angle=this.innerRadius=0;this.startRadius=\"500%\";this.pullOutRadius=\"20%\";this.labelRadius=20;this.labelText=\"[[title]]: [[percents]]%\";this.balloonText=\"[[title]]: [[percents]]% ([[value]])\\n[[description]]\";this.previousScale=1;this.adjustPrecision=\n!1;this.gradientType=\"radial\";k.applyTheme(this,a,this.cname)},drawChart:function(){k.AmPieChart.base.drawChart.call(this);var a=this.chartData;if(k.ifArray(a)){if(0this.maxLabelWidth&&(q=this.maxLabelWidth);this.labelText&&this.labelsEnabled||(w=q=0);A=void 0===this.pieX?(d-h-e)/2+h:f(this.pieX,this.realWidth);B=void 0===this.pieY?(g-z-n)/2+z:f(this.pieY,g);m=f(this.radius,d,g);m||(d=0<=w?d-h-e-2*q:d-h-e,g=g-z-n,m=Math.min(d,g),gd&&(m=d)),g=k.toCoordinate(this.pullOutRadius,m),m=(0<=w?m-1.8*(w+g):m-1.8*g)/2);m=m&&(f=m-1);n=k.fitToBounds(this.startAngle,0,360);0=this.hideLabelsPercent){var l=n+r/2;0>l&&(l+=360);360t&&(e.skipTick=!0));var r=A+q*(m+t),D=B+C*(m+t),x,v=0;isNaN(E)&&350=l&&0<=l?(y=0,x=\"start\",v=8):90<=l&&180>l?(y=1,\nx=\"start\",v=8):180<=l&&270>l?(y=2,x=\"end\",v=-8):270<=l&&354>=l?(y=3,x=\"end\",v=-8):354<=l&&(h>E?(y=0,x=\"start\",v=8):(y=3,x=\"end\",v=-8));e.labelQuarter=y}else x=\"middle\";l=this.formatString(this.labelText,e);(t=this.labelFunction)&&(l=t(e,l));t=e.labelColor;t||(t=this.color);\"\"!==l&&(l=k.wrappedText(c,l,t,this.fontFamily,this.fontSize,x,!1,this.maxLabelWidth),k.setCN(this,l,\"pie-label\"),k.setCN(this,l,e.className,!0),l.translate(r+1.5*v,D),0>w&&(l.node.style.pointerEvents=\"none\"),l.node.style.cursor=\n\"default\",e.ty=D,e.textX=r+1.5*v,u.push(l),this.axesSet.push(u),e.labelSet=u,e.label=l,this.addEventListeners(u,e));e.tx=r;e.tx2=r+v;e.tx0=A+q*m;e.ty0=B+C*m}r=f+(m-f)/2;e.pulled&&(r+=g);this.accessible&&this.accessibleLabel&&(D=this.formatString(this.accessibleLabel,e),this.makeAccessible(p,D));void 0!==this.tabIndex&&p.setAttr(\"tabindex\",this.tabIndex);e.balloonX=q*r+A;e.balloonY=C*r+B;e.startX=Math.round(q*z);e.startY=Math.round(C*z);e.pullX=Math.round(q*g);e.pullY=Math.round(C*g);this.graphsSet.push(p);\nif(0===e.alpha||0c?d.toFront():180<=c&&d.toBack()}},arrangeLabels:function(){var a=\nthis.chartData,b=a.length,c,d;for(d=b-1;0<=d;d--)c=a[d],0!==c.labelQuarter||c.hidden||this.checkOverlapping(d,c,0,!0,0);for(d=0;dg&&isNaN(b.labelRadius)&&(f=b.ty+3*b.iy,b.ty=f,n.translate(b.textX,f),this.checkOverlapping(a,b,c,d,g+1))}},checkOverlappingReal:function(a,b,c){var d=!1,g=a.label,f=b.label;a.labelQuarter!=c||a.hidden||b.hidden||!f||(g=g.getBBox(),c={},c.width=g.width,c.height=g.height,c.y=a.ty,c.x=a.tx,a=f.getBBox(),f={},f.width=a.width,f.height=a.height,f.y=\nb.ty,f.x=b.tx,k.hitTest(c,f)&&(d=!0));return d}})})();\n\n/* @preserve\n * The MIT License (MIT)\n * \n * Copyright (c) 2013-2018 Petka Antonov\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n * \n */\n/**\n * bluebird build version 3.7.1\n * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each\n*/\n!function(t){if(\"object\"==typeof exports&&\"undefined\"!=typeof module)module.exports=t();else if(\"function\"==typeof define&&define.amd)define([],t);else{var e;\"undefined\"!=typeof window?e=window:\"undefined\"!=typeof global?e=global:\"undefined\"!=typeof self&&(e=self),e.Promise=t()}}(function(){var t,e,n;return function r(t,e,n){function i(s,a){if(!e[s]){if(!t[s]){var c=\"function\"==typeof _dereq_&&_dereq_;if(!a&&c)return c(s,!0);if(o)return o(s,!0);var u=new Error(\"Cannot find module '\"+s+\"'\");throw u.code=\"MODULE_NOT_FOUND\",u}var l=e[s]={exports:{}};t[s][0].call(l.exports,function(e){var n=t[s][1][e];return i(n?n:e)},l,l.exports,r,t,e,n)}return e[s].exports}for(var o=\"function\"==typeof _dereq_&&_dereq_,s=0;s0;)c(t)}function c(t){var e=t.shift();if(\"function\"!=typeof e)e._settlePromises();else{var n=t.shift(),r=t.shift();e.call(n,r)}}var u;try{throw new Error}catch(l){u=l}var p=t(\"./schedule\"),f=t(\"./queue\");r.prototype.setScheduler=function(t){var e=this._schedule;return this._schedule=t,this._customScheduler=!0,e},r.prototype.hasCustomScheduler=function(){return this._customScheduler},r.prototype.haveItemsQueued=function(){return this._isTickUsed||this._haveDrainedQueues},r.prototype.fatalError=function(t,e){e?(process.stderr.write(\"Fatal \"+(t instanceof Error?t.stack:t)+\"\\n\"),process.exit(2)):this.throwLater(t)},r.prototype.throwLater=function(t,e){if(1===arguments.length&&(e=t,t=function(){throw e}),\"undefined\"!=typeof setTimeout)setTimeout(function(){t(e)},0);else try{this._schedule(function(){t(e)})}catch(n){throw new Error(\"No async scheduler available\\n\\n See http://goo.gl/MqrFmX\\n\")}},r.prototype.invokeLater=i,r.prototype.invoke=o,r.prototype.settlePromises=s,r.prototype._drainQueues=function(){a(this._normalQueue),this._reset(),this._haveDrainedQueues=!0,a(this._lateQueue)},r.prototype._queueTick=function(){this._isTickUsed||(this._isTickUsed=!0,this._schedule(this.drainQueues))},r.prototype._reset=function(){this._isTickUsed=!1},e.exports=r,e.exports.firstLineError=u},{\"./queue\":26,\"./schedule\":29}],3:[function(t,e,n){\"use strict\";e.exports=function(t,e,n,r){var i=!1,o=function(t,e){this._reject(e)},s=function(t,e){e.promiseRejectionQueued=!0,e.bindingPromise._then(o,o,null,this,t)},a=function(t,e){0===(50397184&this._bitField)&&this._resolveCallback(e.target)},c=function(t,e){e.promiseRejectionQueued||this._reject(t)};t.prototype.bind=function(o){i||(i=!0,t.prototype._propagateFrom=r.propagateFromFunction(),t.prototype._boundValue=r.boundValueFunction());var u=n(o),l=new t(e);l._propagateFrom(this,1);var p=this._target();if(l._setBoundTo(u),u instanceof t){var f={promiseRejectionQueued:!1,promise:l,target:p,bindingPromise:u};p._then(e,s,void 0,l,f),u._then(a,c,void 0,l,f),l._setOnCancel(u)}else l._resolveCallback(p);return l},t.prototype._setBoundTo=function(t){void 0!==t?(this._bitField=2097152|this._bitField,this._boundTo=t):this._bitField=-2097153&this._bitField},t.prototype._isBound=function(){return 2097152===(2097152&this._bitField)},t.bind=function(e,n){return t.resolve(n).bind(e)}}},{}],4:[function(t,e,n){\"use strict\";function r(){try{Promise===o&&(Promise=i)}catch(t){}return o}var i;\"undefined\"!=typeof Promise&&(i=Promise);var o=t(\"./promise\")();o.noConflict=r,e.exports=o},{\"./promise\":22}],5:[function(t,e,n){\"use strict\";var r=Object.create;if(r){var i=r(null),o=r(null);i[\" size\"]=o[\" size\"]=0}e.exports=function(e){function n(t,n){var r;if(null!=t&&(r=t[n]),\"function\"!=typeof r){var i=\"Object \"+a.classString(t)+\" has no method '\"+a.toString(n)+\"'\";throw new e.TypeError(i)}return r}function r(t){var e=this.pop(),r=n(t,e);return r.apply(t,this)}function i(t){return t[this]}function o(t){var e=+this;return 0>e&&(e=Math.max(0,e+t.length)),t[e]}var s,a=t(\"./util\"),c=a.canEvaluate;a.isIdentifier;e.prototype.call=function(t){var e=[].slice.call(arguments,1);return e.push(t),this._then(r,void 0,void 0,e,void 0)},e.prototype.get=function(t){var e,n=\"number\"==typeof t;if(n)e=o;else if(c){var r=s(t);e=null!==r?r:i}else e=i;return this._then(e,void 0,void 0,t,void 0)}}},{\"./util\":36}],6:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i){var o=t(\"./util\"),s=o.tryCatch,a=o.errorObj,c=e._async;e.prototype[\"break\"]=e.prototype.cancel=function(){if(!i.cancellation())return this._warn(\"cancellation is disabled\");for(var t=this,e=t;t._isCancellable();){if(!t._cancelBy(e)){e._isFollowing()?e._followee().cancel():e._cancelBranched();break}var n=t._cancellationParent;if(null==n||!n._isCancellable()){t._isFollowing()?t._followee().cancel():t._cancelBranched();break}t._isFollowing()&&t._followee().cancel(),t._setWillBeCancelled(),e=t,t=n}},e.prototype._branchHasCancelled=function(){this._branchesRemainingToCancel--},e.prototype._enoughBranchesHaveCancelled=function(){return void 0===this._branchesRemainingToCancel||this._branchesRemainingToCancel<=0},e.prototype._cancelBy=function(t){return t===this?(this._branchesRemainingToCancel=0,this._invokeOnCancel(),!0):(this._branchHasCancelled(),this._enoughBranchesHaveCancelled()?(this._invokeOnCancel(),!0):!1)},e.prototype._cancelBranched=function(){this._enoughBranchesHaveCancelled()&&this._cancel()},e.prototype._cancel=function(){this._isCancellable()&&(this._setCancelled(),c.invoke(this._cancelPromises,this,void 0))},e.prototype._cancelPromises=function(){this._length()>0&&this._settlePromises()},e.prototype._unsetOnCancel=function(){this._onCancelField=void 0},e.prototype._isCancellable=function(){return this.isPending()&&!this._isCancelled()},e.prototype.isCancellable=function(){return this.isPending()&&!this.isCancelled()},e.prototype._doInvokeOnCancel=function(t,e){if(o.isArray(t))for(var n=0;n=0?o[t]:void 0}var i=!1,o=[];return t.prototype._promiseCreated=function(){},t.prototype._pushContext=function(){},t.prototype._popContext=function(){return null},t._peekContext=t.prototype._peekContext=function(){},e.prototype._pushContext=function(){void 0!==this._trace&&(this._trace._promiseCreated=null,o.push(this._trace))},e.prototype._popContext=function(){if(void 0!==this._trace){var t=o.pop(),e=t._promiseCreated;return t._promiseCreated=null,e}return null},e.CapturedTrace=null,e.create=n,e.deactivateLongStackTraces=function(){},e.activateLongStackTraces=function(){var n=t.prototype._pushContext,o=t.prototype._popContext,s=t._peekContext,a=t.prototype._peekContext,c=t.prototype._promiseCreated;e.deactivateLongStackTraces=function(){t.prototype._pushContext=n,t.prototype._popContext=o,t._peekContext=s,t.prototype._peekContext=a,t.prototype._promiseCreated=c,i=!1},i=!0,t.prototype._pushContext=e.prototype._pushContext,t.prototype._popContext=e.prototype._popContext,t._peekContext=t.prototype._peekContext=r,t.prototype._promiseCreated=function(){var t=this._peekContext();t&&null==t._promiseCreated&&(t._promiseCreated=this)}},e}},{}],9:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i){function o(t,e){return{promise:e}}function s(){return!1}function a(t,e,n){var r=this;try{t(e,n,function(t){if(\"function\"!=typeof t)throw new TypeError(\"onCancel must be a function, got: \"+B.toString(t));r._attachCancellationCallback(t)})}catch(i){return i}}function c(t){if(!this._isCancellable())return this;var e=this._onCancel();void 0!==e?B.isArray(e)?e.push(t):this._setOnCancel([e,t]):this._setOnCancel(t)}function u(){return this._onCancelField}function l(t){this._onCancelField=t}function p(){this._cancellationParent=void 0,this._onCancelField=void 0}function f(t,e){if(0!==(1&e)){this._cancellationParent=t;var n=t._branchesRemainingToCancel;void 0===n&&(n=0),t._branchesRemainingToCancel=n+1}0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function h(t,e){0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function _(){var t=this._boundTo;return void 0!==t&&t instanceof e?t.isFulfilled()?t.value():void 0:t}function d(){this._trace=new V(this._peekContext())}function v(t,e){if(q(t)){var n=this._trace;if(void 0!==n&&e&&(n=n._parent),void 0!==n)n.attachExtraTrace(t);else if(!t.__stackCleaned__){var r=F(t);B.notEnumerableProp(t,\"stack\",r.message+\"\\n\"+r.stack.join(\"\\n\")),B.notEnumerableProp(t,\"__stackCleaned__\",!0)}}}function y(){this._trace=void 0}function g(t,e,n,r,i){if(void 0===t&&null!==e&&Z){if(void 0!==i&&i._returnedNonUndefined())return;if(0===(65535&r._bitField))return;n&&(n+=\" \");var o=\"\",s=\"\";if(e._trace){for(var a=e._trace.stack.split(\"\\n\"),c=k(a),u=c.length-1;u>=0;--u){var l=c[u];if(!Q.test(l)){var p=l.match(G);p&&(o=\"at \"+p[1]+\":\"+p[2]+\":\"+p[3]+\" \");break}}if(c.length>0)for(var f=c[0],u=0;u0&&(s=\"\\n\"+a[u-1]);break}}var h=\"a promise was created in a \"+n+\"handler \"+o+\"but was not returned from it, see http://goo.gl/rRqMUw\"+s;r._warn(h,!0,e)}}function m(t,e){var n=t+\" is deprecated and will be removed in a future version.\";return e&&(n+=\" Use \"+e+\" instead.\"),b(n)}function b(t,n,r){if(lt.warnings){var i,o=new U(t);if(n)r._attachExtraTrace(o);else if(lt.longStackTraces&&(i=e._peekContext()))i.attachExtraTrace(o);else{var s=F(o);o.stack=s.message+\"\\n\"+s.stack.join(\"\\n\")}ot(\"warning\",o)||x(o,\"\",!0)}}function w(t,e){for(var n=0;n=0;--a)if(r[a]===o){s=a;break}for(var a=s;a>=0;--a){var c=r[a];if(e[i]!==c)break;e.pop(),i--}e=r}}function k(t){for(var e=[],n=0;n0&&\"SyntaxError\"!=t.name&&(e=e.slice(n)),e}function F(t){var e=t.stack,n=t.toString();return e=\"string\"==typeof e&&e.length>0?E(t):[\" (No stack trace)\"],{message:n,stack:\"SyntaxError\"==t.name?e:k(e)}}function x(t,e,n){if(\"undefined\"!=typeof console){var r;if(B.isObject(t)){var i=t.stack;r=e+z(i,t)}else r=e+String(t);\"function\"==typeof I?I(r,n):(\"function\"==typeof console.log||\"object\"==typeof console.log)&&console.log(r)}}function T(t,e,n,r){var i=!1;try{\"function\"==typeof e&&(i=!0,\"rejectionHandled\"===t?e(r):e(n,r))}catch(o){N.throwLater(o)}\"unhandledRejection\"===t?ot(t,n,r)||i||x(n,\"Unhandled rejection \"):ot(t,r)}function P(t){var e;if(\"function\"==typeof t)e=\"[function \"+(t.name||\"anonymous\")+\"]\";else{e=t&&\"function\"==typeof t.toString?t.toString():B.toString(t);var n=/\\[object [a-zA-Z0-9$_]+\\]/;if(n.test(e))try{var r=JSON.stringify(t);e=r}catch(i){}0===e.length&&(e=\"(empty array)\")}return\"(<\"+R(e)+\">, no stack trace)\"}function R(t){var e=41;return t.lengths||0>a||!n||!r||n!==r||s>=a||(at=function(t){if($.test(t))return!0;var e=O(t);return e&&e.fileName===n&&s<=e.line&&e.line<=a?!0:!1})}}function V(t){this._parent=t,this._promisesCreated=0;var e=this._length=1+(void 0===t?0:t._length);ut(this,V),e>32&&this.uncycle()}var H,D,I,L,N=e._async,U=t(\"./errors\").Warning,B=t(\"./util\"),M=t(\"./es5\"),q=B.canAttachTrace,$=/[\\\\\\/]bluebird[\\\\\\/]js[\\\\\\/](release|debug|instrumented)/,Q=/\\((?:timers\\.js):\\d+:\\d+\\)/,G=/[\\/<\\(](.+?):(\\d+):(\\d+)\\)?\\s*$/,W=null,z=null,X=!1,K=!(0==B.env(\"BLUEBIRD_DEBUG\")||!B.env(\"BLUEBIRD_DEBUG\")&&\"development\"!==B.env(\"NODE_ENV\")),J=!(0==B.env(\"BLUEBIRD_WARNINGS\")||!K&&!B.env(\"BLUEBIRD_WARNINGS\")),Y=!(0==B.env(\"BLUEBIRD_LONG_STACK_TRACES\")||!K&&!B.env(\"BLUEBIRD_LONG_STACK_TRACES\")),Z=0!=B.env(\"BLUEBIRD_W_FORGOTTEN_RETURN\")&&(J||!!B.env(\"BLUEBIRD_W_FORGOTTEN_RETURN\"));!function(){function t(){for(var t=0;t0},e.prototype._setRejectionIsUnhandled=function(){this._bitField=1048576|this._bitField},e.prototype._unsetRejectionIsUnhandled=function(){this._bitField=-1048577&this._bitField,this._isUnhandledRejectionNotified()&&(this._unsetUnhandledRejectionIsNotified(),this._notifyUnhandledRejectionIsHandled())},e.prototype._isRejectionUnhandled=function(){return(1048576&this._bitField)>0},e.prototype._warn=function(t,e,n){return b(t,e,n||this)},e.onPossiblyUnhandledRejection=function(t){var n=e._getContext();D=B.contextBind(n,t)},e.onUnhandledRejectionHandled=function(t){var n=e._getContext();H=B.contextBind(n,t)};var tt=function(){};e.longStackTraces=function(){if(N.haveItemsQueued()&&!lt.longStackTraces)throw new Error(\"cannot enable long stack traces after promises have been created\\n\\n See http://goo.gl/MqrFmX\\n\");if(!lt.longStackTraces&&S()){var t=e.prototype._captureStackTrace,r=e.prototype._attachExtraTrace,i=e.prototype._dereferenceTrace;lt.longStackTraces=!0,tt=function(){if(N.haveItemsQueued()&&!lt.longStackTraces)throw new Error(\"cannot enable long stack traces after promises have been created\\n\\n See http://goo.gl/MqrFmX\\n\");e.prototype._captureStackTrace=t,e.prototype._attachExtraTrace=r,e.prototype._dereferenceTrace=i,n.deactivateLongStackTraces(),lt.longStackTraces=!1},e.prototype._captureStackTrace=d,e.prototype._attachExtraTrace=v,e.prototype._dereferenceTrace=y,n.activateLongStackTraces()}},e.hasLongStackTraces=function(){return lt.longStackTraces&&S()};var et={unhandledrejection:{before:function(){var t=B.global.onunhandledrejection;return B.global.onunhandledrejection=null,t},after:function(t){B.global.onunhandledrejection=t}},rejectionhandled:{before:function(){var t=B.global.onrejectionhandled;return B.global.onrejectionhandled=null,t},after:function(t){B.global.onrejectionhandled=t}}},nt=function(){var t=function(t,e){if(!t)return!B.global.dispatchEvent(e);var n;try{return n=t.before(),!B.global.dispatchEvent(e)}finally{t.after(n)}};try{if(\"function\"==typeof CustomEvent){var e=new CustomEvent(\"CustomEvent\");return B.global.dispatchEvent(e),function(e,n){e=e.toLowerCase();var r={detail:n,cancelable:!0},i=new CustomEvent(e,r);return M.defineProperty(i,\"promise\",{value:n.promise}),M.defineProperty(i,\"reason\",{value:n.reason}),t(et[e],i)}}if(\"function\"==typeof Event){var e=new Event(\"CustomEvent\");return B.global.dispatchEvent(e),function(e,n){e=e.toLowerCase();var r=new Event(e,{cancelable:!0});return r.detail=n,M.defineProperty(r,\"promise\",{value:n.promise}),M.defineProperty(r,\"reason\",{value:n.reason}),t(et[e],r)}}var e=document.createEvent(\"CustomEvent\");return e.initCustomEvent(\"testingtheevent\",!1,!0,{}),B.global.dispatchEvent(e),function(e,n){e=e.toLowerCase();var r=document.createEvent(\"CustomEvent\");return r.initCustomEvent(e,!1,!0,n),t(et[e],r)}}catch(n){}return function(){return!1}}(),rt=function(){return B.isNode?function(){return process.emit.apply(process,arguments)}:B.global?function(t){var e=\"on\"+t.toLowerCase(),n=B.global[e];return n?(n.apply(B.global,[].slice.call(arguments,1)),!0):!1}:function(){return!1}}(),it={promiseCreated:o,promiseFulfilled:o,promiseRejected:o,promiseResolved:o,promiseCancelled:o,promiseChained:function(t,e,n){return{promise:e,child:n}},warning:function(t,e){return{warning:e}},unhandledRejection:function(t,e,n){return{reason:e,promise:n}},rejectionHandled:o},ot=function(t){var e=!1;try{e=rt.apply(null,arguments)}catch(n){N.throwLater(n),e=!0}var r=!1;try{r=nt(t,it[t].apply(null,arguments))}catch(n){N.throwLater(n),r=!0}return r||e};e.config=function(t){if(t=Object(t),\"longStackTraces\"in t&&(t.longStackTraces?e.longStackTraces():!t.longStackTraces&&e.hasLongStackTraces()&&tt()),\"warnings\"in t){var n=t.warnings;lt.warnings=!!n,Z=lt.warnings,B.isObject(n)&&\"wForgottenReturn\"in n&&(Z=!!n.wForgottenReturn)}if(\"cancellation\"in t&&t.cancellation&&!lt.cancellation){if(N.haveItemsQueued())throw new Error(\"cannot enable cancellation after promises are in use\");e.prototype._clearCancellationData=p,e.prototype._propagateFrom=f,e.prototype._onCancel=u,e.prototype._setOnCancel=l,e.prototype._attachCancellationCallback=c,e.prototype._execute=a,st=f,lt.cancellation=!0}if(\"monitoring\"in t&&(t.monitoring&&!lt.monitoring?(lt.monitoring=!0,e.prototype._fireEvent=ot):!t.monitoring&<.monitoring&&(lt.monitoring=!1,e.prototype._fireEvent=s)),\"asyncHooks\"in t&&B.nodeSupportsAsyncResource){var o=lt.asyncHooks,h=!!t.asyncHooks;o!==h&&(lt.asyncHooks=h,h?r():i())}return e},e.prototype._fireEvent=s,e.prototype._execute=function(t,e,n){try{t(e,n)}catch(r){return r}},e.prototype._onCancel=function(){},e.prototype._setOnCancel=function(t){},e.prototype._attachCancellationCallback=function(t){},e.prototype._captureStackTrace=function(){},e.prototype._attachExtraTrace=function(){},e.prototype._dereferenceTrace=function(){},e.prototype._clearCancellationData=function(){},e.prototype._propagateFrom=function(t,e){};var st=h,at=function(){return!1},ct=/[\\/<\\(]([^:\\/]+):(\\d+):(?:\\d+)\\)?\\s*$/;B.inherits(V,Error),n.CapturedTrace=V,V.prototype.uncycle=function(){var t=this._length;if(!(2>t)){for(var e=[],n={},r=0,i=this;void 0!==i;++r)e.push(i),i=i._parent;t=this._length=r;for(var r=t-1;r>=0;--r){var o=e[r].stack;void 0===n[o]&&(n[o]=r)}for(var r=0;t>r;++r){var s=e[r].stack,a=n[s];if(void 0!==a&&a!==r){a>0&&(e[a-1]._parent=void 0,e[a-1]._length=1),e[r]._parent=void 0,e[r]._length=1;var c=r>0?e[r-1]:this;t-1>a?(c._parent=e[a+1],c._parent.uncycle(),c._length=c._parent._length+1):(c._parent=void 0,c._length=1);for(var u=c._length+1,l=r-2;l>=0;--l)e[l]._length=u,u++;return}}}},V.prototype.attachExtraTrace=function(t){if(!t.__stackCleaned__){this.uncycle();for(var e=F(t),n=e.message,r=[e.stack],i=this;void 0!==i;)r.push(k(i.stack.split(\"\\n\"))),i=i._parent;j(r),C(r),B.notEnumerableProp(t,\"stack\",w(n,r)),B.notEnumerableProp(t,\"__stackCleaned__\",!0)}};var ut=function(){var t=/^\\s*at\\s*/,e=function(t,e){return\"string\"==typeof t?t:void 0!==e.name&&void 0!==e.message?e.toString():P(e)};if(\"number\"==typeof Error.stackTraceLimit&&\"function\"==typeof Error.captureStackTrace){Error.stackTraceLimit+=6,W=t,z=e;var n=Error.captureStackTrace;return at=function(t){return $.test(t)},function(t,e){Error.stackTraceLimit+=6,n(t,e),Error.stackTraceLimit-=6}}var r=new Error;if(\"string\"==typeof r.stack&&r.stack.split(\"\\n\")[0].indexOf(\"stackDetection@\")>=0)return W=/@/,z=e,X=!0,function(t){t.stack=(new Error).stack};var i;try{throw new Error}catch(o){i=\"stack\"in o}return\"stack\"in r||!i||\"number\"!=typeof Error.stackTraceLimit?(z=function(t,e){return\"string\"==typeof t?t:\"object\"!=typeof e&&\"function\"!=typeof e||void 0===e.name||void 0===e.message?P(e):e.toString()},null):(W=t,z=e,function(t){Error.stackTraceLimit+=6;try{throw new Error}catch(e){t.stack=e.stack}Error.stackTraceLimit-=6})}([]);\"undefined\"!=typeof console&&\"undefined\"!=typeof console.warn&&(I=function(t){console.warn(t)},B.isNode&&process.stderr.isTTY?I=function(t,e){var n=e?\"\u001b[33m\":\"\u001b[31m\";console.warn(n+t+\"\u001b[0m\\n\")}:B.isNode||\"string\"!=typeof(new Error).stack||(I=function(t,e){console.warn(\"%c\"+t,e?\"color: darkorange\":\"color: red\")}));var lt={warnings:J,longStackTraces:!1,cancellation:!1,monitoring:!1,asyncHooks:!1};return Y&&e.longStackTraces(),{asyncHooks:function(){return lt.asyncHooks},longStackTraces:function(){return lt.longStackTraces},warnings:function(){return lt.warnings},cancellation:function(){return lt.cancellation},monitoring:function(){return lt.monitoring},propagateFromFunction:function(){return st},boundValueFunction:function(){return _},checkForgottenReturns:g,setBounds:A,warn:b,deprecated:m,CapturedTrace:V,fireDomEvent:nt,fireGlobalEvent:rt}}},{\"./errors\":12,\"./es5\":13,\"./util\":36}],10:[function(t,e,n){\"use strict\";e.exports=function(t){function e(){return this.value}function n(){throw this.reason}t.prototype[\"return\"]=t.prototype.thenReturn=function(n){return n instanceof t&&n.suppressUnhandledRejections(),this._then(e,void 0,void 0,{value:n},void 0)},t.prototype[\"throw\"]=t.prototype.thenThrow=function(t){return this._then(n,void 0,void 0,{reason:t},void 0)},t.prototype.catchThrow=function(t){if(arguments.length<=1)return this._then(void 0,n,void 0,{reason:t},void 0);var e=arguments[1],r=function(){throw e};return this.caught(t,r)},t.prototype.catchReturn=function(n){if(arguments.length<=1)return n instanceof t&&n.suppressUnhandledRejections(),this._then(void 0,e,void 0,{value:n},void 0);var r=arguments[1];r instanceof t&&r.suppressUnhandledRejections();var i=function(){return r};return this.caught(n,i)}}},{}],11:[function(t,e,n){\"use strict\";e.exports=function(t,e){function n(){return o(this)}function r(t,n){return i(t,n,e,e)}var i=t.reduce,o=t.all;t.prototype.each=function(t){return i(this,t,e,0)._then(n,void 0,void 0,this,void 0)},t.prototype.mapSeries=function(t){return i(this,t,e,e)},t.each=function(t,r){return i(t,r,e,0)._then(n,void 0,void 0,t,void 0)},t.mapSeries=r}},{}],12:[function(t,e,n){\"use strict\";function r(t,e){function n(r){return this instanceof n?(p(this,\"message\",\"string\"==typeof r?r:e),p(this,\"name\",t),void(Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):Error.call(this))):new n(r)}return l(n,Error),n}function i(t){return this instanceof i?(p(this,\"name\",\"OperationalError\"),p(this,\"message\",t),this.cause=t,this.isOperational=!0,void(t instanceof Error?(p(this,\"message\",t.message),p(this,\"stack\",t.stack)):Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor))):new i(t)}var o,s,a=t(\"./es5\"),c=a.freeze,u=t(\"./util\"),l=u.inherits,p=u.notEnumerableProp,f=r(\"Warning\",\"warning\"),h=r(\"CancellationError\",\"cancellation error\"),_=r(\"TimeoutError\",\"timeout error\"),d=r(\"AggregateError\",\"aggregate error\");try{o=TypeError,s=RangeError}catch(v){o=r(\"TypeError\",\"type error\"),s=r(\"RangeError\",\"range error\")}for(var y=\"join pop push shift unshift slice filter forEach some every map indexOf lastIndexOf reduce reduceRight sort reverse\".split(\" \"),g=0;g1?t.cancelPromise._reject(e):t.cancelPromise._cancel(),t.cancelPromise=null,!0):!1}function a(){return u.call(this,this.promise._target()._settledValue())}function c(t){return s(this,t)?void 0:(f.e=t,f)}function u(t){var i=this.promise,u=this.handler;if(!this.called){this.called=!0;var l=this.isFinallyHandler()?u.call(i._boundValue()):u.call(i._boundValue(),t);if(l===r)return l;if(void 0!==l){i._setReturnedNonUndefined();var h=n(l,i);if(h instanceof e){if(null!=this.cancelPromise){if(h._isCancelled()){var _=new p(\"late cancellation observer\");return i._attachExtraTrace(_),f.e=_,f}h.isPending()&&h._attachCancellationCallback(new o(this))}return h._then(a,c,void 0,this,void 0)}}}return i.isRejected()?(s(this),f.e=t,f):(s(this),t)}var l=t(\"./util\"),p=e.CancellationError,f=l.errorObj,h=t(\"./catch_filter\")(r);return i.prototype.isFinallyHandler=function(){return 0===this.type},o.prototype._resultCancelled=function(){s(this.finallyHandler)},e.prototype._passThrough=function(t,e,n,r){return\"function\"!=typeof t?this.then():this._then(n,r,void 0,new i(this,e,t),void 0)},e.prototype.lastly=e.prototype[\"finally\"]=function(t){return this._passThrough(t,0,u,u)},e.prototype.tap=function(t){return this._passThrough(t,1,u)},e.prototype.tapCatch=function(t){var n=arguments.length;if(1===n)return this._passThrough(t,1,void 0,u);var r,i=new Array(n-1),o=0;for(r=0;n-1>r;++r){var s=arguments[r];if(!l.isObject(s))return e.reject(new TypeError(\"tapCatch statement predicate: expecting an object but got \"+l.classString(s)));i[o++]=s}i.length=o;var a=arguments[r];return this._passThrough(h(i,a,this),1,void 0,u)},i}},{\"./catch_filter\":7,\"./util\":36}],16:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i,o,s){function a(t,n,r){for(var o=0;o0&&\"function\"==typeof arguments[e]){t=arguments[e];var r}var i=[].slice.call(arguments);t&&i.pop();var r=new n(i).promise();return void 0!==t?r.spread(t):r}}},{\"./util\":36}],18:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i,o,s){function a(t,n,r,i){this.constructor$(t),this._promise._captureStackTrace();var s=e._getContext();if(this._callback=u.contextBind(s,n),this._preservedValues=i===o?new Array(this.length()):null,this._limit=r,this._inFlight=0,this._queue=[],f.invoke(this._asyncInit,this,void 0),u.isArray(t))for(var a=0;a=1?s:0,new a(t,n,s,o).promise()}var u=t(\"./util\"),l=u.tryCatch,p=u.errorObj,f=e._async;u.inherits(a,n),a.prototype._asyncInit=function(){this._init$(void 0,-2)},a.prototype._init=function(){},a.prototype._promiseFulfilled=function(t,n){var r=this._values,o=this.length(),a=this._preservedValues,c=this._limit;if(0>n){if(n=-1*n-1,r[n]=t,c>=1&&(this._inFlight--,this._drainQueue(),this._isResolved()))return!0}else{if(c>=1&&this._inFlight>=c)return r[n]=t,this._queue.push(n),!1;null!==a&&(a[n]=t);var u=this._promise,f=this._callback,h=u._boundValue();u._pushContext();var _=l(f).call(h,t,n,o),d=u._popContext();if(s.checkForgottenReturns(_,d,null!==a?\"Promise.filter\":\"Promise.map\",u),_===p)return this._reject(_.e),!0;var v=i(_,this._promise);if(v instanceof e){v=v._target();var y=v._bitField;if(0===(50397184&y))return c>=1&&this._inFlight++,r[n]=v,v._proxy(this,-1*(n+1)),!1;if(0===(33554432&y))return 0!==(16777216&y)?(this._reject(v._reason()),!0):(this._cancel(),!0);_=v._value()}r[n]=_}var g=++this._totalResolved;return g>=o?(null!==a?this._filter(r,a):this._resolve(r),!0):!1},a.prototype._drainQueue=function(){for(var t=this._queue,e=this._limit,n=this._values;t.length>0&&this._inFlighto;++o)t[o]&&(r[i++]=e[o]);r.length=i,this._resolve(r)},a.prototype.preservedValues=function(){return this._preservedValues},e.prototype.map=function(t,e){return c(this,t,e,null)},e.map=function(t,e,n,r){return c(t,e,n,r)}}},{\"./util\":36}],19:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i,o){var s=t(\"./util\"),a=s.tryCatch;e.method=function(t){if(\"function\"!=typeof t)throw new e.TypeError(\"expecting a function but got \"+s.classString(t));return function(){var r=new e(n);r._captureStackTrace(),r._pushContext();var i=a(t).apply(this,arguments),s=r._popContext();return o.checkForgottenReturns(i,s,\"Promise.method\",r),r._resolveFromSyncValue(i),r}},e.attempt=e[\"try\"]=function(t){if(\"function\"!=typeof t)return i(\"expecting a function but got \"+s.classString(t));var r=new e(n);r._captureStackTrace(),r._pushContext();var c;if(arguments.length>1){o.deprecated(\"calling Promise.try with more than 1 argument\");var u=arguments[1],l=arguments[2];c=s.isArray(u)?a(t).apply(l,u):a(t).call(l,u)}else c=a(t)();var p=r._popContext();return o.checkForgottenReturns(c,p,\"Promise.try\",r),r._resolveFromSyncValue(c),r},e.prototype._resolveFromSyncValue=function(t){t===s.errorObj?this._rejectCallback(t.e,!1):this._resolveCallback(t,!0)}}},{\"./util\":36}],20:[function(t,e,n){\"use strict\";function r(t){return t instanceof Error&&l.getPrototypeOf(t)===Error.prototype}function i(t){var e;if(r(t)){e=new u(t),e.name=t.name,e.message=t.message,e.stack=t.stack;for(var n=l.keys(t),i=0;i1){var n,r=new Array(e-1),i=0;for(n=0;e-1>n;++n){var o=arguments[n];if(!f.isObject(o))return l(\"Catch statement predicate: expecting an object but got \"+f.classString(o));r[i++]=o}if(r.length=i,t=arguments[n],\"function\"!=typeof t)throw new E(\"The last argument to .catch() must be a function, got \"+f.toString(t));return this.then(void 0,D(r,t,this))}return this.then(void 0,t)},i.prototype.reflect=function(){return this._then(u,u,void 0,this,void 0)},i.prototype.then=function(t,e){if(V.warnings()&&arguments.length>0&&\"function\"!=typeof t&&\"function\"!=typeof e){var n=\".then() only accepts functions but was passed: \"+f.classString(t);arguments.length>1&&(n+=\", \"+f.classString(e)),this._warn(n)}return this._then(t,e,void 0,void 0,void 0)},i.prototype.done=function(t,e){var n=this._then(t,e,void 0,void 0,void 0);n._setIsFinal()},i.prototype.spread=function(t){return\"function\"!=typeof t?l(\"expecting a function but got \"+f.classString(t)):this.all()._then(t,void 0,void 0,T,void 0)},i.prototype.toJSON=function(){var t={isFulfilled:!1,isRejected:!1,fulfillmentValue:void 0,rejectionReason:void 0};return this.isFulfilled()?(t.fulfillmentValue=this.value(),t.isFulfilled=!0):this.isRejected()&&(t.rejectionReason=this.reason(),t.isRejected=!0),t},i.prototype.all=function(){return arguments.length>0&&this._warn(\".all() was passed arguments but it does not take any\"),new S(this).promise()},i.prototype.error=function(t){return this.caught(f.originatesFromRejection,t)},i.getNewLibraryCopy=e.exports,i.is=function(t){return t instanceof i},i.fromNode=i.fromCallback=function(t){var e=new i(x);e._captureStackTrace();var n=arguments.length>1?!!Object(arguments[1]).multiArgs:!1,r=N(t)(I(e,n));return r===L&&e._rejectCallback(r.e,!0),e._isFateSealed()||e._setAsyncGuaranteed(),e},i.all=function(t){return new S(t).promise()},i.cast=function(t){var e=R(t);return e instanceof i||(e=new i(x),e._captureStackTrace(),e._setFulfilled(),e._rejectionHandler0=t),e},i.resolve=i.fulfilled=i.cast,i.reject=i.rejected=function(t){var e=new i(x);return e._captureStackTrace(),e._rejectCallback(t,!0),e},i.setScheduler=function(t){if(\"function\"!=typeof t)throw new E(\"expecting a function but got \"+f.classString(t));return j.setScheduler(t)},i.prototype._then=function(t,e,n,r,o){var s=void 0!==o,a=s?o:new i(x),c=this._target(),u=c._bitField;s||(a._propagateFrom(this,3),a._captureStackTrace(),void 0===r&&0!==(2097152&this._bitField)&&(r=0!==(50397184&u)?this._boundValue():c===this?void 0:this._boundTo),this._fireEvent(\"promiseChained\",this,a));var l=g();if(0!==(50397184&u)){var p,h,_=c._settlePromiseCtx;0!==(33554432&u)?(h=c._rejectionHandler0,p=t):0!==(16777216&u)?(h=c._fulfillmentHandler0,p=e,c._unsetRejectionIsUnhandled()):(_=c._settlePromiseLateCancellationObserver,h=new F(\"late cancellation observer\"),c._attachExtraTrace(h),p=e),j.invoke(_,c,{handler:f.contextBind(l,p),promise:a,receiver:r,value:h})}else c._addCallbacks(t,e,a,r,l);return a},i.prototype._length=function(){return 65535&this._bitField},i.prototype._isFateSealed=function(){return 0!==(117506048&this._bitField)},i.prototype._isFollowing=function(){return 67108864===(67108864&this._bitField)},i.prototype._setLength=function(t){this._bitField=-65536&this._bitField|65535&t},i.prototype._setFulfilled=function(){this._bitField=33554432|this._bitField,this._fireEvent(\"promiseFulfilled\",this)},i.prototype._setRejected=function(){this._bitField=16777216|this._bitField,this._fireEvent(\"promiseRejected\",this)},i.prototype._setFollowing=function(){this._bitField=67108864|this._bitField,this._fireEvent(\"promiseResolved\",this)},i.prototype._setIsFinal=function(){this._bitField=4194304|this._bitField},i.prototype._isFinal=function(){return(4194304&this._bitField)>0},i.prototype._unsetCancelled=function(){this._bitField=-65537&this._bitField},i.prototype._setCancelled=function(){this._bitField=65536|this._bitField,this._fireEvent(\"promiseCancelled\",this)},i.prototype._setWillBeCancelled=function(){this._bitField=8388608|this._bitField},i.prototype._setAsyncGuaranteed=function(){if(!j.hasCustomScheduler()){var t=this._bitField;this._bitField=t|(536870912&t)>>2^134217728}},i.prototype._setNoAsyncGuarantee=function(){this._bitField=-134217729&(536870912|this._bitField)},i.prototype._receiverAt=function(t){var e=0===t?this._receiver0:this[4*t-4+3];return e===p?void 0:void 0===e&&this._isBound()?this._boundValue():e},i.prototype._promiseAt=function(t){return this[4*t-4+2]},i.prototype._fulfillmentHandlerAt=function(t){return this[4*t-4+0]},i.prototype._rejectionHandlerAt=function(t){return this[4*t-4+1]},i.prototype._boundValue=function(){},i.prototype._migrateCallback0=function(t){var e=(t._bitField,t._fulfillmentHandler0),n=t._rejectionHandler0,r=t._promise0,i=t._receiverAt(0);void 0===i&&(i=p),this._addCallbacks(e,n,r,i,null)},i.prototype._migrateCallbackAt=function(t,e){var n=t._fulfillmentHandlerAt(e),r=t._rejectionHandlerAt(e),i=t._promiseAt(e),o=t._receiverAt(e);void 0===o&&(o=p),this._addCallbacks(n,r,i,o,null)},i.prototype._addCallbacks=function(t,e,n,r,i){var o=this._length();if(o>=65531&&(o=0,this._setLength(0)),0===o)this._promise0=n,this._receiver0=r,\"function\"==typeof t&&(this._fulfillmentHandler0=f.contextBind(i,t)),\"function\"==typeof e&&(this._rejectionHandler0=f.contextBind(i,e));else{var s=4*o-4;this[s+2]=n,this[s+3]=r,\"function\"==typeof t&&(this[s+0]=f.contextBind(i,t)),\"function\"==typeof e&&(this[s+1]=f.contextBind(i,e))}return this._setLength(o+1),o},i.prototype._proxy=function(t,e){this._addCallbacks(void 0,void 0,e,t,null)},i.prototype._resolveCallback=function(t,e){if(0===(117506048&this._bitField)){if(t===this)return this._rejectCallback(c(),!1);var n=R(t,this);if(!(n instanceof i))return this._fulfill(t);e&&this._propagateFrom(n,2);var r=n._target();if(r===this)return void this._reject(c());var o=r._bitField;if(0===(50397184&o)){var s=this._length();s>0&&r._migrateCallback0(this);for(var a=1;s>a;++a)r._migrateCallbackAt(this,a);this._setFollowing(),this._setLength(0),this._setFollowee(n)}else if(0!==(33554432&o))this._fulfill(r._value());else if(0!==(16777216&o))this._reject(r._reason());else{var u=new F(\"late cancellation observer\");r._attachExtraTrace(u),this._reject(u)}}},i.prototype._rejectCallback=function(t,e,n){var r=f.ensureErrorObject(t),i=r===t;if(!i&&!n&&V.warnings()){var o=\"a promise was rejected with a non-error: \"+f.classString(t);this._warn(o,!0)}this._attachExtraTrace(r,e?i:!1),this._reject(t)},i.prototype._resolveFromExecutor=function(t){if(t!==x){var e=this;this._captureStackTrace(),this._pushContext();var n=!0,r=this._execute(t,function(t){e._resolveCallback(t)},function(t){e._rejectCallback(t,n)});n=!1,this._popContext(),void 0!==r&&e._rejectCallback(r,!0)}},i.prototype._settlePromiseFromHandler=function(t,e,n,r){var i=r._bitField;if(0===(65536&i)){r._pushContext();var o;e===T?n&&\"number\"==typeof n.length?o=N(t).apply(this._boundValue(),n):(o=L,o.e=new E(\"cannot .spread() a non-array: \"+f.classString(n))):o=N(t).call(e,n);var s=r._popContext();i=r._bitField,0===(65536&i)&&(o===P?r._reject(n):o===L?r._rejectCallback(o.e,!1):(V.checkForgottenReturns(o,s,\"\",r,this),r._resolveCallback(o)))}},i.prototype._target=function(){for(var t=this;t._isFollowing();)t=t._followee();return t},i.prototype._followee=function(){return this._rejectionHandler0},i.prototype._setFollowee=function(t){this._rejectionHandler0=t},i.prototype._settlePromise=function(t,e,r,o){var s=t instanceof i,a=this._bitField,c=0!==(134217728&a);0!==(65536&a)?(s&&t._invokeInternalOnCancel(),r instanceof H&&r.isFinallyHandler()?(r.cancelPromise=t,N(e).call(r,o)===L&&t._reject(L.e)):e===u?t._fulfill(u.call(r)):r instanceof n?r._promiseCancelled(t):s||t instanceof S?t._cancel():r.cancel()):\"function\"==typeof e?s?(c&&t._setAsyncGuaranteed(),this._settlePromiseFromHandler(e,r,o,t)):e.call(r,o,t):r instanceof n?r._isResolved()||(0!==(33554432&a)?r._promiseFulfilled(o,t):r._promiseRejected(o,t)):s&&(c&&t._setAsyncGuaranteed(),0!==(33554432&a)?t._fulfill(o):t._reject(o))},i.prototype._settlePromiseLateCancellationObserver=function(t){var e=t.handler,n=t.promise,r=t.receiver,o=t.value;\"function\"==typeof e?n instanceof i?this._settlePromiseFromHandler(e,r,o,n):e.call(r,o,n):n instanceof i&&n._reject(o)},i.prototype._settlePromiseCtx=function(t){this._settlePromise(t.promise,t.handler,t.receiver,t.value)},i.prototype._settlePromise0=function(t,e,n){var r=this._promise0,i=this._receiverAt(0);this._promise0=void 0,this._receiver0=void 0,this._settlePromise(r,t,i,e)},i.prototype._clearCallbackDataAtIndex=function(t){var e=4*t-4;this[e+2]=this[e+3]=this[e+0]=this[e+1]=void 0},i.prototype._fulfill=function(t){var e=this._bitField;if(!((117506048&e)>>>16)){if(t===this){var n=c();return this._attachExtraTrace(n),this._reject(n)}this._setFulfilled(),this._rejectionHandler0=t,(65535&e)>0&&(0!==(134217728&e)?this._settlePromises():j.settlePromises(this),this._dereferenceTrace())}},i.prototype._reject=function(t){var e=this._bitField;if(!((117506048&e)>>>16))return this._setRejected(),this._fulfillmentHandler0=t,this._isFinal()?j.fatalError(t,f.isNode):void((65535&e)>0?j.settlePromises(this):this._ensurePossibleRejectionHandled())},i.prototype._fulfillPromises=function(t,e){for(var n=1;t>n;n++){var r=this._fulfillmentHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._rejectPromises=function(t,e){for(var n=1;t>n;n++){var r=this._rejectionHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._settlePromises=function(){var t=this._bitField,e=65535&t;if(e>0){if(0!==(16842752&t)){var n=this._fulfillmentHandler0;this._settlePromise0(this._rejectionHandler0,n,t),this._rejectPromises(e,n)}else{var r=this._rejectionHandler0;this._settlePromise0(this._fulfillmentHandler0,r,t),this._fulfillPromises(e,r)}this._setLength(0)}this._clearCancellationData()},i.prototype._settledValue=function(){var t=this._bitField;return 0!==(33554432&t)?this._rejectionHandler0:0!==(16777216&t)?this._fulfillmentHandler0:void 0},\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&w.defineProperty(i.prototype,Symbol.toStringTag,{get:function(){return\"Object\"}}),i.defer=i.pending=function(){V.deprecated(\"Promise.defer\",\"new Promise\");var t=new i(x);return{promise:t,resolve:o,reject:s}},f.notEnumerableProp(i,\"_makeSelfResolutionError\",c),t(\"./method\")(i,x,R,l,V),t(\"./bind\")(i,x,R,V),t(\"./cancel\")(i,S,l,V),t(\"./direct_resolve\")(i),t(\"./synchronous_inspection\")(i),t(\"./join\")(i,S,R,x,j),i.Promise=i,i.version=\"3.7.1\",t(\"./call_get.js\")(i),t(\"./generators.js\")(i,l,x,R,n,V),t(\"./map.js\")(i,S,l,R,x,V),t(\"./nodeify.js\")(i),t(\"./promisify.js\")(i,x),t(\"./props.js\")(i,S,R,l),t(\"./race.js\")(i,x,R,l),t(\"./reduce.js\")(i,S,l,R,x,V),t(\"./settle.js\")(i,S,V),t(\"./some.js\")(i,S,l),t(\"./timers.js\")(i,x,V),t(\"./using.js\")(i,l,R,A,x,V),t(\"./any.js\")(i),t(\"./each.js\")(i,x),t(\"./filter.js\")(i,x),f.toFastProperties(i),f.toFastProperties(i.prototype),a({a:1}),a({b:2}),a({c:3}),a(1),a(function(){}),a(void 0),a(!1),a(new i(x)),V.setBounds(C.firstLineError,f.lastLineError),i}},{\"./any.js\":1,\"./async\":2,\"./bind\":3,\"./call_get.js\":5,\"./cancel\":6,\"./catch_filter\":7,\"./context\":8,\"./debuggability\":9,\"./direct_resolve\":10,\"./each.js\":11,\"./errors\":12,\"./es5\":13,\"./filter.js\":14,\"./finally\":15,\"./generators.js\":16,\"./join\":17,\"./map.js\":18,\"./method\":19,\"./nodeback\":20,\"./nodeify.js\":21,\"./promise_array\":23,\"./promisify.js\":24,\"./props.js\":25,\"./race.js\":27,\"./reduce.js\":28,\"./settle.js\":30,\"./some.js\":31,\"./synchronous_inspection\":32,\"./thenables\":33,\"./timers.js\":34,\"./using.js\":35,\"./util\":36,async_hooks:void 0}],23:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i,o){function s(t){switch(t){case-2:return[];case-3:return{};case-6:return new Map}}function a(t){var r=this._promise=new e(n);t instanceof e&&(r._propagateFrom(t,3),t.suppressUnhandledRejections()),r._setOnCancel(this),this._values=t,this._length=0,this._totalResolved=0,this._init(void 0,-2)}var c=t(\"./util\");c.isArray;return c.inherits(a,o),a.prototype.length=function(){return this._length},a.prototype.promise=function(){return this._promise},a.prototype._init=function u(t,n){var o=r(this._values,this._promise);if(o instanceof e){o=o._target();var a=o._bitField;if(this._values=o,0===(50397184&a))return this._promise._setAsyncGuaranteed(),o._then(u,this._reject,void 0,this,n);if(0===(33554432&a))return 0!==(16777216&a)?this._reject(o._reason()):this._cancel();o=o._value()}if(o=c.asArray(o),null===o){var l=i(\"expecting an array or an iterable object but got \"+c.classString(o)).reason();return void this._promise._rejectCallback(l,!1)}return 0===o.length?void(-5===n?this._resolveEmptyArray():this._resolve(s(n))):void this._iterate(o)},a.prototype._iterate=function(t){var n=this.getActualLength(t.length);this._length=n,this._values=this.shouldCopyValues()?new Array(n):this._values;for(var i=this._promise,o=!1,s=null,a=0;n>a;++a){var c=r(t[a],i);c instanceof e?(c=c._target(),s=c._bitField):s=null,o?null!==s&&c.suppressUnhandledRejections():null!==s?0===(50397184&s)?(c._proxy(this,a),this._values[a]=c):o=0!==(33554432&s)?this._promiseFulfilled(c._value(),a):0!==(16777216&s)?this._promiseRejected(c._reason(),a):this._promiseCancelled(a):o=this._promiseFulfilled(c,a)}o||i._setAsyncGuaranteed()},a.prototype._isResolved=function(){return null===this._values},a.prototype._resolve=function(t){this._values=null,this._promise._fulfill(t)},a.prototype._cancel=function(){!this._isResolved()&&this._promise._isCancellable()&&(this._values=null,this._promise._cancel())},a.prototype._reject=function(t){this._values=null,this._promise._rejectCallback(t,!1)},a.prototype._promiseFulfilled=function(t,e){this._values[e]=t;var n=++this._totalResolved;return n>=this._length?(this._resolve(this._values),!0):!1},a.prototype._promiseCancelled=function(){return this._cancel(),!0},a.prototype._promiseRejected=function(t){return this._totalResolved++,this._reject(t),!0},a.prototype._resultCancelled=function(){if(!this._isResolved()){var t=this._values;if(this._cancel(),t instanceof e)t.cancel();else for(var n=0;nc;c+=2){var l=s[c],p=s[c+1],_=l+e;if(r===E)t[_]=E(l,f,l,p,e,i);else{var d=r(p,function(){return E(l,f,l,p,e,i)});h.notEnumerableProp(d,\"__isPromisified__\",!0),t[_]=d}}return h.toFastProperties(t),t}function l(t,e,n){return E(t,e,void 0,t,null,n)}var p,f={},h=t(\"./util\"),_=t(\"./nodeback\"),d=h.withAppended,v=h.maybeWrapAsError,y=h.canEvaluate,g=t(\"./errors\").TypeError,m=\"Async\",b={__isPromisified__:!0},w=[\"arity\",\"length\",\"name\",\"arguments\",\"caller\",\"callee\",\"prototype\",\"__isPromisified__\"],C=new RegExp(\"^(?:\"+w.join(\"|\")+\")$\"),j=function(t){return h.isIdentifier(t)&&\"_\"!==t.charAt(0)&&\"constructor\"!==t},k=function(t){return t.replace(/([$])/,\"\\\\$\")},E=y?p:c;e.promisify=function(t,e){if(\"function\"!=typeof t)throw new g(\"expecting a function but got \"+h.classString(t));if(i(t))return t;e=Object(e);var n=void 0===e.context?f:e.context,o=!!e.multiArgs,s=l(t,n,o);return h.copyDescriptors(t,s,r),s},e.promisifyAll=function(t,e){if(\"function\"!=typeof t&&\"object\"!=typeof t)throw new g(\"the target of promisifyAll must be an object or a function\\n\\n See http://goo.gl/MqrFmX\\n\");e=Object(e);var n=!!e.multiArgs,r=e.suffix;\"string\"!=typeof r&&(r=m);var i=e.filter;\"function\"!=typeof i&&(i=j);var o=e.promisifier;if(\"function\"!=typeof o&&(o=E),!h.isIdentifier(r))throw new RangeError(\"suffix must be a valid identifier\\n\\n See http://goo.gl/MqrFmX\\n\");for(var s=h.inheritedDataKeys(t),a=0;ao;++o){var s=r[o];e[o]=t[s],e[o+i]=s}}this.constructor$(e),this._isMap=n,this._init$(void 0,n?-6:-3)}function s(t){var n,s=r(t);return u(s)?(n=s instanceof e?s._then(e.props,void 0,void 0,void 0,void 0):new o(s).promise(),s instanceof e&&n._propagateFrom(s,2),n):i(\"cannot await properties of a non-object\\n\\n See http://goo.gl/MqrFmX\\n\")}var a,c=t(\"./util\"),u=c.isObject,l=t(\"./es5\");\"function\"==typeof Map&&(a=Map);var p=function(){function t(t,r){this[e]=t,this[e+n]=r,e++}var e=0,n=0;return function(r){n=r.size,e=0;var i=new Array(2*r.size);return r.forEach(t,i),i}}(),f=function(t){for(var e=new a,n=t.length/2|0,r=0;n>r;++r){var i=t[n+r],o=t[r];e.set(i,o)}return e};c.inherits(o,n),o.prototype._init=function(){},o.prototype._promiseFulfilled=function(t,e){this._values[e]=t;var n=++this._totalResolved;if(n>=this._length){var r;if(this._isMap)r=f(this._values);else{r={};for(var i=this.length(),o=0,s=this.length();s>o;++o)r[this._values[o+i]]=this._values[o]}return this._resolve(r),!0}return!1},o.prototype.shouldCopyValues=function(){return!1},o.prototype.getActualLength=function(t){return t>>1},e.prototype.props=function(){return s(this)},e.props=function(t){return s(t)}}},{\"./es5\":13,\"./util\":36}],26:[function(t,e,n){\"use strict\";function r(t,e,n,r,i){for(var o=0;i>o;++o)n[o+r]=t[o+e],t[o+e]=void 0}function i(t){this._capacity=t,this._length=0,this._front=0}i.prototype._willBeOverCapacity=function(t){return this._capacityf;++f){var _=t[f];(void 0!==_||f in t)&&e.cast(_)._then(l,p,void 0,u,null)}return u}var s=t(\"./util\"),a=function(t){return t.then(function(e){return o(e,t)})};e.race=function(t){return o(t,void 0)},e.prototype.race=function(){return o(this,void 0)}}},{\"./util\":36}],28:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i,o,s){function a(t,n,r,i){this.constructor$(t);var s=e._getContext();this._fn=f.contextBind(s,n),void 0!==r&&(r=e.resolve(r),r._attachCancellationCallback(this)),this._initialValue=r,this._currentCancellable=null,i===o?this._eachValues=Array(this._length):0===i?this._eachValues=null:this._eachValues=void 0,this._promise._captureStackTrace(),this._init$(void 0,-5)}function c(t,e){this.isFulfilled()?e._resolve(t):e._reject(t)}function u(t,e,n,i){if(\"function\"!=typeof e)return r(\"expecting a function but got \"+f.classString(e));var o=new a(t,e,n,i);return o.promise()}function l(t){this.accum=t,this.array._gotAccum(t);var n=i(this.value,this.array._promise);return n instanceof e?(this.array._currentCancellable=n,n._then(p,void 0,void 0,this,void 0)):p.call(this,n)}function p(t){var n=this.array,r=n._promise,i=h(n._fn);r._pushContext();var o;o=void 0!==n._eachValues?i.call(r._boundValue(),t,this.index,this.length):i.call(r._boundValue(),this.accum,t,this.index,this.length),o instanceof e&&(n._currentCancellable=o);var a=r._popContext();return s.checkForgottenReturns(o,a,void 0!==n._eachValues?\"Promise.each\":\"Promise.reduce\",r),o}var f=t(\"./util\"),h=f.tryCatch;f.inherits(a,n),a.prototype._gotAccum=function(t){void 0!==this._eachValues&&null!==this._eachValues&&t!==o&&this._eachValues.push(t)},a.prototype._eachComplete=function(t){return null!==this._eachValues&&this._eachValues.push(t),this._eachValues},a.prototype._init=function(){},a.prototype._resolveEmptyArray=function(){this._resolve(void 0!==this._eachValues?this._eachValues:this._initialValue)},a.prototype.shouldCopyValues=function(){return!1},a.prototype._resolve=function(t){this._promise._resolveCallback(t),this._values=null},a.prototype._resultCancelled=function(t){return t===this._initialValue?this._cancel():void(this._isResolved()||(this._resultCancelled$(),this._currentCancellable instanceof e&&this._currentCancellable.cancel(),this._initialValue instanceof e&&this._initialValue.cancel()))},a.prototype._iterate=function(t){this._values=t;var n,r,i=t.length;void 0!==this._initialValue?(n=this._initialValue,r=0):(n=e.resolve(t[0]),r=1),this._currentCancellable=n;for(var o=r;i>o;++o){var s=t[o];s instanceof e&&s.suppressUnhandledRejections()}if(!n.isRejected())for(;i>r;++r){var a={accum:null,value:t[r],index:r,length:i,array:this};n=n._then(l,void 0,void 0,a,void 0),0===(127&r)&&n._setNoAsyncGuarantee()}void 0!==this._eachValues&&(n=n._then(this._eachComplete,void 0,void 0,this,void 0)),n._then(c,c,void 0,n,this)},e.prototype.reduce=function(t,e){return u(this,t,e,null)},e.reduce=function(t,e,n,r){return u(t,e,n,r)}}},{\"./util\":36}],29:[function(t,e,n){\"use strict\";var r,i=t(\"./util\"),o=function(){\nthrow new Error(\"No async scheduler available\\n\\n See http://goo.gl/MqrFmX\\n\")},s=i.getNativePromise();if(i.isNode&&\"undefined\"==typeof MutationObserver){var a=global.setImmediate,c=process.nextTick;r=i.isRecentNode?function(t){a.call(global,t)}:function(t){c.call(process,t)}}else if(\"function\"==typeof s&&\"function\"==typeof s.resolve){var u=s.resolve();r=function(t){u.then(t)}}else r=\"undefined\"!=typeof MutationObserver&&(\"undefined\"==typeof window||!window.navigator||!window.navigator.standalone&&!window.cordova)&&\"classList\"in document.documentElement?function(){var t=document.createElement(\"div\"),e={attributes:!0},n=!1,r=document.createElement(\"div\"),i=new MutationObserver(function(){t.classList.toggle(\"foo\"),n=!1});i.observe(r,e);var o=function(){n||(n=!0,r.classList.toggle(\"foo\"))};return function(n){var r=new MutationObserver(function(){r.disconnect(),n()});r.observe(t,e),o()}}():\"undefined\"!=typeof setImmediate?function(t){setImmediate(t)}:\"undefined\"!=typeof setTimeout?function(t){setTimeout(t,0)}:o;e.exports=r},{\"./util\":36}],30:[function(t,e,n){\"use strict\";e.exports=function(e,n,r){function i(t){this.constructor$(t)}var o=e.PromiseInspection,s=t(\"./util\");s.inherits(i,n),i.prototype._promiseResolved=function(t,e){this._values[t]=e;var n=++this._totalResolved;return n>=this._length?(this._resolve(this._values),!0):!1},i.prototype._promiseFulfilled=function(t,e){var n=new o;return n._bitField=33554432,n._settledValueField=t,this._promiseResolved(e,n)},i.prototype._promiseRejected=function(t,e){var n=new o;return n._bitField=16777216,n._settledValueField=t,this._promiseResolved(e,n)},e.settle=function(t){return r.deprecated(\".settle()\",\".reflect()\"),new i(t).promise()},e.allSettled=function(t){return new i(t).promise()},e.prototype.settle=function(){return e.settle(this)}}},{\"./util\":36}],31:[function(t,e,n){\"use strict\";e.exports=function(e,n,r){function i(t){this.constructor$(t),this._howMany=0,this._unwrap=!1,this._initialized=!1}function o(t,e){if((0|e)!==e||0>e)return r(\"expecting a positive integer\\n\\n See http://goo.gl/MqrFmX\\n\");var n=new i(t),o=n.promise();return n.setHowMany(e),n.init(),o}var s=t(\"./util\"),a=t(\"./errors\").RangeError,c=t(\"./errors\").AggregateError,u=s.isArray,l={};s.inherits(i,n),i.prototype._init=function(){if(this._initialized){if(0===this._howMany)return void this._resolve([]);this._init$(void 0,-5);var t=u(this._values);!this._isResolved()&&t&&this._howMany>this._canPossiblyFulfill()&&this._reject(this._getRangeError(this.length()))}},i.prototype.init=function(){this._initialized=!0,this._init()},i.prototype.setUnwrap=function(){this._unwrap=!0},i.prototype.howMany=function(){return this._howMany},i.prototype.setHowMany=function(t){this._howMany=t},i.prototype._promiseFulfilled=function(t){return this._addFulfilled(t),this._fulfilled()===this.howMany()?(this._values.length=this.howMany(),1===this.howMany()&&this._unwrap?this._resolve(this._values[0]):this._resolve(this._values),!0):!1},i.prototype._promiseRejected=function(t){return this._addRejected(t),this._checkOutcome()},i.prototype._promiseCancelled=function(){return this._values instanceof e||null==this._values?this._cancel():(this._addRejected(l),this._checkOutcome())},i.prototype._checkOutcome=function(){if(this.howMany()>this._canPossiblyFulfill()){for(var t=new c,e=this.length();e0?this._reject(t):this._cancel(),!0}return!1},i.prototype._fulfilled=function(){return this._totalResolved},i.prototype._rejected=function(){return this._values.length-this.length()},i.prototype._addRejected=function(t){this._values.push(t)},i.prototype._addFulfilled=function(t){this._values[this._totalResolved++]=t},i.prototype._canPossiblyFulfill=function(){return this.length()-this._rejected()},i.prototype._getRangeError=function(t){var e=\"Input array must contain at least \"+this._howMany+\" items but contains only \"+t+\" items\";return new a(e)},i.prototype._resolveEmptyArray=function(){this._reject(this._getRangeError(0))},e.some=function(t,e){return o(t,e)},e.prototype.some=function(t){return o(this,t)},e._SomePromiseArray=i}},{\"./errors\":12,\"./util\":36}],32:[function(t,e,n){\"use strict\";e.exports=function(t){function e(t){void 0!==t?(t=t._target(),this._bitField=t._bitField,this._settledValueField=t._isFateSealed()?t._settledValue():void 0):(this._bitField=0,this._settledValueField=void 0)}e.prototype._settledValue=function(){return this._settledValueField};var n=e.prototype.value=function(){if(!this.isFulfilled())throw new TypeError(\"cannot get fulfillment value of a non-fulfilled promise\\n\\n See http://goo.gl/MqrFmX\\n\");return this._settledValue()},r=e.prototype.error=e.prototype.reason=function(){if(!this.isRejected())throw new TypeError(\"cannot get rejection reason of a non-rejected promise\\n\\n See http://goo.gl/MqrFmX\\n\");return this._settledValue()},i=e.prototype.isFulfilled=function(){return 0!==(33554432&this._bitField)},o=e.prototype.isRejected=function(){return 0!==(16777216&this._bitField)},s=e.prototype.isPending=function(){return 0===(50397184&this._bitField)},a=e.prototype.isResolved=function(){return 0!==(50331648&this._bitField)};e.prototype.isCancelled=function(){return 0!==(8454144&this._bitField)},t.prototype.__isCancelled=function(){return 65536===(65536&this._bitField)},t.prototype._isCancelled=function(){return this._target().__isCancelled()},t.prototype.isCancelled=function(){return 0!==(8454144&this._target()._bitField)},t.prototype.isPending=function(){return s.call(this._target())},t.prototype.isRejected=function(){return o.call(this._target())},t.prototype.isFulfilled=function(){return i.call(this._target())},t.prototype.isResolved=function(){return a.call(this._target())},t.prototype.value=function(){return n.call(this._target())},t.prototype.reason=function(){var t=this._target();return t._unsetRejectionIsUnhandled(),r.call(t)},t.prototype._value=function(){return this._settledValue()},t.prototype._reason=function(){return this._unsetRejectionIsUnhandled(),this._settledValue()},t.PromiseInspection=e}},{}],33:[function(t,e,n){\"use strict\";e.exports=function(e,n){function r(t,r){if(l(t)){if(t instanceof e)return t;var i=o(t);if(i===u){r&&r._pushContext();var c=e.reject(i.e);return r&&r._popContext(),c}if(\"function\"==typeof i){if(s(t)){var c=new e(n);return t._then(c._fulfill,c._reject,void 0,c,null),c}return a(t,i,r)}}return t}function i(t){return t.then}function o(t){try{return i(t)}catch(e){return u.e=e,u}}function s(t){try{return p.call(t,\"_promise0\")}catch(e){return!1}}function a(t,r,i){function o(t){a&&(a._resolveCallback(t),a=null)}function s(t){a&&(a._rejectCallback(t,p,!0),a=null)}var a=new e(n),l=a;i&&i._pushContext(),a._captureStackTrace(),i&&i._popContext();var p=!0,f=c.tryCatch(r).call(t,o,s);return p=!1,a&&f===u&&(a._rejectCallback(f.e,!0,!0),a=null),l}var c=t(\"./util\"),u=c.errorObj,l=c.isObject,p={}.hasOwnProperty;return r}},{\"./util\":36}],34:[function(t,e,n){\"use strict\";e.exports=function(e,n,r){function i(t){this.handle=t}function o(t){return clearTimeout(this.handle),t}function s(t){throw clearTimeout(this.handle),t}var a=t(\"./util\"),c=e.TimeoutError;i.prototype._resultCancelled=function(){clearTimeout(this.handle)};var u=function(t){return l(+this).thenReturn(t)},l=e.delay=function(t,o){var s,a;return void 0!==o?(s=e.resolve(o)._then(u,null,null,t,void 0),r.cancellation()&&o instanceof e&&s._setOnCancel(o)):(s=new e(n),a=setTimeout(function(){s._fulfill()},+t),r.cancellation()&&s._setOnCancel(new i(a)),s._captureStackTrace()),s._setAsyncGuaranteed(),s};e.prototype.delay=function(t){return l(t,this)};var p=function(t,e,n){var r;r=\"string\"!=typeof e?e instanceof Error?e:new c(\"operation timed out\"):new c(e),a.markAsOriginatingFromRejection(r),t._attachExtraTrace(r),t._reject(r),null!=n&&n.cancel()};e.prototype.timeout=function(t,e){t=+t;var n,a,c=new i(setTimeout(function(){n.isPending()&&p(n,e,a)},t));return r.cancellation()?(a=this.then(),n=a._then(o,s,void 0,c,void 0),n._setOnCancel(c)):n=this._then(o,s,void 0,c,void 0),n}}},{\"./util\":36}],35:[function(t,e,n){\"use strict\";e.exports=function(e,n,r,i,o,s){function a(t){setTimeout(function(){throw t},0)}function c(t){var e=r(t);return e!==t&&\"function\"==typeof t._isDisposable&&\"function\"==typeof t._getDisposer&&t._isDisposable()&&e._setDisposable(t._getDisposer()),e}function u(t,n){function i(){if(s>=u)return l._fulfill();var o=c(t[s++]);if(o instanceof e&&o._isDisposable()){try{o=r(o._getDisposer().tryDispose(n),t.promise)}catch(p){return a(p)}if(o instanceof e)return o._then(i,a,null,null,null)}i()}var s=0,u=t.length,l=new e(o);return i(),l}function l(t,e,n){this._data=t,this._promise=e,this._context=n}function p(t,e,n){this.constructor$(t,e,n)}function f(t){return l.isDisposer(t)?(this.resources[this.index]._setDisposable(t),t.promise()):t}function h(t){this.length=t,this.promise=null,this[t-1]=null}var _=t(\"./util\"),d=t(\"./errors\").TypeError,v=t(\"./util\").inherits,y=_.errorObj,g=_.tryCatch,m={};l.prototype.data=function(){return this._data},l.prototype.promise=function(){return this._promise},l.prototype.resource=function(){return this.promise().isFulfilled()?this.promise().value():m},l.prototype.tryDispose=function(t){var e=this.resource(),n=this._context;void 0!==n&&n._pushContext();var r=e!==m?this.doDispose(e,t):null;return void 0!==n&&n._popContext(),this._promise._unsetDisposable(),this._data=null,r},l.isDisposer=function(t){return null!=t&&\"function\"==typeof t.resource&&\"function\"==typeof t.tryDispose},v(p,l),p.prototype.doDispose=function(t,e){var n=this.data();return n.call(t,t,e)},h.prototype._resultCancelled=function(){for(var t=this.length,n=0;t>n;++n){var r=this[n];r instanceof e&&r.cancel()}},e.using=function(){var t=arguments.length;if(2>t)return n(\"you must pass at least 2 arguments to Promise.using\");var i=arguments[t-1];if(\"function\"!=typeof i)return n(\"expecting a function but got \"+_.classString(i));var o,a=!0;2===t&&Array.isArray(arguments[0])?(o=arguments[0],t=o.length,a=!1):(o=arguments,t--);for(var c=new h(t),p=0;t>p;++p){var d=o[p];if(l.isDisposer(d)){var v=d;d=d.promise(),d._setDisposable(v)}else{var m=r(d);m instanceof e&&(d=m._then(f,null,null,{resources:c,index:p},void 0))}c[p]=d}for(var b=new Array(c.length),p=0;p0},e.prototype._getDisposer=function(){return this._disposer},e.prototype._unsetDisposable=function(){this._bitField=-131073&this._bitField,this._disposer=void 0},e.prototype.disposer=function(t){if(\"function\"==typeof t)return new p(t,this,i());throw new d}}},{\"./errors\":12,\"./util\":36}],36:[function(t,e,n){\"use strict\";function r(){try{var t=P;return P=null,t.apply(this,arguments)}catch(e){return T.e=e,T}}function i(t){return P=t,r}function o(t){return null==t||t===!0||t===!1||\"string\"==typeof t||\"number\"==typeof t}function s(t){return\"function\"==typeof t||\"object\"==typeof t&&null!==t}function a(t){return o(t)?new Error(v(t)):t}function c(t,e){var n,r=t.length,i=new Array(r+1);for(n=0;r>n;++n)i[n]=t[n];return i[n]=e,i}function u(t,e,n){if(!F.isES5)return{}.hasOwnProperty.call(t,e)?t[e]:void 0;var r=Object.getOwnPropertyDescriptor(t,e);return null!=r?null==r.get&&null==r.set?r.value:n:void 0}function l(t,e,n){if(o(t))return t;var r={value:n,configurable:!0,enumerable:!1,writable:!0};return F.defineProperty(t,e,r),t}function p(t){throw t}function f(t){try{if(\"function\"==typeof t){var e=F.names(t.prototype),n=F.isES5&&e.length>1,r=e.length>0&&!(1===e.length&&\"constructor\"===e[0]),i=A.test(t+\"\")&&F.names(t).length>0;if(n||r||i)return!0}return!1}catch(o){return!1}}function h(t){function e(){}function n(){return typeof r.foo}e.prototype=t;var r=new e;return n(),n(),t}function _(t){return V.test(t)}function d(t,e,n){for(var r=new Array(t),i=0;t>i;++i)r[i]=e+i+n;return r}function v(t){try{return t+\"\"}catch(e){return\"[no string representation]\"}}function y(t){return t instanceof Error||null!==t&&\"object\"==typeof t&&\"string\"==typeof t.message&&\"string\"==typeof t.name}function g(t){try{l(t,\"isOperational\",!0)}catch(e){}}function m(t){return null==t?!1:t instanceof Error.__BluebirdErrorTypes__.OperationalError||t.isOperational===!0}function b(t){return y(t)&&F.propertyIsWritable(t,\"stack\")}function w(t){return{}.toString.call(t)}function C(t,e,n){for(var r=F.names(t),i=0;i10||t[0]>0}(),B.nodeSupportsAsyncResource=B.isNode&&function(){var e=!1;try{var n=t(\"async_hooks\").AsyncResource;e=\"function\"==typeof n.prototype.runInAsyncScope}catch(r){e=!1}return e}(),B.isNode&&B.toFastProperties(process);try{throw new Error}catch(M){B.lastLineError=M}e.exports=B},{\"./es5\":13,async_hooks:void 0}]},{},[4])(4)}),\"undefined\"!=typeof window&&null!==window?window.P=window.Promise:\"undefined\"!=typeof self&&null!==self&&(self.P=self.Promise);\nvar parser =\n /******/\n (function(modules) { // webpackBootstrap\n /******/\n // The module cache\n /******/\n var installedModules = {};\n /******/\n /******/\n // The require function\n /******/\n function __webpack_require__(moduleId) {\n /******/\n /******/\n // Check if module is in cache\n /******/\n if (installedModules[moduleId]) {\n /******/\n return installedModules[moduleId].exports;\n /******/\n }\n /******/\n // Create a new module (and put it into the cache)\n /******/\n var module = installedModules[moduleId] = {\n /******/\n i: moduleId,\n /******/\n l: false,\n /******/\n exports: {}\n /******/\n };\n /******/\n /******/\n // Execute the module function\n /******/\n modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n /******/\n /******/\n // Flag the module as loaded\n /******/\n module.l = true;\n /******/\n /******/\n // Return the exports of the module\n /******/\n return module.exports;\n /******/\n }\n /******/\n /******/\n /******/\n // expose the modules object (__webpack_modules__)\n /******/\n __webpack_require__.m = modules;\n /******/\n /******/\n // expose the module cache\n /******/\n __webpack_require__.c = installedModules;\n /******/\n /******/\n // define getter function for harmony exports\n /******/\n __webpack_require__.d = function(exports, name, getter) {\n /******/\n if (!__webpack_require__.o(exports, name)) {\n /******/\n Object.defineProperty(exports, name, {\n enumerable: true,\n get: getter\n });\n /******/\n }\n /******/\n };\n /******/\n /******/\n // define __esModule on exports\n /******/\n __webpack_require__.r = function(exports) {\n /******/\n if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n /******/\n Object.defineProperty(exports, Symbol.toStringTag, {\n value: 'Module'\n });\n /******/\n }\n /******/\n Object.defineProperty(exports, '__esModule', {\n value: true\n });\n /******/\n };\n /******/\n /******/\n // create a fake namespace object\n /******/\n // mode & 1: value is a module id, require it\n /******/\n // mode & 2: merge all properties of value into the ns\n /******/\n // mode & 4: return value when already ns object\n /******/\n // mode & 8|1: behave like require\n /******/\n __webpack_require__.t = function(value, mode) {\n /******/\n if (mode & 1) value = __webpack_require__(value);\n /******/\n if (mode & 8) return value;\n /******/\n if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n /******/\n var ns = Object.create(null);\n /******/\n __webpack_require__.r(ns);\n /******/\n Object.defineProperty(ns, 'default', {\n enumerable: true,\n value: value\n });\n /******/\n if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function(key) {\n return value[key];\n }.bind(null, key));\n /******/\n return ns;\n /******/\n };\n /******/\n /******/\n // getDefaultExport function for compatibility with non-harmony modules\n /******/\n __webpack_require__.n = function(module) {\n /******/\n var getter = module && module.__esModule ?\n /******/\n function getDefault() {\n return module['default'];\n } :\n /******/\n function getModuleExports() {\n return module;\n };\n /******/\n __webpack_require__.d(getter, 'a', getter);\n /******/\n return getter;\n /******/\n };\n /******/\n /******/\n // Object.prototype.hasOwnProperty.call\n /******/\n __webpack_require__.o = function(object, property) {\n return Object.prototype.hasOwnProperty.call(object, property);\n };\n /******/\n /******/\n // __webpack_public_path__\n /******/\n __webpack_require__.p = \"\";\n /******/\n /******/\n /******/\n // Load entry module and return exports\n /******/\n return __webpack_require__(__webpack_require__.s = \"./src/parser.js\");\n /******/\n })\n /************************************************************************/\n /******/\n ({\n\n /***/\n \"./src/json2xml.js\":\n /*!*************************!*\\\n !*** ./src/json2xml.js ***!\n \\*************************/\n /*! no static exports found */\n /***/\n (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n //parse Empty Node as self closing node\n var buildOptions = __webpack_require__( /*! ./util */ \"./src/util.js\").buildOptions;\n var defaultOptions = {\n attributeNamePrefix: '@_',\n attrNodeName: false,\n textNodeName: '#text',\n ignoreAttributes: true,\n cdataTagName: false,\n cdataPositionChar: '\\\\c',\n format: false,\n indentBy: ' ',\n supressEmptyNode: false,\n tagValueProcessor: function tagValueProcessor(a) {\n return a;\n },\n attrValueProcessor: function attrValueProcessor(a) {\n return a;\n }\n };\n var props = ['attributeNamePrefix', 'attrNodeName', 'textNodeName', 'ignoreAttributes', 'cdataTagName', 'cdataPositionChar', 'format', 'indentBy', 'supressEmptyNode', 'tagValueProcessor', 'attrValueProcessor'];\n\n function Parser(options) {\n this.options = buildOptions(options, defaultOptions, props);\n if (this.options.ignoreAttributes || this.options.attrNodeName) {\n this.isAttribute = function() /*a*/\n {\n return false;\n };\n } else {\n this.attrPrefixLen = this.options.attributeNamePrefix.length;\n this.isAttribute = isAttribute;\n }\n if (this.options.cdataTagName) {\n this.isCDATA = isCDATA;\n } else {\n this.isCDATA = function() /*a*/\n {\n return false;\n };\n }\n this.replaceCDATAstr = replaceCDATAstr;\n this.replaceCDATAarr = replaceCDATAarr;\n if (this.options.format) {\n this.indentate = indentate;\n this.tagEndChar = '>\\n';\n this.newLine = '\\n';\n } else {\n this.indentate = function() {\n return '';\n };\n this.tagEndChar = '>';\n this.newLine = '';\n }\n if (this.options.supressEmptyNode) {\n this.buildTextNode = buildEmptyTextNode;\n this.buildObjNode = buildEmptyObjNode;\n } else {\n this.buildTextNode = buildTextValNode;\n this.buildObjNode = buildObjectNode;\n }\n this.buildTextValNode = buildTextValNode;\n this.buildObjectNode = buildObjectNode;\n }\n Parser.prototype.parse = function(jObj) {\n return this.j2x(jObj, 0).val;\n };\n Parser.prototype.j2x = function(jObj, level) {\n var attrStr = '';\n var val = '';\n var keys = Object.keys(jObj);\n var len = keys.length;\n for (var i = 0; i < len; i++) {\n var key = keys[i];\n if (typeof jObj[key] === 'undefined') { // supress undefined node\n } else if (jObj[key] === null) {\n val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;\n } else if (jObj[key] instanceof Date) {\n val += this.buildTextNode(jObj[key], key, '', level);\n } else if (typeof jObj[key] !== 'object') { //premitive type\n var attr = this.isAttribute(key);\n if (attr) {\n attrStr += ' ' + attr + '=\"' + this.options.attrValueProcessor('' + jObj[key]) + '\"';\n } else if (this.isCDATA(key)) {\n if (jObj[this.options.textNodeName]) {\n val += this.replaceCDATAstr(jObj[this.options.textNodeName], jObj[key]);\n } else {\n val += this.replaceCDATAstr('', jObj[key]);\n }\n } else { //tag value\n if (key === this.options.textNodeName) {\n if (jObj[this.options.cdataTagName]) { //value will added while processing cdata\n } else {\n val += this.options.tagValueProcessor('' + jObj[key]);\n }\n } else {\n val += this.buildTextNode(jObj[key], key, '', level);\n }\n }\n } else if (Array.isArray(jObj[key])) { //repeated nodes\n if (this.isCDATA(key)) {\n val += this.indentate(level);\n if (jObj[this.options.textNodeName]) {\n val += this.replaceCDATAarr(jObj[this.options.textNodeName], jObj[key]);\n } else {\n val += this.replaceCDATAarr('', jObj[key]);\n }\n } else { //nested nodes\n var arrLen = jObj[key].length;\n for (var j = 0; j < arrLen; j++) {\n var item = jObj[key][j];\n if (typeof item === 'undefined') { // supress undefined node\n } else if (item === null) {\n val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;\n } else if (typeof item === 'object') {\n var result = this.j2x(item, level + 1);\n val += this.buildObjNode(result.val, key, result.attrStr, level);\n } else {\n val += this.buildTextNode(item, key, '', level);\n }\n }\n }\n } else { //nested node\n if (this.options.attrNodeName && key === this.options.attrNodeName) {\n var Ks = Object.keys(jObj[key]);\n var L = Ks.length;\n for (var _j = 0; _j < L; _j++) {\n attrStr += ' ' + Ks[_j] + '=\"' + this.options.attrValueProcessor('' + jObj[key][Ks[_j]]) + '\"';\n }\n } else {\n var _result = this.j2x(jObj[key], level + 1);\n val += this.buildObjNode(_result.val, key, _result.attrStr, level);\n }\n }\n }\n return {\n attrStr: attrStr,\n val: val\n };\n };\n\n function replaceCDATAstr(str, cdata) {\n str = this.options.tagValueProcessor('' + str);\n if (this.options.cdataPositionChar === '' || str === '') {\n return str + '');\n }\n return str + this.newLine;\n }\n }\n function buildObjectNode(val, key, attrStr, level) {\n if (attrStr && !val.includes('<')) {\n return this.indentate(level) + '<' + key + attrStr + '>' + val + //+ this.newLine\n // + this.indentate(level)\n '' + this.options.tagValueProcessor(val) + ' 1) {\n jObj[tagname] = [];\n for (var tag in node.child[tagname]) {\n jObj[tagname].push(convertToJson(node.child[tagname][tag], options));\n }\n } else {\n if (options.arrayMode === true) {\n var result = convertToJson(node.child[tagname][0], options);\n if (typeof result === 'object') jObj[tagname] = [result];\n else jObj[tagname] = result;\n } else if (options.arrayMode === \"strict\") {\n jObj[tagname] = [convertToJson(node.child[tagname][0], options)];\n } else {\n jObj[tagname] = convertToJson(node.child[tagname][0], options);\n }\n }\n } //add value\n return jObj;\n };\n exports.convertToJson = convertToJson;\n\n /***/\n }),\n\n /***/\n \"./src/node2json_str.js\":\n /*!******************************!*\\\n !*** ./src/node2json_str.js ***!\n \\******************************/\n /*! no static exports found */\n /***/\n (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n var util = __webpack_require__( /*! ./util */ \"./src/util.js\");\n var buildOptions = __webpack_require__( /*! ./util */ \"./src/util.js\").buildOptions;\n var x2j = __webpack_require__( /*! ./xmlstr2xmlnode */ \"./src/xmlstr2xmlnode.js\"); //TODO: do it later\n var convertToJsonString = function convertToJsonString(node, options) {\n options = buildOptions(options, x2j.defaultOptions, x2j.props);\n options.indentBy = options.indentBy || '';\n return _cToJsonStr(node, options, 0);\n };\n var _cToJsonStr = function _cToJsonStr(node, options, level) {\n var jObj = '{'; //traver through all the children\n var keys = Object.keys(node.child);\n for (var index = 0; index < keys.length; index++) {\n var tagname = keys[index];\n if (node.child[tagname] && node.child[tagname].length > 1) {\n jObj += '\"' + tagname + '\" : [ ';\n for (var tag in node.child[tagname]) {\n jObj += _cToJsonStr(node.child[tagname][tag], options) + ' , ';\n }\n jObj = jObj.substr(0, jObj.length - 1) + ' ] '; //remove extra comma in last\n } else {\n jObj += '\"' + tagname + '\" : ' + _cToJsonStr(node.child[tagname][0], options) + ' ,';\n }\n }\n util.merge(jObj, node.attrsMap); //add attrsMap as new children\n if (util.isEmptyObject(jObj)) {\n return util.isExist(node.val) ? node.val : '';\n } else {\n if (util.isExist(node.val)) {\n if (!(typeof node.val === 'string' && (node.val === '' || node.val === options.cdataPositionChar))) {\n jObj += '\"' + options.textNodeName + '\" : ' + stringval(node.val);\n }\n }\n } //add value\n if (jObj[jObj.length - 1] === ',') {\n jObj = jObj.substr(0, jObj.length - 2);\n }\n return jObj + '}';\n };\n\n function stringval(v) {\n if (v === true || v === false || !isNaN(v)) {\n return v;\n } else {\n return '\"' + v + '\"';\n }\n }\n function indentate(options, level) {\n return options.indentBy.repeat(level);\n }\n exports.convertToJsonString = convertToJsonString;\n\n /***/\n }),\n\n /***/\n \"./src/parser.js\":\n /*!***********************!*\\\n !*** ./src/parser.js ***!\n \\***********************/\n /*! no static exports found */\n /***/\n (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n var nodeToJson = __webpack_require__( /*! ./node2json */ \"./src/node2json.js\");\n var xmlToNodeobj = __webpack_require__( /*! ./xmlstr2xmlnode */ \"./src/xmlstr2xmlnode.js\");\n var x2xmlnode = __webpack_require__( /*! ./xmlstr2xmlnode */ \"./src/xmlstr2xmlnode.js\");\n var buildOptions = __webpack_require__( /*! ./util */ \"./src/util.js\").buildOptions;\n var validator = __webpack_require__( /*! ./validator */ \"./src/validator.js\");\n exports.parse = function(xmlData, options, validationOption) {\n if (validationOption) {\n if (validationOption === true) validationOption = {};\n var result = validator.validate(xmlData, validationOption);\n if (result !== true) {\n throw Error(result.err.msg);\n }\n }\n options = buildOptions(options, x2xmlnode.defaultOptions, x2xmlnode.props);\n return nodeToJson.convertToJson(xmlToNodeobj.getTraversalObj(xmlData, options), options);\n };\n exports.convertTonimn = __webpack_require__( /*! ../src/nimndata */ \"./src/nimndata.js\").convert2nimn;\n exports.getTraversalObj = xmlToNodeobj.getTraversalObj;\n exports.convertToJson = nodeToJson.convertToJson;\n exports.convertToJsonString = __webpack_require__( /*! ./node2json_str */ \"./src/node2json_str.js\").convertToJsonString;\n exports.validate = validator.validate;\n exports.j2xParser = __webpack_require__( /*! ./json2xml */ \"./src/json2xml.js\");\n exports.parseToNimn = function(xmlData, schema, options) {\n return exports.convertTonimn(exports.getTraversalObj(xmlData, options), schema, options);\n };\n\n /***/\n }),\n\n /***/\n \"./src/util.js\":\n /*!*********************!*\\\n !*** ./src/util.js ***!\n \\*********************/\n /*! no static exports found */\n /***/\n (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n var getAllMatches = function getAllMatches(string, regex) {\n var matches = [];\n var match = regex.exec(string);\n while (match) {\n var allmatches = [];\n var len = match.length;\n for (var index = 0; index < len; index++) {\n allmatches.push(match[index]);\n }\n matches.push(allmatches);\n match = regex.exec(string);\n }\n return matches;\n };\n var doesMatch = function doesMatch(string, regex) {\n var match = regex.exec(string);\n return !(match === null || typeof match === 'undefined');\n };\n var doesNotMatch = function doesNotMatch(string, regex) {\n return !doesMatch(string, regex);\n };\n exports.isExist = function(v) {\n return typeof v !== 'undefined';\n };\n exports.isEmptyObject = function(obj) {\n return Object.keys(obj).length === 0;\n };\n /**\n * Copy all the properties of a into b.\n * @param {*} target\n * @param {*} a\n */\n exports.merge = function(target, a, arrayMode) {\n if (a) {\n var keys = Object.keys(a); // will return an array of own properties\n var len = keys.length; //don't make it inline\n for (var i = 0; i < len; i++) {\n if (arrayMode === 'strict') {\n target[keys[i]] = [a[keys[i]]];\n } else {\n target[keys[i]] = a[keys[i]];\n }\n }\n }\n };\n /* exports.merge =function (b,a){\n return Object.assign(b,a);\n } */\n exports.getValue = function(v) {\n if (exports.isExist(v)) {\n return v;\n } else {\n return '';\n }\n }; // const fakeCall = function(a) {return a;};\n // const fakeCallNoReturn = function() {};\n exports.buildOptions = function(options, defaultOptions, props) {\n var newOptions = {};\n if (!options) {\n return defaultOptions; //if there are not options\n }\n for (var i = 0; i < props.length; i++) {\n if (options[props[i]] !== undefined) {\n newOptions[props[i]] = options[props[i]];\n } else {\n newOptions[props[i]] = defaultOptions[props[i]];\n }\n }\n return newOptions;\n };\n exports.doesMatch = doesMatch;\n exports.doesNotMatch = doesNotMatch;\n exports.getAllMatches = getAllMatches;\n\n /***/\n }),\n\n /***/\n \"./src/validator.js\":\n /*!**************************!*\\\n !*** ./src/validator.js ***!\n \\**************************/\n /*! no static exports found */\n /***/\n (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n var util = __webpack_require__( /*! ./util */ \"./src/util.js\");\n var defaultOptions = {\n allowBooleanAttributes: false, //A tag can have attributes without any value\n localeRange: 'a-zA-Z'\n };\n var props = ['allowBooleanAttributes', 'localeRange']; //const tagsPattern = new RegExp(\"<\\\\/?([\\\\w:\\\\-_\\.]+)\\\\s*\\/?>\",\"g\");\n exports.validate = function(xmlData, options) {\n options = util.buildOptions(options, defaultOptions, props); //xmlData = xmlData.replace(/(\\r\\n|\\n|\\r)/gm,\"\");//make it single line\n //xmlData = xmlData.replace(/(^\\s*<\\?xml.*?\\?>)/g,\"\");//Remove XML starting tag\n //xmlData = xmlData.replace(/()/g,\"\");//Remove DOCTYPE\n var localRangeRegex = new RegExp(\"[\" + options.localeRange + \"]\");\n if (localRangeRegex.test(\"<#$'\\\"\\\\\\/:0\")) {\n return getErrorObject('InvalidOptions', 'Invalid localeRange', 1);\n }\n var tags = [];\n var tagFound = false; //indicates that the root tag has been closed (aka. depth 0 has been reached)\n var reachedRoot = false;\n if (xmlData[0] === \"\\uFEFF\") { // check for byte order mark (BOM)\n xmlData = xmlData.substr(1);\n }\n var regxAttrName = new RegExp(\"^[\" + options.localeRange + \"_][\" + options.localeRange + \"0-9\\\\-\\\\.:]*$\");\n var regxTagName = new RegExp(\"^([\" + options.localeRange + \"_])[\" + options.localeRange + \"0-9\\\\.\\\\-_:]*$\");\n for (var i = 0; i < xmlData.length; i++) {\n if (xmlData[i] === '<') { //starting of tag\n //read until you reach to '>' avoiding any '>' in attribute value\n i++;\n if (xmlData[i] === '?') {\n i = readPI(xmlData, ++i);\n if (i.err) {\n return i;\n }\n } else if (xmlData[i] === '!') {\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n var closingTag = false;\n if (xmlData[i] === '/') { //closing tag\n closingTag = true;\n i++;\n } //read tagname\n var tagName = '';\n for (; i < xmlData.length && xmlData[i] !== '>' && xmlData[i] !== ' ' && xmlData[i] !== '\\t' && xmlData[i] !== '\\n' && xmlData[i] !== '\\r'; i++) {\n tagName += xmlData[i];\n }\n tagName = tagName.trim(); //console.log(tagName);\n if (tagName[tagName.length - 1] === '/') { //self closing tag without attributes\n tagName = tagName.substring(0, tagName.length - 1); //continue;\n i--;\n }\n if (!validateTagName(tagName, regxTagName)) {\n var msg = void 0;\n if (tagName.trim().length === 0) {\n msg = \"There is an unnecessary space between tag name and backward slash ' 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' can't have attributes or invalid starting.\", getLineNumberForPosition(xmlData, i));\n } else {\n var otg = tags.pop();\n if (tagName !== otg) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + otg + \"' is expected inplace of '\" + tagName + \"'.\", getLineNumberForPosition(xmlData, i));\n } //when there are no more tags, we reached the root level.\n if (tags.length == 0) {\n reachedRoot = true;\n }\n }\n } else {\n var _isValid = validateAttributeString(attrStr, options, regxAttrName);\n if (_isValid !== true) { //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(_isValid.err.code, _isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + _isValid.err.line));\n } //if the root level has been reached before ...\n if (reachedRoot === true) {\n return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));\n } else {\n tags.push(tagName);\n }\n tagFound = true;\n } //skip tag text value\n //It may include comments and CDATA value\n for (i++; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n if (xmlData[i + 1] === '!') { //comment or CADATA\n i++;\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n break;\n }\n }\n } //end of reading tag text value\n if (xmlData[i] === '<') {\n i--;\n }\n }\n } else {\n if (xmlData[i] === ' ' || xmlData[i] === '\\t' || xmlData[i] === '\\n' || xmlData[i] === '\\r') {\n continue;\n }\n return getErrorObject('InvalidChar', \"char '\" + xmlData[i] + \"' is not expected.\", getLineNumberForPosition(xmlData, i));\n }\n }\n if (!tagFound) {\n return getErrorObject('InvalidXml', 'Start tag expected.', 1);\n } else if (tags.length > 0) {\n return getErrorObject('InvalidXml', \"Invalid '\" + JSON.stringify(tags, null, 4).replace(/\\r?\\n/g, '') + \"' found.\", 1);\n }\n return true;\n };\n /**\n * Read Processing insstructions and skip\n * @param {*} xmlData\n * @param {*} i\n */\n function readPI(xmlData, i) {\n var start = i;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] == '?' || xmlData[i] == ' ') { //tagname\n var tagname = xmlData.substr(start, i - start);\n if (i > 5 && tagname === 'xml') {\n return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));\n } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') { //check if valid attribut string\n i++;\n break;\n } else {\n continue;\n }\n }\n }\n return i;\n }\n function readCommentAndCDATA(xmlData, i) {\n if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') { //comment\n for (i += 3; i < xmlData.length; i++) {\n if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n } else if (xmlData.length > i + 8 && xmlData[i + 1] === 'D' && xmlData[i + 2] === 'O' && xmlData[i + 3] === 'C' && xmlData[i + 4] === 'T' && xmlData[i + 5] === 'Y' && xmlData[i + 6] === 'P' && xmlData[i + 7] === 'E') {\n var angleBracketsCount = 1;\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n angleBracketsCount++;\n } else if (xmlData[i] === '>') {\n angleBracketsCount--;\n if (angleBracketsCount === 0) {\n break;\n }\n }\n }\n } else if (xmlData.length > i + 9 && xmlData[i + 1] === '[' && xmlData[i + 2] === 'C' && xmlData[i + 3] === 'D' && xmlData[i + 4] === 'A' && xmlData[i + 5] === 'T' && xmlData[i + 6] === 'A' && xmlData[i + 7] === '[') {\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n }\n return i;\n }\n var doubleQuote = '\"';\n var singleQuote = \"'\";\n /**\n * Keep reading xmlData until '<' is found outside the attribute value.\n * @param {string} xmlData\n * @param {number} i\n */\n function readAttributeStr(xmlData, i) {\n var attrStr = '';\n var startChar = '';\n var tagClosed = false;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {\n if (startChar === '') {\n startChar = xmlData[i];\n } else if (startChar !== xmlData[i]) { //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa\n continue;\n } else {\n startChar = '';\n }\n } else if (xmlData[i] === '>') {\n if (startChar === '') {\n tagClosed = true;\n break;\n }\n }\n attrStr += xmlData[i];\n }\n if (startChar !== '') {\n return false;\n }\n return {\n value: attrStr,\n index: i,\n tagClosed: tagClosed\n };\n }\n /**\n * Select all the attributes whether valid or invalid.\n */\n var validAttrStrRegxp = new RegExp('(\\\\s*)([^\\\\s=]+)(\\\\s*=)?(\\\\s*([\\'\"])(([\\\\s\\\\S])*?)\\\\5)?', 'g'); //attr, =\"sd\", a=\"amit's\", a=\"sd\"b=\"saf\", ab cd=\"\"\n function validateAttributeString(attrStr, options, regxAttrName) { //console.log(\"start:\"+attrStr+\":end\");\n //if(attrStr.trim().length === 0) return true; //empty string\n var matches = util.getAllMatches(attrStr, validAttrStrRegxp);\n var attrNames = {};\n for (var i = 0; i < matches.length; i++) {\n if (matches[i][1].length === 0) { //nospace before attribute name: a=\"sd\"b=\"saf\"\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' has no space in starting.\", getPositionFromMatch(attrStr, matches[i][0]));\n } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) { //independent attribute: ab\n return getErrorObject('InvalidAttr', \"boolean attribute '\" + matches[i][2] + \"' is not allowed.\", getPositionFromMatch(attrStr, matches[i][0]));\n }\n /* else if(matches[i][6] === undefined){//attribute without value: ab=\n return { err: { code:\"InvalidAttr\",msg:\"attribute \" + matches[i][2] + \" has no value assigned.\"}};\n } */\n var attrName = matches[i][2];\n if (!validateAttrName(attrName, regxAttrName)) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is an invalid name.\", getPositionFromMatch(attrStr, matches[i][0]));\n }\n if (!attrNames.hasOwnProperty(attrName)) { //check for duplicate attribute.\n attrNames[attrName] = 1;\n } else {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is repeated.\", getPositionFromMatch(attrStr, matches[i][0]));\n }\n }\n return true;\n }\n function getErrorObject(code, message, lineNumber) {\n return {\n err: {\n code: code,\n msg: message,\n line: lineNumber\n }\n };\n }\n function validateAttrName(attrName, regxAttrName) { // const validAttrRegxp = new RegExp(regxAttrName);\n return util.doesMatch(attrName, regxAttrName);\n } //const startsWithXML = new RegExp(\"^[Xx][Mm][Ll]\");\n // startsWith = /^([a-zA-Z]|_)[\\w.\\-_:]*/;\n function validateTagName(tagname, regxTagName) {\n /*if(util.doesMatch(tagname,startsWithXML)) return false;\n else*/\n //return !tagname.toLowerCase().startsWith(\"xml\") || !util.doesNotMatch(tagname, regxTagName);\n return !util.doesNotMatch(tagname, regxTagName);\n } //this function returns the line number for the character at the given index\n function getLineNumberForPosition(xmlData, index) {\n var lines = xmlData.substring(0, index).split(/\\r?\\n/);\n return lines.length;\n } //this function returns the position of the last character of match within attrStr\n function getPositionFromMatch(attrStr, match) {\n return attrStr.indexOf(match) + match.length;\n }\n\n /***/\n }),\n\n /***/\n \"./src/xmlNode.js\":\n /*!************************!*\\\n !*** ./src/xmlNode.js ***!\n \\************************/\n /*! no static exports found */\n /***/\n (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n module.exports = function(tagname, parent, val) {\n this.tagname = tagname;\n this.parent = parent;\n this.child = {}; //child tags\n this.attrsMap = {}; //attributes map\n this.val = val; //text only\n this.addChild = function(child) {\n if (Array.isArray(this.child[child.tagname])) { //already presents\n this.child[child.tagname].push(child);\n } else {\n this.child[child.tagname] = [child];\n }\n };\n };\n\n /***/\n }),\n\n /***/\n \"./src/xmlstr2xmlnode.js\":\n /*!*******************************!*\\\n !*** ./src/xmlstr2xmlnode.js ***!\n \\*******************************/\n /*! no static exports found */\n /***/\n (function(module, exports, __webpack_require__) {\n\n \"use strict\";\n var util = __webpack_require__( /*! ./util */ \"./src/util.js\");\n var buildOptions = __webpack_require__( /*! ./util */ \"./src/util.js\").buildOptions;\n var xmlNode = __webpack_require__( /*! ./xmlNode */ \"./src/xmlNode.js\");\n var TagType = {\n OPENING: 1,\n CLOSING: 2,\n SELF: 3,\n CDATA: 4\n };\n var regx = '<((!\\\\[CDATA\\\\[([\\\\s\\\\S]*?)(]]>))|(([\\\\w:\\\\-._]*:)?([\\\\w:\\\\-._]+))([^>]*)>|((\\\\/)(([\\\\w:\\\\-._]*:)?([\\\\w:\\\\-._]+))\\\\s*>))([^<]*)'; //const tagsRegx = new RegExp(\"<(\\\\/?[\\\\w:\\\\-\\._]+)([^>]*)>(\\\\s*\"+cdataRegx+\")*([^<]+)?\",\"g\");\n //const tagsRegx = new RegExp(\"<(\\\\/?)((\\\\w*:)?([\\\\w:\\\\-\\._]+))([^>]*)>([^<]*)(\"+cdataRegx+\"([^<]*))*([^<]+)?\",\"g\");\n //polyfill\n if (!Number.parseInt && window.parseInt) {\n Number.parseInt = window.parseInt;\n }\n if (!Number.parseFloat && window.parseFloat) {\n Number.parseFloat = window.parseFloat;\n }\n var defaultOptions = {\n attributeNamePrefix: '@_',\n attrNodeName: false,\n textNodeName: '#text',\n ignoreAttributes: true,\n ignoreNameSpace: false,\n allowBooleanAttributes: false, //a tag can have attributes without any value\n //ignoreRootElement : false,\n parseNodeValue: true,\n parseAttributeValue: false,\n arrayMode: false,\n trimValues: true, //Trim string values of tag and attributes\n cdataTagName: false,\n cdataPositionChar: '\\\\c',\n localeRange: '',\n tagValueProcessor: function tagValueProcessor(a, tagName) {\n return a;\n },\n attrValueProcessor: function attrValueProcessor(a, attrName) {\n return a;\n },\n stopNodes: [] //decodeStrict: false,\n };\n exports.defaultOptions = defaultOptions;\n var props = ['attributeNamePrefix', 'attrNodeName', 'textNodeName', 'ignoreAttributes', 'ignoreNameSpace', 'allowBooleanAttributes', 'parseNodeValue', 'parseAttributeValue', 'arrayMode', 'trimValues', 'cdataTagName', 'cdataPositionChar', 'localeRange', 'tagValueProcessor', 'attrValueProcessor', 'parseTrueNumberOnly', 'stopNodes'];\n exports.props = props;\n var getTraversalObj = function getTraversalObj(xmlData, options) {\n options = buildOptions(options, defaultOptions, props); //xmlData = xmlData.replace(/\\r?\\n/g, \" \");//make it single line\n xmlData = xmlData.replace(//g, ''); //Remove comments\n var xmlObj = new xmlNode('!xml');\n var currentNode = xmlObj;\n regx = regx.replace(/\\[\\\\w/g, '[' + options.localeRange + '\\\\w');\n var tagsRegx = new RegExp(regx, 'g');\n var tag = tagsRegx.exec(xmlData);\n var nextTag = tagsRegx.exec(xmlData);\n while (tag) {\n var tagType = checkForTagType(tag);\n if (tagType === TagType.CLOSING) { //add parsed data to parent node\n if (currentNode.parent && tag[14]) {\n currentNode.parent.val = util.getValue(currentNode.parent.val) + '' + processTagValue(tag, options, currentNode.parent.tagname);\n }\n if (options.stopNodes.length && options.stopNodes.includes(currentNode.tagname)) {\n currentNode.child = [];\n if (currentNode.attrsMap == undefined) {\n currentNode.attrsMap = {};\n }\n currentNode.val = xmlData.substr(currentNode.startIndex + 1, tag.index - currentNode.startIndex - 1);\n }\n currentNode = currentNode.parent;\n } else if (tagType === TagType.CDATA) {\n if (options.cdataTagName) { //add cdata node\n var childNode = new xmlNode(options.cdataTagName, currentNode, tag[3]);\n childNode.attrsMap = buildAttributesMap(tag[8], options);\n currentNode.addChild(childNode); //for backtracking\n currentNode.val = util.getValue(currentNode.val) + options.cdataPositionChar; //add rest value to parent node\n if (tag[14]) {\n currentNode.val += processTagValue(tag, options);\n }\n } else {\n currentNode.val = (currentNode.val || '') + (tag[3] || '') + processTagValue(tag, options);\n }\n } else if (tagType === TagType.SELF) {\n if (currentNode && tag[14]) {\n currentNode.val = util.getValue(currentNode.val) + '' + processTagValue(tag, options);\n }\n var _childNode = new xmlNode(options.ignoreNameSpace ? tag[7] : tag[5], currentNode, '');\n if (tag[8] && tag[8].length > 0) {\n tag[8] = tag[8].substr(0, tag[8].length - 1);\n }\n _childNode.attrsMap = buildAttributesMap(tag[8], options);\n currentNode.addChild(_childNode);\n } else { //TagType.OPENING\n var _childNode2 = new xmlNode(options.ignoreNameSpace ? tag[7] : tag[5], currentNode, processTagValue(tag, options));\n if (options.stopNodes.length && options.stopNodes.includes(_childNode2.tagname)) {\n _childNode2.startIndex = tag.index + tag[1].length;\n }\n _childNode2.attrsMap = buildAttributesMap(tag[8], options);\n currentNode.addChild(_childNode2);\n currentNode = _childNode2;\n }\n tag = nextTag;\n nextTag = tagsRegx.exec(xmlData);\n }\n return xmlObj;\n };\n\n function processTagValue(parsedTags, options, parentTagName) {\n var tagName = parsedTags[7] || parentTagName;\n var val = parsedTags[14];\n if (val) {\n if (options.trimValues) {\n val = val.trim();\n }\n val = options.tagValueProcessor(val, tagName);\n val = parseValue(val, options.parseNodeValue, options.parseTrueNumberOnly);\n }\n return val;\n }\n function checkForTagType(match) {\n if (match[4] === ']]>') {\n return TagType.CDATA;\n } else if (match[10] === '/') {\n return TagType.CLOSING;\n } else if (typeof match[8] !== 'undefined' && match[8].substr(match[8].length - 1) === '/') {\n return TagType.SELF;\n } else {\n return TagType.OPENING;\n }\n }\n function resolveNameSpace(tagname, options) {\n if (options.ignoreNameSpace) {\n var tags = tagname.split(':');\n var prefix = tagname.charAt(0) === '/' ? '/' : '';\n if (tags[0] === 'xmlns') {\n return '';\n }\n if (tags.length === 2) {\n tagname = prefix + tags[1];\n }\n }\n return tagname;\n }\n function parseValue(val, shouldParse, parseTrueNumberOnly) {\n if (shouldParse && typeof val === 'string') {\n var parsed;\n if (val.trim() === '' || isNaN(val)) {\n parsed = val === 'true' ? true : val === 'false' ? false : val;\n } else {\n if (val.indexOf('0x') !== -1) { //support hexa decimal\n parsed = Number.parseInt(val, 16);\n } else if (val.indexOf('.') !== -1) {\n parsed = Number.parseFloat(val);\n val = val.replace(/0+$/, \"\");\n } else {\n parsed = Number.parseInt(val, 10);\n }\n if (parseTrueNumberOnly) {\n parsed = String(parsed) === val ? parsed : val;\n }\n }\n return parsed;\n } else {\n if (util.isExist(val)) {\n return val;\n } else {\n return '';\n }\n }\n } //TODO: change regex to capture NS\n //const attrsRegx = new RegExp(\"([\\\\w\\\\-\\\\.\\\\:]+)\\\\s*=\\\\s*(['\\\"])((.|\\n)*?)\\\\2\",\"gm\");\n var attrsRegx = new RegExp('([^\\\\s=]+)\\\\s*(=\\\\s*([\\'\"])(.*?)\\\\3)?', 'g');\n\n function buildAttributesMap(attrStr, options) {\n if (!options.ignoreAttributes && typeof attrStr === 'string') {\n attrStr = attrStr.replace(/\\r?\\n/g, ' '); //attrStr = attrStr || attrStr.trim();\n var matches = util.getAllMatches(attrStr, attrsRegx);\n var len = matches.length; //don't make it inline\n var attrs = {};\n for (var i = 0; i < len; i++) {\n var attrName = resolveNameSpace(matches[i][1], options);\n if (attrName.length) {\n if (matches[i][4] !== undefined) {\n if (options.trimValues) {\n matches[i][4] = matches[i][4].trim();\n }\n matches[i][4] = options.attrValueProcessor(matches[i][4], attrName);\n attrs[options.attributeNamePrefix + attrName] = parseValue(matches[i][4], options.parseAttributeValue, options.parseTrueNumberOnly);\n } else if (options.allowBooleanAttributes) {\n attrs[options.attributeNamePrefix + attrName] = true;\n }\n }\n }\n if (!Object.keys(attrs).length) {\n return;\n }\n if (options.attrNodeName) {\n var attrCollection = {};\n attrCollection[options.attrNodeName] = attrs;\n return attrCollection;\n }\n return attrs;\n }\n }\n exports.getTraversalObj = getTraversalObj;\n\n /***/\n })\n\n /******/\n });\n\n\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ISO6391\"] = factory();\n\telse\n\t\troot[\"ISO6391\"] = factory();\n})(typeof self !== 'undefined' ? self : this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./src/index.js\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./node_modules/babel-runtime/core-js/object/define-property.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = { \"default\": __webpack_require__(\"./node_modules/core-js/library/fn/object/define-property.js\"), __esModule: true };\n\n/***/ }),\n\n/***/ \"./node_modules/babel-runtime/core-js/object/keys.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = { \"default\": __webpack_require__(\"./node_modules/core-js/library/fn/object/keys.js\"), __esModule: true };\n\n/***/ }),\n\n/***/ \"./node_modules/babel-runtime/core-js/object/values.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = { \"default\": __webpack_require__(\"./node_modules/core-js/library/fn/object/values.js\"), __esModule: true };\n\n/***/ }),\n\n/***/ \"./node_modules/babel-runtime/helpers/classCallCheck.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nexports.__esModule = true;\n\nexports.default = function (instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n};\n\n/***/ }),\n\n/***/ \"./node_modules/babel-runtime/helpers/createClass.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nexports.__esModule = true;\n\nvar _defineProperty = __webpack_require__(\"./node_modules/babel-runtime/core-js/object/define-property.js\");\n\nvar _defineProperty2 = _interopRequireDefault(_defineProperty);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = function () {\n function defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n (0, _defineProperty2.default)(target, descriptor.key, descriptor);\n }\n }\n\n return function (Constructor, protoProps, staticProps) {\n if (protoProps) defineProperties(Constructor.prototype, protoProps);\n if (staticProps) defineProperties(Constructor, staticProps);\n return Constructor;\n };\n}();\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/fn/object/define-property.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n__webpack_require__(\"./node_modules/core-js/library/modules/es6.object.define-property.js\");\nvar $Object = __webpack_require__(\"./node_modules/core-js/library/modules/_core.js\").Object;\nmodule.exports = function defineProperty(it, key, desc) {\n return $Object.defineProperty(it, key, desc);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/fn/object/keys.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n__webpack_require__(\"./node_modules/core-js/library/modules/es6.object.keys.js\");\nmodule.exports = __webpack_require__(\"./node_modules/core-js/library/modules/_core.js\").Object.keys;\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/fn/object/values.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n__webpack_require__(\"./node_modules/core-js/library/modules/es7.object.values.js\");\nmodule.exports = __webpack_require__(\"./node_modules/core-js/library/modules/_core.js\").Object.values;\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_a-function.js\":\n/***/ (function(module, exports) {\n\nmodule.exports = function (it) {\n if (typeof it != 'function') throw TypeError(it + ' is not a function!');\n return it;\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_an-object.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar isObject = __webpack_require__(\"./node_modules/core-js/library/modules/_is-object.js\");\nmodule.exports = function (it) {\n if (!isObject(it)) throw TypeError(it + ' is not an object!');\n return it;\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_array-includes.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = __webpack_require__(\"./node_modules/core-js/library/modules/_to-iobject.js\");\nvar toLength = __webpack_require__(\"./node_modules/core-js/library/modules/_to-length.js\");\nvar toAbsoluteIndex = __webpack_require__(\"./node_modules/core-js/library/modules/_to-absolute-index.js\");\nmodule.exports = function (IS_INCLUDES) {\n return function ($this, el, fromIndex) {\n var O = toIObject($this);\n var length = toLength(O.length);\n var index = toAbsoluteIndex(fromIndex, length);\n var value;\n // Array#includes uses SameValueZero equality algorithm\n // eslint-disable-next-line no-self-compare\n if (IS_INCLUDES && el != el) while (length > index) {\n value = O[index++];\n // eslint-disable-next-line no-self-compare\n if (value != value) return true;\n // Array#indexOf ignores holes, Array#includes - not\n } else for (;length > index; index++) if (IS_INCLUDES || index in O) {\n if (O[index] === el) return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_cof.js\":\n/***/ (function(module, exports) {\n\nvar toString = {}.toString;\n\nmodule.exports = function (it) {\n return toString.call(it).slice(8, -1);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_core.js\":\n/***/ (function(module, exports) {\n\nvar core = module.exports = { version: '2.5.1' };\nif (typeof __e == 'number') __e = core; // eslint-disable-line no-undef\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_ctx.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// optional / simple context binding\nvar aFunction = __webpack_require__(\"./node_modules/core-js/library/modules/_a-function.js\");\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_defined.js\":\n/***/ (function(module, exports) {\n\n// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_descriptors.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// Thank's IE8 for his funny defineProperty\nmodule.exports = !__webpack_require__(\"./node_modules/core-js/library/modules/_fails.js\")(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_dom-create.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar isObject = __webpack_require__(\"./node_modules/core-js/library/modules/_is-object.js\");\nvar document = __webpack_require__(\"./node_modules/core-js/library/modules/_global.js\").document;\n// typeof document.createElement is 'object' in old IE\nvar is = isObject(document) && isObject(document.createElement);\nmodule.exports = function (it) {\n return is ? document.createElement(it) : {};\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_enum-bug-keys.js\":\n/***/ (function(module, exports) {\n\n// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_export.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar global = __webpack_require__(\"./node_modules/core-js/library/modules/_global.js\");\nvar core = __webpack_require__(\"./node_modules/core-js/library/modules/_core.js\");\nvar ctx = __webpack_require__(\"./node_modules/core-js/library/modules/_ctx.js\");\nvar hide = __webpack_require__(\"./node_modules/core-js/library/modules/_hide.js\");\nvar PROTOTYPE = 'prototype';\n\nvar $export = function (type, name, source) {\n var IS_FORCED = type & $export.F;\n var IS_GLOBAL = type & $export.G;\n var IS_STATIC = type & $export.S;\n var IS_PROTO = type & $export.P;\n var IS_BIND = type & $export.B;\n var IS_WRAP = type & $export.W;\n var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});\n var expProto = exports[PROTOTYPE];\n var target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE];\n var key, own, out;\n if (IS_GLOBAL) source = name;\n for (key in source) {\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n if (own && key in exports) continue;\n // export native or passed\n out = own ? target[key] : source[key];\n // prevent global pollution for namespaces\n exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key]\n // bind timers to global for call from export context\n : IS_BIND && own ? ctx(out, global)\n // wrap global constructors for prevent change them in library\n : IS_WRAP && target[key] == out ? (function (C) {\n var F = function (a, b, c) {\n if (this instanceof C) {\n switch (arguments.length) {\n case 0: return new C();\n case 1: return new C(a);\n case 2: return new C(a, b);\n } return new C(a, b, c);\n } return C.apply(this, arguments);\n };\n F[PROTOTYPE] = C[PROTOTYPE];\n return F;\n // make static versions for prototype methods\n })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // export proto methods to core.%CONSTRUCTOR%.methods.%NAME%\n if (IS_PROTO) {\n (exports.virtual || (exports.virtual = {}))[key] = out;\n // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME%\n if (type & $export.R && expProto && !expProto[key]) hide(expProto, key, out);\n }\n }\n};\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library`\nmodule.exports = $export;\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_fails.js\":\n/***/ (function(module, exports) {\n\nmodule.exports = function (exec) {\n try {\n return !!exec();\n } catch (e) {\n return true;\n }\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_global.js\":\n/***/ (function(module, exports) {\n\n// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self\n // eslint-disable-next-line no-new-func\n : Function('return this')();\nif (typeof __g == 'number') __g = global; // eslint-disable-line no-undef\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_has.js\":\n/***/ (function(module, exports) {\n\nvar hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function (it, key) {\n return hasOwnProperty.call(it, key);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_hide.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar dP = __webpack_require__(\"./node_modules/core-js/library/modules/_object-dp.js\");\nvar createDesc = __webpack_require__(\"./node_modules/core-js/library/modules/_property-desc.js\");\nmodule.exports = __webpack_require__(\"./node_modules/core-js/library/modules/_descriptors.js\") ? function (object, key, value) {\n return dP.f(object, key, createDesc(1, value));\n} : function (object, key, value) {\n object[key] = value;\n return object;\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_ie8-dom-define.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = !__webpack_require__(\"./node_modules/core-js/library/modules/_descriptors.js\") && !__webpack_require__(\"./node_modules/core-js/library/modules/_fails.js\")(function () {\n return Object.defineProperty(__webpack_require__(\"./node_modules/core-js/library/modules/_dom-create.js\")('div'), 'a', { get: function () { return 7; } }).a != 7;\n});\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_iobject.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = __webpack_require__(\"./node_modules/core-js/library/modules/_cof.js\");\n// eslint-disable-next-line no-prototype-builtins\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_is-object.js\":\n/***/ (function(module, exports) {\n\nmodule.exports = function (it) {\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_object-dp.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar anObject = __webpack_require__(\"./node_modules/core-js/library/modules/_an-object.js\");\nvar IE8_DOM_DEFINE = __webpack_require__(\"./node_modules/core-js/library/modules/_ie8-dom-define.js\");\nvar toPrimitive = __webpack_require__(\"./node_modules/core-js/library/modules/_to-primitive.js\");\nvar dP = Object.defineProperty;\n\nexports.f = __webpack_require__(\"./node_modules/core-js/library/modules/_descriptors.js\") ? Object.defineProperty : function defineProperty(O, P, Attributes) {\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if (IE8_DOM_DEFINE) try {\n return dP(O, P, Attributes);\n } catch (e) { /* empty */ }\n if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');\n if ('value' in Attributes) O[P] = Attributes.value;\n return O;\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_object-keys-internal.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar has = __webpack_require__(\"./node_modules/core-js/library/modules/_has.js\");\nvar toIObject = __webpack_require__(\"./node_modules/core-js/library/modules/_to-iobject.js\");\nvar arrayIndexOf = __webpack_require__(\"./node_modules/core-js/library/modules/_array-includes.js\")(false);\nvar IE_PROTO = __webpack_require__(\"./node_modules/core-js/library/modules/_shared-key.js\")('IE_PROTO');\n\nmodule.exports = function (object, names) {\n var O = toIObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (has(O, key = names[i++])) {\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_object-keys.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = __webpack_require__(\"./node_modules/core-js/library/modules/_object-keys-internal.js\");\nvar enumBugKeys = __webpack_require__(\"./node_modules/core-js/library/modules/_enum-bug-keys.js\");\n\nmodule.exports = Object.keys || function keys(O) {\n return $keys(O, enumBugKeys);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_object-pie.js\":\n/***/ (function(module, exports) {\n\nexports.f = {}.propertyIsEnumerable;\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_object-sap.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// most Object methods by ES6 should accept primitives\nvar $export = __webpack_require__(\"./node_modules/core-js/library/modules/_export.js\");\nvar core = __webpack_require__(\"./node_modules/core-js/library/modules/_core.js\");\nvar fails = __webpack_require__(\"./node_modules/core-js/library/modules/_fails.js\");\nmodule.exports = function (KEY, exec) {\n var fn = (core.Object || {})[KEY] || Object[KEY];\n var exp = {};\n exp[KEY] = exec(fn);\n $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_object-to-array.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar getKeys = __webpack_require__(\"./node_modules/core-js/library/modules/_object-keys.js\");\nvar toIObject = __webpack_require__(\"./node_modules/core-js/library/modules/_to-iobject.js\");\nvar isEnum = __webpack_require__(\"./node_modules/core-js/library/modules/_object-pie.js\").f;\nmodule.exports = function (isEntries) {\n return function (it) {\n var O = toIObject(it);\n var keys = getKeys(O);\n var length = keys.length;\n var i = 0;\n var result = [];\n var key;\n while (length > i) if (isEnum.call(O, key = keys[i++])) {\n result.push(isEntries ? [key, O[key]] : O[key]);\n } return result;\n };\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_property-desc.js\":\n/***/ (function(module, exports) {\n\nmodule.exports = function (bitmap, value) {\n return {\n enumerable: !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable: !(bitmap & 4),\n value: value\n };\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_shared-key.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar shared = __webpack_require__(\"./node_modules/core-js/library/modules/_shared.js\")('keys');\nvar uid = __webpack_require__(\"./node_modules/core-js/library/modules/_uid.js\");\nmodule.exports = function (key) {\n return shared[key] || (shared[key] = uid(key));\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_shared.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar global = __webpack_require__(\"./node_modules/core-js/library/modules/_global.js\");\nvar SHARED = '__core-js_shared__';\nvar store = global[SHARED] || (global[SHARED] = {});\nmodule.exports = function (key) {\n return store[key] || (store[key] = {});\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_to-absolute-index.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar toInteger = __webpack_require__(\"./node_modules/core-js/library/modules/_to-integer.js\");\nvar max = Math.max;\nvar min = Math.min;\nmodule.exports = function (index, length) {\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_to-integer.js\":\n/***/ (function(module, exports) {\n\n// 7.1.4 ToInteger\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nmodule.exports = function (it) {\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_to-iobject.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = __webpack_require__(\"./node_modules/core-js/library/modules/_iobject.js\");\nvar defined = __webpack_require__(\"./node_modules/core-js/library/modules/_defined.js\");\nmodule.exports = function (it) {\n return IObject(defined(it));\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_to-length.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// 7.1.15 ToLength\nvar toInteger = __webpack_require__(\"./node_modules/core-js/library/modules/_to-integer.js\");\nvar min = Math.min;\nmodule.exports = function (it) {\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_to-object.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// 7.1.13 ToObject(argument)\nvar defined = __webpack_require__(\"./node_modules/core-js/library/modules/_defined.js\");\nmodule.exports = function (it) {\n return Object(defined(it));\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_to-primitive.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = __webpack_require__(\"./node_modules/core-js/library/modules/_is-object.js\");\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function (it, S) {\n if (!isObject(it)) return it;\n var fn, val;\n if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;\n if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/_uid.js\":\n/***/ (function(module, exports) {\n\nvar id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/es6.object.define-property.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar $export = __webpack_require__(\"./node_modules/core-js/library/modules/_export.js\");\n// 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes)\n$export($export.S + $export.F * !__webpack_require__(\"./node_modules/core-js/library/modules/_descriptors.js\"), 'Object', { defineProperty: __webpack_require__(\"./node_modules/core-js/library/modules/_object-dp.js\").f });\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/es6.object.keys.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// 19.1.2.14 Object.keys(O)\nvar toObject = __webpack_require__(\"./node_modules/core-js/library/modules/_to-object.js\");\nvar $keys = __webpack_require__(\"./node_modules/core-js/library/modules/_object-keys.js\");\n\n__webpack_require__(\"./node_modules/core-js/library/modules/_object-sap.js\")('keys', function () {\n return function keys(it) {\n return $keys(toObject(it));\n };\n});\n\n\n/***/ }),\n\n/***/ \"./node_modules/core-js/library/modules/es7.object.values.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n// https://github.com/tc39/proposal-object-values-entries\nvar $export = __webpack_require__(\"./node_modules/core-js/library/modules/_export.js\");\nvar $values = __webpack_require__(\"./node_modules/core-js/library/modules/_object-to-array.js\")(false);\n\n$export($export.S, 'Object', {\n values: function values(it) {\n return $values(it);\n }\n});\n\n\n/***/ }),\n\n/***/ \"./src/data.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nvar LANGUAGES_LIST = {\n aa: {\n name: 'Afar',\n nativeName: 'Afaraf'\n },\n ab: {\n name: 'Abkhaz',\n nativeName: 'аҧсуа бызшәа'\n },\n ae: {\n name: 'Avestan',\n nativeName: 'avesta'\n },\n af: {\n name: 'Afrikaans',\n nativeName: 'Afrikaans'\n },\n ak: {\n name: 'Akan',\n nativeName: 'Akan'\n },\n am: {\n name: 'Amharic',\n nativeName: 'አማርኛ'\n },\n an: {\n name: 'Aragonese',\n nativeName: 'aragonés'\n },\n ar: {\n name: 'Arabic',\n nativeName: 'اللغة العربية'\n },\n as: {\n name: 'Assamese',\n nativeName: 'অসমীয়া'\n },\n av: {\n name: 'Avaric',\n nativeName: 'авар мацӀ'\n },\n ay: {\n name: 'Aymara',\n nativeName: 'aymar aru'\n },\n az: {\n name: 'Azerbaijani',\n nativeName: 'azərbaycan dili'\n },\n ba: {\n name: 'Bashkir',\n nativeName: 'башҡорт теле'\n },\n be: {\n name: 'Belarusian',\n nativeName: 'беларуская мова'\n },\n bg: {\n name: 'Bulgarian',\n nativeName: 'български език'\n },\n bh: {\n name: 'Bihari',\n nativeName: 'भोजपुरी'\n },\n bi: {\n name: 'Bislama',\n nativeName: 'Bislama'\n },\n bm: {\n name: 'Bambara',\n nativeName: 'bamanankan'\n },\n bn: {\n name: 'Bengali',\n nativeName: 'বাংলা'\n },\n bo: {\n name: 'Tibetan Standard',\n nativeName: 'བོད་ཡིག'\n },\n br: {\n name: 'Breton',\n nativeName: 'brezhoneg'\n },\n bs: {\n name: 'Bosnian',\n nativeName: 'bosanski jezik'\n },\n ca: {\n name: 'Catalan',\n nativeName: 'Català'\n },\n ce: {\n name: 'Chechen',\n nativeName: 'нохчийн мотт'\n },\n ch: {\n name: 'Chamorro',\n nativeName: 'Chamoru'\n },\n co: {\n name: 'Corsican',\n nativeName: 'corsu'\n },\n cr: {\n name: 'Cree',\n nativeName: 'ᓀᐦᐃᔭᐍᐏᐣ'\n },\n cs: {\n name: 'Czech',\n nativeName: 'čeština'\n },\n cu: {\n name: 'Old Church Slavonic',\n nativeName: 'ѩзыкъ словѣньскъ'\n },\n cv: {\n name: 'Chuvash',\n nativeName: 'чӑваш чӗлхи'\n },\n cy: {\n name: 'Welsh',\n nativeName: 'Cymraeg'\n },\n da: {\n name: 'Danish',\n nativeName: 'dansk'\n },\n de: {\n name: 'German',\n nativeName: 'Deutsch'\n },\n dv: {\n name: 'Divehi',\n nativeName: 'Dhivehi'\n },\n dz: {\n name: 'Dzongkha',\n nativeName: 'རྫོང་ཁ'\n },\n ee: {\n name: 'Ewe',\n nativeName: 'Eʋegbe'\n },\n el: {\n name: 'Greek',\n nativeName: 'Ελληνικά'\n },\n en: {\n name: 'English',\n nativeName: 'English'\n },\n eo: {\n name: 'Esperanto',\n nativeName: 'Esperanto'\n },\n es: {\n name: 'Spanish',\n nativeName: 'Español'\n },\n et: {\n name: 'Estonian',\n nativeName: 'eesti'\n },\n eu: {\n name: 'Basque',\n nativeName: 'euskara'\n },\n fa: {\n name: 'Persian',\n nativeName: 'فارسی'\n },\n ff: {\n name: 'Fula',\n nativeName: 'Fulfulde'\n },\n fi: {\n name: 'Finnish',\n nativeName: 'suomi'\n },\n fj: {\n name: 'Fijian',\n nativeName: 'Vakaviti'\n },\n fo: {\n name: 'Faroese',\n nativeName: 'føroyskt'\n },\n fr: {\n name: 'French',\n nativeName: 'Français'\n },\n fy: {\n name: 'Western Frisian',\n nativeName: 'Frysk'\n },\n ga: {\n name: 'Irish',\n nativeName: 'Gaeilge'\n },\n gd: {\n name: 'Scottish Gaelic',\n nativeName: 'Gàidhlig'\n },\n gl: {\n name: 'Galician',\n nativeName: 'galego'\n },\n gn: {\n name: 'Guaraní',\n nativeName: \"Avañe'ẽ\"\n },\n gu: {\n name: 'Gujarati',\n nativeName: 'ગુજરાતી'\n },\n gv: {\n name: 'Manx',\n nativeName: 'Gaelg'\n },\n ha: {\n name: 'Hausa',\n nativeName: 'هَوُسَ'\n },\n he: {\n name: 'Hebrew',\n nativeName: 'עברית'\n },\n hi: {\n name: 'Hindi',\n nativeName: 'हिन्दी'\n },\n ho: {\n name: 'Hiri Motu',\n nativeName: 'Hiri Motu'\n },\n hr: {\n name: 'Croatian',\n nativeName: 'hrvatski jezik'\n },\n ht: {\n name: 'Haitian',\n nativeName: 'Kreyòl ayisyen'\n },\n hu: {\n name: 'Hungarian',\n nativeName: 'magyar'\n },\n hy: {\n name: 'Armenian',\n nativeName: 'Հայերեն'\n },\n hz: {\n name: 'Herero',\n nativeName: 'Otjiherero'\n },\n ia: {\n name: 'Interlingua',\n nativeName: 'Interlingua'\n },\n id: {\n name: 'Indonesian',\n nativeName: 'Bahasa Indonesia'\n },\n ie: {\n name: 'Interlingue',\n nativeName: 'Interlingue'\n },\n ig: {\n name: 'Igbo',\n nativeName: 'Asụsụ Igbo'\n },\n ii: {\n name: 'Nuosu',\n nativeName: 'ꆈꌠ꒿ Nuosuhxop'\n },\n ik: {\n name: 'Inupiaq',\n nativeName: 'Iñupiaq'\n },\n io: {\n name: 'Ido',\n nativeName: 'Ido'\n },\n is: {\n name: 'Icelandic',\n nativeName: 'Íslenska'\n },\n it: {\n name: 'Italian',\n nativeName: 'Italiano'\n },\n iu: {\n name: 'Inuktitut',\n nativeName: 'ᐃᓄᒃᑎᑐᑦ'\n },\n ja: {\n name: 'Japanese',\n nativeName: '日本語'\n },\n jv: {\n name: 'Javanese',\n nativeName: 'basa Jawa'\n },\n ka: {\n name: 'Georgian',\n nativeName: 'ქართული'\n },\n kg: {\n name: 'Kongo',\n nativeName: 'Kikongo'\n },\n ki: {\n name: 'Kikuyu',\n nativeName: 'Gĩkũyũ'\n },\n kj: {\n name: 'Kwanyama',\n nativeName: 'Kuanyama'\n },\n kk: {\n name: 'Kazakh',\n nativeName: 'қазақ тілі'\n },\n kl: {\n name: 'Kalaallisut',\n nativeName: 'kalaallisut'\n },\n km: {\n name: 'Khmer',\n nativeName: 'ខេមរភាសា'\n },\n kn: {\n name: 'Kannada',\n nativeName: 'ಕನ್ನಡ'\n },\n ko: {\n name: 'Korean',\n nativeName: '한국어'\n },\n kr: {\n name: 'Kanuri',\n nativeName: 'Kanuri'\n },\n ks: {\n name: 'Kashmiri',\n nativeName: 'कश्मीरी'\n },\n ku: {\n name: 'Kurdish',\n nativeName: 'Kurdî'\n },\n kv: {\n name: 'Komi',\n nativeName: 'коми кыв'\n },\n kw: {\n name: 'Cornish',\n nativeName: 'Kernewek'\n },\n ky: {\n name: 'Kyrgyz',\n nativeName: 'Кыргызча'\n },\n la: {\n name: 'Latin',\n nativeName: 'latine'\n },\n lb: {\n name: 'Luxembourgish',\n nativeName: 'Lëtzebuergesch'\n },\n lg: {\n name: 'Ganda',\n nativeName: 'Luganda'\n },\n li: {\n name: 'Limburgish',\n nativeName: 'Limburgs'\n },\n ln: {\n name: 'Lingala',\n nativeName: 'Lingála'\n },\n lo: {\n name: 'Lao',\n nativeName: 'ພາສາ'\n },\n lt: {\n name: 'Lithuanian',\n nativeName: 'lietuvių kalba'\n },\n lu: {\n name: 'Luba-Katanga',\n nativeName: 'Tshiluba'\n },\n lv: {\n name: 'Latvian',\n nativeName: 'latviešu valoda'\n },\n mg: {\n name: 'Malagasy',\n nativeName: 'fiteny malagasy'\n },\n mh: {\n name: 'Marshallese',\n nativeName: 'Kajin M̧ajeļ'\n },\n mi: {\n name: 'Māori',\n nativeName: 'te reo Māori'\n },\n mk: {\n name: 'Macedonian',\n nativeName: 'македонски јазик'\n },\n ml: {\n name: 'Malayalam',\n nativeName: 'മലയാളം'\n },\n mn: {\n name: 'Mongolian',\n nativeName: 'Монгол хэл'\n },\n mr: {\n name: 'Marathi',\n nativeName: 'मराठी'\n },\n ms: {\n name: 'Malay',\n nativeName: 'Bahasa Malaysia'\n },\n mt: {\n name: 'Maltese',\n nativeName: 'Malti'\n },\n my: {\n name: 'Burmese',\n nativeName: 'ဗမာစာ'\n },\n na: {\n name: 'Nauru',\n nativeName: 'Ekakairũ Naoero'\n },\n nb: {\n name: 'Norwegian Bokmål',\n nativeName: 'Norsk bokmål'\n },\n nd: {\n name: 'Northern Ndebele',\n nativeName: 'isiNdebele'\n },\n ne: {\n name: 'Nepali',\n nativeName: 'नेपाली'\n },\n ng: {\n name: 'Ndonga',\n nativeName: 'Owambo'\n },\n nl: {\n name: 'Dutch',\n nativeName: 'Nederlands'\n },\n nn: {\n name: 'Norwegian Nynorsk',\n nativeName: 'Norsk nynorsk'\n },\n no: {\n name: 'Norwegian',\n nativeName: 'Norsk'\n },\n nr: {\n name: 'Southern Ndebele',\n nativeName: 'isiNdebele'\n },\n nv: {\n name: 'Navajo',\n nativeName: 'Diné bizaad'\n },\n ny: {\n name: 'Chichewa',\n nativeName: 'chiCheŵa'\n },\n oc: {\n name: 'Occitan',\n nativeName: 'occitan'\n },\n oj: {\n name: 'Ojibwe',\n nativeName: 'ᐊᓂᔑᓈᐯᒧᐎᓐ'\n },\n om: {\n name: 'Oromo',\n nativeName: 'Afaan Oromoo'\n },\n or: {\n name: 'Oriya',\n nativeName: 'ଓଡ଼ିଆ'\n },\n os: {\n name: 'Ossetian',\n nativeName: 'ирон æвзаг'\n },\n pa: {\n name: 'Panjabi',\n nativeName: 'ਪੰਜਾਬੀ'\n },\n pi: {\n name: 'Pāli',\n nativeName: 'पाऴि'\n },\n pl: {\n name: 'Polish',\n nativeName: 'język polski'\n },\n ps: {\n name: 'Pashto',\n nativeName: 'پښتو'\n },\n pt: {\n name: 'Portuguese',\n nativeName: 'Português'\n },\n qu: {\n name: 'Quechua',\n nativeName: 'Runa Simi'\n },\n rm: {\n name: 'Romansh',\n nativeName: 'rumantsch grischun'\n },\n rn: {\n name: 'Kirundi',\n nativeName: 'Ikirundi'\n },\n ro: {\n name: 'Romanian',\n nativeName: 'Română'\n },\n ru: {\n name: 'Russian',\n nativeName: 'Русский'\n },\n rw: {\n name: 'Kinyarwanda',\n nativeName: 'Ikinyarwanda'\n },\n sa: {\n name: 'Sanskrit',\n nativeName: 'संस्कृतम्'\n },\n sc: {\n name: 'Sardinian',\n nativeName: 'sardu'\n },\n sd: {\n name: 'Sindhi',\n nativeName: 'सिन्धी'\n },\n se: {\n name: 'Northern Sami',\n nativeName: 'Davvisámegiella'\n },\n sg: {\n name: 'Sango',\n nativeName: 'yângâ tî sängö'\n },\n si: {\n name: 'Sinhala',\n nativeName: 'සිංහල'\n },\n sk: {\n name: 'Slovak',\n nativeName: 'slovenčina'\n },\n sl: {\n name: 'Slovene',\n nativeName: 'slovenski jezik'\n },\n sm: {\n name: 'Samoan',\n nativeName: \"gagana fa'a Samoa\"\n },\n sn: {\n name: 'Shona',\n nativeName: 'chiShona'\n },\n so: {\n name: 'Somali',\n nativeName: 'Soomaaliga'\n },\n sq: {\n name: 'Albanian',\n nativeName: 'Shqip'\n },\n sr: {\n name: 'Serbian',\n nativeName: 'српски језик'\n },\n ss: {\n name: 'Swati',\n nativeName: 'SiSwati'\n },\n st: {\n name: 'Southern Sotho',\n nativeName: 'Sesotho'\n },\n su: {\n name: 'Sundanese',\n nativeName: 'Basa Sunda'\n },\n sv: {\n name: 'Swedish',\n nativeName: 'svenska'\n },\n sw: {\n name: 'Swahili',\n nativeName: 'Kiswahili'\n },\n ta: {\n name: 'Tamil',\n nativeName: 'தமிழ்'\n },\n te: {\n name: 'Telugu',\n nativeName: 'తెలుగు'\n },\n tg: {\n name: 'Tajik',\n nativeName: 'тоҷикӣ'\n },\n th: {\n name: 'Thai',\n nativeName: 'ไทย'\n },\n ti: {\n name: 'Tigrinya',\n nativeName: 'ትግርኛ'\n },\n tk: {\n name: 'Turkmen',\n nativeName: 'Türkmen'\n },\n tl: {\n name: 'Tagalog',\n nativeName: 'Wikang Tagalog'\n },\n tn: {\n name: 'Tswana',\n nativeName: 'Setswana'\n },\n to: {\n name: 'Tonga',\n nativeName: 'faka Tonga'\n },\n tr: {\n name: 'Turkish',\n nativeName: 'Türkçe'\n },\n ts: {\n name: 'Tsonga',\n nativeName: 'Xitsonga'\n },\n tt: {\n name: 'Tatar',\n nativeName: 'татар теле'\n },\n tw: {\n name: 'Twi',\n nativeName: 'Twi'\n },\n ty: {\n name: 'Tahitian',\n nativeName: 'Reo Tahiti'\n },\n ug: {\n name: 'Uyghur',\n nativeName: 'ئۇيغۇرچە‎'\n },\n uk: {\n name: 'Ukrainian',\n nativeName: 'Українська'\n },\n ur: {\n name: 'Urdu',\n nativeName: 'اردو'\n },\n uz: {\n name: 'Uzbek',\n nativeName: 'Ўзбек'\n },\n ve: {\n name: 'Venda',\n nativeName: 'Tshivenḓa'\n },\n vi: {\n name: 'Vietnamese',\n nativeName: 'Tiếng Việt'\n },\n vo: {\n name: 'Volapük',\n nativeName: 'Volapük'\n },\n wa: {\n name: 'Walloon',\n nativeName: 'walon'\n },\n wo: {\n name: 'Wolof',\n nativeName: 'Wollof'\n },\n xh: {\n name: 'Xhosa',\n nativeName: 'isiXhosa'\n },\n yi: {\n name: 'Yiddish',\n nativeName: 'ייִדיש'\n },\n yo: {\n name: 'Yoruba',\n nativeName: 'Yorùbá'\n },\n za: {\n name: 'Zhuang',\n nativeName: 'Saɯ cueŋƅ'\n },\n zh: {\n name: 'Chinese',\n nativeName: '中文'\n },\n zu: {\n name: 'Zulu',\n nativeName: 'isiZulu'\n }\n};\n\nexports.default = LANGUAGES_LIST;\nmodule.exports = exports['default'];\n\n/***/ }),\n\n/***/ \"./src/index.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _keys = __webpack_require__(\"./node_modules/babel-runtime/core-js/object/keys.js\");\n\nvar _keys2 = _interopRequireDefault(_keys);\n\nvar _values = __webpack_require__(\"./node_modules/babel-runtime/core-js/object/values.js\");\n\nvar _values2 = _interopRequireDefault(_values);\n\nvar _classCallCheck2 = __webpack_require__(\"./node_modules/babel-runtime/helpers/classCallCheck.js\");\n\nvar _classCallCheck3 = _interopRequireDefault(_classCallCheck2);\n\nvar _createClass2 = __webpack_require__(\"./node_modules/babel-runtime/helpers/createClass.js\");\n\nvar _createClass3 = _interopRequireDefault(_createClass2);\n\nvar _data = __webpack_require__(\"./src/data.js\");\n\nvar _data2 = _interopRequireDefault(_data);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar ISO6391 = function () {\n function ISO6391() {\n (0, _classCallCheck3.default)(this, ISO6391);\n }\n\n (0, _createClass3.default)(ISO6391, null, [{\n key: 'getLanguages',\n value: function getLanguages() {\n var codes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n\n return codes.map(function (code) {\n return {\n code: code,\n name: ISO6391.getName(code),\n nativeName: ISO6391.getNativeName(code)\n };\n });\n }\n }, {\n key: 'getName',\n value: function getName(code) {\n return ISO6391.validate(code) ? _data2.default[code].name : '';\n }\n }, {\n key: 'getAllNames',\n value: function getAllNames() {\n return (0, _values2.default)(_data2.default).map(function (l) {\n return l.name;\n });\n }\n }, {\n key: 'getNativeName',\n value: function getNativeName(code) {\n return ISO6391.validate(code) ? _data2.default[code].nativeName : '';\n }\n }, {\n key: 'getAllNativeNames',\n value: function getAllNativeNames() {\n return (0, _values2.default)(_data2.default).map(function (l) {\n return l.nativeName;\n });\n }\n }, {\n key: 'getCode',\n value: function getCode(name) {\n var code = (0, _keys2.default)(_data2.default).find(function (code) {\n var language = _data2.default[code];\n\n return language.name.toLowerCase() === name.toLowerCase() || language.nativeName.toLowerCase() === name.toLowerCase();\n });\n return code || '';\n }\n }, {\n key: 'getAllCodes',\n value: function getAllCodes() {\n return (0, _keys2.default)(_data2.default);\n }\n }, {\n key: 'validate',\n value: function validate(code) {\n return _data2.default.hasOwnProperty(code);\n }\n }]);\n return ISO6391;\n}();\n\nexports.default = ISO6391;\nmodule.exports = exports['default'];\n\n/***/ })\n\n/******/ });\n});\n\n(function(exports) {\n 'use strict';\n\n var Constants = {};\n\n Constants.CONTENT_TYPE = {\n MP4: 'MP4',\n HLS: 'HLS',\n RTSP: 'RTSP',\n RTMP: 'RTMP',\n NPP: 'NPP',\n LINEAR: 'LINEAR',\n DASH: 'DASH'\n };\n\n Constants.MEDIA_TYPE = {\n NPP: 'application/x-nppURL',\n HLS: 'application/x-mpegURL',\n MP4: 'video/mp4'\n };\n\n Constants.ENV = {\n MOBILE_WEB: 'MOBILE_WEB',\n MOBILE_WEB_ALLOW_HD: 'MOBILE_WEB_ALLOW_HD',\n TVPOT_WEB: 'TVPOT_WEB',\n DAUM_APP: 'DAUM_APP',\n KAKAOTV: 'KAKAOTV',\n IOS: 'IOS',\n ANDROID: 'ANDROID'\n };\n\n Constants.PHASE = {\n DEV: 'DEV',\n CBT: 'CBT',\n SANDBOX: 'SANDBOX',\n PROD: 'PROD',\n PRODSLV: 'PROD',\n LOCAL: 'LOCAL'\n };\n\n Constants.SUB_DOMAIN = {\n KAKAO: {\n DEV: 'alpha-tv',\n CBT: 'beta-tv',\n SANDBOX: 'sandbox-tv',\n PROD: 'tv',\n LOCAL: '',\n PLAYER: 'play-tv'\n },\n DAUM: {\n DEV: 'alpha-tv.dev',\n CBT: 'beta-tv.dev',\n SANDBOX: 'sandbox-tv.dev',\n PROD: 'kakaotv',\n LOCAL: ''\n }\n };\n\n Constants.DOMAIN = {\n KAKAO: 'kakao.com',\n DAUM: 'daum.net'\n };\n\n Constants.HOST = location.protocol + '//' + location.host;\n\n Constants.SHARE_DOMAIN =\n location.protocol + '//' + Constants.SUB_DOMAIN.KAKAO.PLAYER + '.' + Constants.DOMAIN.KAKAO;\n\n Constants.APP_KEY = {\n DEV: 'c6e6645efbe2d0d688e9136aa0c44fc4',\n CBT: '8ea44e3f160a4c276592eda5f1c7cb61',\n SANDBOX: 'a16c74899bb0672c71ca8024b8d78cd5',\n PROD: '8ea44e3f160a4c276592eda5f1c7cb61',\n LOCAL: '8ea44e3f160a4c276592eda5f1c7cb61'\n };\n\n Constants.DTE_TYPE = {\n IPHONE: 'IPHONE',\n IPAD: 'IPAD',\n ANDROID: 'ANDROID',\n PC: 'PC',\n ETC: 'ETC'\n };\n\n Constants.VIDEO_TYPE = {\n AD: 'AD',\n VOD: 'VOD',\n LIVE: 'LIVE'\n };\n\n Constants.PROFILE = {\n LOW: 'LOW',\n BASE: 'BASE',\n MAIN: 'MAIN',\n HIGH: 'HIGH',\n HIGH4: 'HIGH4',\n SUPER: 'SUPER',\n ULTRA: 'ULTRA',\n AUTO: 'AUTO'\n };\n\n Constants.DASH_PROFILE = {\n AUTO: Constants.PROFILE.AUTO,\n 0: Constants.PROFILE.LOW,\n 1: Constants.PROFILE.BASE,\n 2: Constants.PROFILE.MAIN,\n 3: Constants.PROFILE.HIGH,\n 4: Constants.PROFILE.HIGH4,\n 5: Constants.PROFILE.SUPER,\n 6: Constants.PROFILE.ULTRA\n };\n\n Constants.PROFILE_RESOULTION = {};\n Constants.PROFILE_RESOULTION[Constants.PROFILE.LOW] = '240P';\n Constants.PROFILE_RESOULTION[Constants.PROFILE.BASE] = '360P';\n Constants.PROFILE_RESOULTION[Constants.PROFILE.MAIN] = '480P';\n Constants.PROFILE_RESOULTION[Constants.PROFILE.HIGH] = '720P HD';\n Constants.PROFILE_RESOULTION[Constants.PROFILE.HIGH4] = '1080P HD';\n Constants.PROFILE_RESOULTION[Constants.PROFILE.SUPER] = '1440P HD';\n Constants.PROFILE_RESOULTION[Constants.PROFILE.ULTRA] = '2160P 4K';\n\n Constants.ABR_RESTRICTION_PROFILE = {};\n Constants.ABR_RESTRICTION_PROFILE[Constants.PROFILE.LOW] = 454 * 240;\n Constants.ABR_RESTRICTION_PROFILE[Constants.PROFILE.BASE] = 682 * 360;\n Constants.ABR_RESTRICTION_PROFILE[Constants.PROFILE.MAIN] = 910 * 480;\n Constants.ABR_RESTRICTION_PROFILE[Constants.PROFILE.HIGH] = 1364 * 720;\n Constants.ABR_RESTRICTION_PROFILE[Constants.PROFILE.HIGH4] = 2520 * 1080;\n\n Constants.ID = {\n VIDEO_ELEMENT: 'videoElement',\n VIDEO_CONTAINER: 'videoContainer'\n };\n\n Constants.URL = {\n THUMBNAIL_FARM_URL: '//t1.daumcdn.net/thumb/#{type}.q50.fjpg/?fname=#{url}',\n KEMI_LOG_URL: Constants.HOST + '/api/v1/ft/logging/player',\n LIVEAGENT_DOWNLOAD_URL_MAC: '//t1.daumcdn.net/liveagent/v2/macOS/LiveAgent.dmg',\n LIVEAGENT_DOWNLOAD_URL_WIN: '//t1.daumcdn.net/liveagent/v4/win/KakaoLiveAgentSetup.exe',\n LIVEAGENT_SETUP_GUIDE: '//cs.kakao.com/helps?category=242&device=659&locale=ko&service=53&articleId=1073187694'\n };\n\n Constants.STORAGE = {\n UUID: 'player_uuid',\n VOLUME: 'player_volume',\n ALERT_MSG: '3g4g_alert_msg',\n PROFILE: 'player_profile',\n MUTE: 'player_mute',\n ABR: 'player_abr',\n CHART: 'player_chart',\n SUBTITLE: 'player_subtitle'\n };\n\n Constants.ERROR = {\n CLASS: {\n BACKGROUND_ALPHA: 'background_alpha',\n BACKGROUND_DIMMED: 'background_dimmed',\n THUMBNAIL_IMG: 'thumbnail_img'\n },\n STATUS: {\n Age18: {\n NAME: 'Age18',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '이 비디오물은 청소년 관람불가 등급으로
만 18세 미만의 청소년은 시청할 수 없습니다.',\n CLASS_NAME: 'message_intro',\n HAS_OUT_LINK: false\n },\n Age19: {\n NAME: 'Age19',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION:\n '이 정보 내용은 청소년 유해매체물로서
정보 통신망 이용 촉진 및 정보 보호 등에 관한
' +\n '법률 및 청소년 보호법에 따라
19세 미만의 청소년이 이용할 수 없습니다.',\n CLASS_NAME: 'type_agelimit_intro message_intro',\n HAS_OUT_LINK: false\n },\n AgeLimited18: {\n NAME: 'AgeLimited18',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '인증 결과 청소년으로 확인되어 이 동영상을 시청할 수 없습니다.',\n CLASS_NAME: 'type_agelimit',\n HAS_OUT_LINK: false\n },\n AgeLimited19: {\n NAME: 'AgeLimited19',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '인증 결과 청소년으로 확인되어 이 동영상을 시청할 수 없습니다.',\n CLASS_NAME: 'type_agelimit',\n HAS_OUT_LINK: false\n },\n AgeLimitedLive19: {\n NAME: 'AgeLimitedLive19',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION:\n '본 방송은 미성년자가 시청하기에 적합하지 않은 터프한 방송입니다. 미성년자는 터프한 방송 시청이 제한됩니다.',\n CLASS_NAME: 'type_tough',\n HAS_OUT_LINK: false\n },\n AudioCopyright: {\n NAME: 'AudioCopyright',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '음원 저작권자의 권리보호를 위해 재생 차단되었습니다.',\n CLASS_NAME: 'message_info outlink_none',\n HAS_OUT_LINK: false\n },\n CleanCenterTemporaryRightViolations: {\n NAME: 'CleanCenterTemporaryRightViolations',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '해당 콘텐츠는 권리침해 신고로 임시 조치 되었습니다.',\n CLASS_NAME: 'message_info',\n LINK_TYPE: 'qna'\n },\n CodecNotInstalled: {\n NAME: 'CodecNotInstalled',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION:\n '윈도우에서 HTML5플레이어로 재생하기 위해서는
윈도우 미디어 기능팩 설치가 필요합니다.',\n CLASS_NAME: 'message_info',\n LINK_TYPE: 'qna',\n LINK_URL:\n 'https://cs.kakao.com/helps?' +\n 'category=242&device=659&locale=ko&service=53&articleId=1073187747&page=1'\n },\n LiveAgentNotInstalled: {\n NAME: 'LiveAgentNotInstalled',\n MESSAGE_TYPE: 'install',\n DESCRIPTION: '고화질로 생생한 라이브를 시청하기 위해서는 라이브 에이전트 설치가 필요합니다.',\n LINK_URL:\n 'https://cs.kakao.com/helps?' +\n 'category=242&device=659&locale=ko&service=53&articleId=1073187747&page=1'\n },\n EncodingNotCompleted: {\n NAME: 'EncodingNotCompleted',\n MESSAGE_TYPE: 'process',\n DESCRIPTION: '동영상 인코딩 중입니다.
잠시 후 다시 확인해주세요.',\n CLASS_NAME: 'message_popup',\n LINK_TYPE: 'refresh'\n },\n ExceededAllowance: {\n NAME: 'ExceededAllowance',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '허용된 방송 시청자수를 초과하였습니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n FailedEncoding: {\n NAME: 'FailedEncoding',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '동영상을 등록할 수 없습니다. 다시 업로드 해주세요.',\n CLASS_NAME: 'message_info outlink_none'\n },\n GeoBlocked: {\n NAME: 'GeoBlocked',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '해당 국가에서의 접근은 금지되어 있습니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n LiveFinished: {\n NAME: 'LiveFinished',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '종료된 방송입니다.',\n CLASS_NAME: 'message_info outlink_none thumbnail_img type_stop background_dimmed'\n },\n LiveException: {\n NAME: 'LiveException',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '라이브가 종료되었거나, 재생이 원활하지 않습니다.',\n CLASS_NAME: 'message_info outlink_none thumbnail_img'\n },\n LivefarmServerError: {\n NAME: 'LivefarmServerError',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '현재 이용자가 많아
접속이 원활하지 않습니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n Need19Login: {\n NAME: 'Need19Login',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '19금 컨텐츠에 접근하기 위해서는 로그인이 필요합니다.',\n CLASS_NAME: 'type_nineteen',\n LINK_TYPE: 'auth'\n },\n NeedAuth: {\n NAME: 'NeedAuth',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '본인인증이 필요합니다.',\n CLASS_NAME: 'type_nineteen',\n LINK_TYPE: 'auth'\n },\n NeedAuth18: {\n NAME: 'NeedAuth18',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '청소년은 시청할 수 없는 동영상으로 본인인증 후 이용이 가능합니다.',\n CLASS_NAME: 'type_nineteen',\n LINK_TYPE: 'auth'\n },\n NeedAuth19: {\n NAME: 'NeedAuth19',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '청소년은 시청할 수 없는 동영상으로 본인인증 후 이용이 가능합니다.',\n CLASS_NAME: 'type_nineteen',\n LINK_TYPE: 'auth'\n },\n NeedAuthLive19: {\n NAME: 'NeedAuthLive19',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION:\n '터프한 방송은 비속어 또는 일부 폭력적인 영상이 포함되어 있어 19세 미만의 청소년은 시청할 수 없습니다.',\n CLASS_NAME: 'type_tough',\n LINK_TYPE: 'auth'\n },\n NeedChannel: {\n NAME: 'NeedChannel',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '하나 이상의 채널이 필요합니다.',\n CLASS_NAME: 'message_info'\n },\n NoOwnership: {\n NAME: 'NoOwnership',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '권한이 없습니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n NotFound: {\n NAME: 'NotFound',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '존재하지 않거나 삭제된 영상입니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n NotOpenClipOrLive: {\n NAME: 'NotOpenClipOrLive',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '비공개된 영상입니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n RightViolations: {\n NAME: 'RightViolations',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '해당 콘텐츠는 권리침해 신고로
임시 접근 금지되었습니다.',\n CLASS_NAME: 'message_info',\n LINK_TYPE: 'qna'\n },\n UNAVAILABLE: {\n NAME: 'UNAVAILABLE',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '동영상을 재생할 수 없습니다.',\n CLASS_NAME: 'message_info outlink_none',\n LINK_TYPE: 'refresh'\n },\n UNAVAILABLE_DRM: {\n NAME: 'UNAVAILABLE_DRM',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '본 영상은 카카오톡 최신 버전에서 시청할 수 있습니다. (9.2.0 버전 이상)',\n CLASS_NAME: 'message_info outlink_none'\n },\n UNAVAILABLE_COOKIE: {\n NAME: 'UNAVAILABLE_COOKIE',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION:\n '쿠키 차단으로 인해 영상을 재생할 수 없습니다.
브라우저 쿠키 설정을 \"허용\"으로 변경해주세요.',\n CLASS_NAME: 'message_info message_type1',\n LINK_TYPE: 'help'\n },\n Violation: {\n NAME: 'Violation',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '규제되었습니다.',\n CLASS_NAME: 'message_info'\n },\n VideoCopyright: {\n NAME: 'VideoCopyright',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '저작권자의 권리보호를 위해 재생 차단되었습니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n OperationPolicy: {\n NAME: 'OperationPolicy',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '카카오TV 운영정책 위반으로 규제 되었습니다.',\n CLASS_NAME: 'message_info'\n },\n LegacyPlayerNotice: {\n NAME: 'LegacyPlayerNotice',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION:\n '최신 버전의 카카오 TV 플레이어에서만
바로 재생이 가능합니다. 재생하시려면
아래 확인 버튼을 눌러 주세요.',\n CLASS_NAME: 'message_info message_type1',\n LINK_TYPE: 'redirect',\n LINK_URL: 'https://cs.kakao.com/requests?category=298&locale=ko&service=53'\n },\n UNAVAILABLE_ADBLOCK: {\n NAME: 'UNAVAILABLE_ADBLOCK',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION:\n '동영상을 재생할 수 없습니다.
광고 차단 프로그램이 원인일 수 있으므로
해제 또는 삭제 후 재생하시기 바랍니다.',\n CLASS_NAME: 'message_info outlink_none',\n LINK_TYPE: 'refresh'\n },\n UNAVAILABLE_ADCONTENTS: {\n NAME: 'UNAVAILABLE_ADCONTENTS',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '일시적인 오류로 광고 정보를 불러오지 못했습니다.',\n CLASS_NAME: 'message_info outlink_none',\n LINK_TYPE: 'refresh'\n },\n NETWORK_OFFLINE: {\n NAME: 'NETWORK_OFFLINE',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '네트워크 상태를 확인해주세요.',\n CLASS_NAME: 'message_info',\n LINK_TYPE: 'refresh'\n },\n ReservedClip: {\n NAME: 'ReservedClip',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '공개 예정인 영상입니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n LimitExceeded: {\n NAME: 'LimitExceeded',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '이용자가 많아 잠시 대기중입니다.',\n CLASS_NAME: 'message_info outlink_none'\n },\n NotSupportedMedia: {\n NAME: 'NotSupportedMedia',\n MESSAGE_TYPE: 'notice',\n DESCRIPTION: '영상 재생을 위해 디바이스 OS 및 브라우저 버전 업데이트가 필요합니다.',\n CLASS_NAME: 'message_info outlink_none'\n }\n }\n };\n\n Constants.CONFIRM = {\n CLASS: {\n BACKGROUND_ALPHA: 'background_alpha'\n },\n STATUS: {\n CARRIER: {\n NAME: 'CARRIER',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION: '사용 중인 요금제에 따라 데이터 요금이
발생할 수 있습니다.',\n CLASS_NAME: 'background_alpha',\n LINK_TYPE: 'normal'\n },\n LinearLive: {\n NAME: 'LinearLive',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION: 'tvingTV 채널 방송은
카카오TV 라이브앱에서 재생할 수 있습니다.',\n CLASS_NAME: '',\n LINK_TYPE: 'web2app'\n },\n LAUNCH_APP: {\n NAME: 'LAUNCH_APP',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION:\n 'HD화질 시청을 위해 카카오TV 라이브앱으로
연결합니다. 설치가 안된 경우 설치하시겠습니까?',\n CLASS_NAME: 'background_alpha',\n LINK_TYPE: 'normal'\n },\n NeedJoinAgreement: {\n NAME: 'NeedJoinAgreement',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION: '가입 동의가 필요합니다.',\n CLASS_NAME: 'background_alpha',\n LINK_TYPE: 'normal'\n },\n NeedLaunchApp: {\n NAME: 'NeedLaunchApp',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION: '카카오TV 라이브앱에서만
시청 가능한 콘텐츠입니다.',\n CLASS_NAME: 'background_alpha',\n LINK_TYPE: 'web2app'\n },\n NeedPassword: {\n NAME: 'NeedPassword',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION: '비밀번호 입력이 필요한 컨텐츠입니다.',\n CLASS_NAME: 'message_popup background_alpha',\n LINK_TYPE: 'password'\n },\n NeedLogin: {\n NAME: 'NeedLogin',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION: '로그인 후 시청 가능한 컨텐츠입니다.',\n CLASS_NAME: 'message_popup background_alpha',\n LINK_TYPE: 'login'\n },\n PasswordIncorrect: {\n NAME: 'PasswordIncorrect',\n MESSAGE_TYPE: 'input',\n DESCRIPTION: '잘못된 비밀번호입니다. 다시 입력해주세요.',\n CLASS_NAME: 'message_popup background_alpha color_g',\n LINK_TYPE: 'password'\n },\n NoPurchased: {\n NAME: 'NoPurchased',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION:\n \"영상 시청을 위해 모바일 카카오톡에서 구매가 필요합니다.
구매 링크는 '나와의 채팅방'으로 전송됩니다.\",\n CLASS_NAME: 'background_alpha background_dimmed',\n LINK_TYPE: 'purchase'\n },\n NoPurchasedForMobile: {\n NAME: 'NoPurchasedForMobile',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION: '영상 시청을 위해 구매가 필요합니다.',\n CLASS_NAME: 'background_alpha background_dimmed',\n LINK_TYPE: 'purchase'\n },\n NeedPurchased: {\n NAME: 'NeedPurchased',\n MESSAGE_TYPE: 'confirm',\n DESCRIPTION:\n \"영상 시청을 위해 모바일 카카오톡에서 구매가 필요합니다.
구매 링크는 '나와의 채팅방'으로 전송됩니다.\",\n CLASS_NAME: 'background_alpha background_dimmed',\n LINK_TYPE: 'purchase'\n },\n EncodingNotCompleted: Constants.ERROR.STATUS.EncodingNotCompleted\n }\n };\n\n Constants.HTTP = {\n TYPE: {\n XML: 'xml',\n JSON: 'json',\n TEXT: 'text'\n },\n METHOD: {\n GET: 'get',\n POST: 'post',\n PUT: 'put'\n }\n };\n\n Constants.SHAKA = {\n CONFIGURE: {\n PC: {\n abr: {\n defaultBandwidthEstimate: 2500000,\n bandwidthUpgradeTarget: 0.8,\n switchInterval: 2\n },\n manifest: {\n retryParameters: {\n maxAttempts: 2\n }\n },\n streaming: {\n rebufferingGoal: 4,\n bufferingGoal: 10,\n retryParameters: {\n baseDelay: 5000,\n maxAttempts: 1,\n timeout: 60000\n },\n smallGapLimit: 1\n }\n },\n MOBILE: {\n abr: {\n defaultBandwidthEstimate: 1250000,\n bandwidthUpgradeTarget: 0.8,\n switchInterval: 2\n },\n manifest: {\n retryParameters: {\n maxAttempts: 2\n }\n },\n streaming: {\n rebufferingGoal: 4,\n bufferingGoal: 10,\n retryParameters: {\n baseDelay: 5000,\n maxAttempts: 1,\n timeout: 60000\n }\n }\n }\n }\n };\n\n Constants.SHAKA.ERROR = {\n HTTP_ERROR: {\n CODE: 1002\n },\n BAD_HTTP_STATUS: {\n CODE: 1001\n },\n MEDIA_FORMAT_ERROR: {\n CODE: 3016\n },\n // IE11 playread 제약사항: https://wiki.daumkakao.com/pages/viewpage.action?pageId=713801232\n FAILED_TO_GENERATE_LICENSE_REQUEST: {\n CODE: 6006\n }\n };\n\n Constants.QOE = {\n EVENT: {\n PLAYBACK_FAIL: 'playback_fail',\n REBUFFERING: 'rebuffering',\n SEEK: 'seek',\n RESOLUTION_CHANGE: 'resolution_change',\n INITIAL_DELAY: 'initial_delay',\n BANDWIDTH: 'bandwidth',\n FRAME_DROP: 'frame_drop',\n DISPLAY_SIZE_CHANGE: 'display_size_change'\n }\n };\n\n Constants.PLAYER_CALLBACK_NAME = {\n notReadyCallback: 'notReadyCallback',\n onAddPlaylist: 'onAddPlaylist',\n onCheckNextVideo: 'onCheckNextVideo',\n onChangeAutoPlayMode: 'onChangeAutoPlayMode',\n onKakaoIframeAPIReady: 'onKakaoIframeAPIReady',\n onEndAutoPlayTimer: 'onEndAutoPlayTimer',\n onFullScreenChange: 'onFullScreenChange',\n onLoadedContentVideo: 'onLoadedContentVideo',\n onMeasureHeight: 'onMeasureHeight',\n onClickEventStart: 'onClickEventStart',\n onPlayError: 'onPlayError',\n onPlayCancel: 'onPlayCancel',\n onFailAutoPlay: 'onFailAutoPlay',\n onReadyComplete: 'onReadyComplete',\n onReadyVideo: 'onReadyVideo',\n onStartImpression: 'onStartImpression',\n onStartLoadVideo: 'onStartLoadVideo',\n onTouchEventStart: 'onTouchEventStart',\n onTouchEventEnd: 'onTouchEventEnd',\n onVideoStateChange: 'onVideoStateChange',\n onWideScreenChange: 'onWideScreenChange',\n onPlayStart: 'onPlayStart',\n onPlayEnd: 'onPlayEnd',\n onAlreadyInited: 'onAlreadyInited',\n onOffsetPointUpdate: 'onOffsetPointUpdate',\n onTimeUpdate: 'onTimeUpdate',\n pageReload: 'pageReload'\n };\n\n Constants.PLAYER_VIDEO_STATE = {\n PLAYING: 'playing',\n PLAY: 'play',\n PAUSE: 'pause',\n PASSED: 'passed',\n ENDED: 'ended'\n };\n\n Constants.PLAYER_CLICK_ACTION = {\n PLAY: 'play',\n PAUSE: 'pause'\n };\n\n Constants.TRACKING_OFF_PARAM = 'tk=off';\n\n Constants.SENTRY = {\n DEFAULT_MESSAGE_OPTION: {\n level: 'warning'\n },\n CONFIG: {\n DSN: {\n DEV: 'https://6c3a23572a38405cbcbb6f7f76b7dc59@aem-collector.daumkakao.io/400',\n SANDBOX: 'https://06d4965dc4ff4a0c82a3ffcaf491233b@aem-collector.daumkakao.io/391',\n CBT: 'https://3b52761fbc4144088d2e577ccc535e19@aem-collector.daumkakao.io/397',\n PROD: 'https://711c55a031e544338c0b272f0fb34990@aem-collector.daumkakao.io/1561'\n }\n }\n };\n\n Constants.TIARA = {\n SVC_DOMAIN: 'tv.kakao.com',\n SECTION: {\n PLAYER_HTML5: 'player_html5'\n },\n PC_VOD: {\n PAGE_VIEW: {\n PAGE_NAME: 'pc_player_vod',\n ACTION_NAME: 'PC VOD 플레이어 조회'\n },\n EVENT: {\n CLICK: {\n LAYER1: 'recommend_video'\n },\n ACTION_NAME: '플레이어 추천 영상 클릭'\n }\n },\n PC_LIVE: {\n PAGE_VIEW: {\n PAGE_NAME: 'pc_player_live',\n ACTION_NAME: 'PC LIVE 플레이어 조회'\n },\n EVENT: {\n CLICK: {\n LAYER1: 'recommend_video'\n },\n ACTION_NAME: '플레이어 추천 영상 클릭'\n }\n },\n MOBILE_VOD: {\n PAGE_VIEW: {\n PAGE_NAME: 'm_player_vod',\n ACTION_NAME: '모바일 VOD 플레이어 조회'\n },\n EVENT: {\n CLICK: {\n LAYER1: 'recommend_video'\n },\n ACTION_NAME: '플레이어 추천 영상 클릭'\n }\n },\n MOBILE_LIVE: {\n PAGE_VIEW: {\n PAGE_NAME: 'm_player_live',\n ACTION_NAME: '모바일 LIVE 플레이어 조회'\n },\n EVENT: {\n CLICK: {\n LAYER1: 'recommend_video'\n },\n ACTION_NAME: '플레이어 추천 영상 클릭'\n }\n }\n };\n\n Constants.PLAYERCLASS = {\n SHAKA: 'shaka',\n KAMP: 'kamp',\n HTML5: 'html5',\n CAST: 'cast'\n };\n\n Constants.AGE_LIMIT = {\n ALL: {\n name: 'ALL',\n class: 'ico_watchall'\n },\n AGE_12: {\n name: 'AGE_12',\n class: 'ico_watch12'\n },\n AGE_15: {\n name: 'AGE_15',\n class: 'ico_watch15'\n },\n AGE_18: {\n name: 'AGE_18',\n class: 'ico_watch19'\n },\n AGE_19: {\n name: 'AGE_19',\n class: 'ico_watch19'\n }\n };\n\n Constants.RATING = {\n subject: {\n key: 'subject',\n name: '주제',\n class: 'ico_watchsubject'\n },\n sexual: {\n key: 'sexual',\n name: '선정성',\n class: 'ico_watchsexuality'\n },\n violence: {\n key: 'violence',\n name: '폭력성',\n class: 'ico_watchviolence'\n },\n dialogue: {\n key: 'dialogue',\n name: '대사',\n class: 'ico_watchcurse'\n },\n fear: {\n key: 'fear',\n name: '공포',\n class: 'ico_watchfear'\n },\n drug: {\n key: 'drug',\n name: '약물',\n class: 'ico_watchdrug'\n },\n imitation: {\n key: 'imitation',\n name: '모방위험',\n class: 'ico_watchcopyrisk'\n }\n };\n\n Constants.RATING_LEVEL = {\n NONE: {\n key: 'NONE',\n value: 0,\n name: ''\n },\n LOW: {\n key: 'LOW',\n value: 1,\n name: '낮음'\n },\n NORMAL: {\n key: 'NORMAL',\n value: 2,\n name: '보통'\n },\n LOW_HIGH: {\n key: 'LOW_HIGH',\n value: 3,\n name: '다소높음'\n },\n MEDIUM_HIGH: {\n key: 'MEDIUM_HIGH',\n value: 4,\n name: '높음'\n },\n HIGH: {\n key: 'HIGH',\n value: 5,\n name: '매우높음'\n }\n };\n\n Constants.SUBTITLE = {\n STATUS: {\n OFF: 'off'\n }\n };\n\n Constants.DRM = {\n TYPE: {\n WIDEVINE: 'widevine',\n FAIRPLAY: 'fairplay',\n PLAYREADY: 'playready'\n }\n };\n\n exports.constants = Constants;\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\nvar utils = (function (exports) {\n 'use strict';\n\n function _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) {\n return typeof obj;\n } : function (obj) {\n return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n }, _typeof(obj);\n }\n\n function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n }\n\n function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n }\n\n function _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n Object.defineProperty(Constructor, \"prototype\", {\n writable: false\n });\n return Constructor;\n }\n\n var Tiara=function(){var dt=window.daumtools;var constants=window.monet.constants;var phase=window.monet.phase;var defaultConfig={svcDomain:constants.TIARA.SVC_DOMAIN,deployment:phase!=='prod'?'dev':'production'};var tiaraInstance=window.TiaraTracker&&window.TiaraTracker.getInstance();var setSection=function setSection(sectionName){tiaraInstance.setSection(sectionName);};var setPage=function setPage(pageName){tiaraInstance.setPage(pageName);};var setExtras=function setExtras(extras){if(extras.actionKind){tiaraInstance.actionKind(extras.actionKind);}if(extras.customProps){tiaraInstance.customProps(extras.customProps);}if(extras.url){tiaraInstance.setUrl(extras.url);}if(extras.referrer){tiaraInstance.setReferrer(extras.referrer);}if(extras.pageMeta){tiaraInstance.pageMeta(extras.pageMeta);}if(extras.eventMeta){tiaraInstance.eventMeta(extras.eventMeta);}if(extras.click){tiaraInstance.click(extras.click);}if(extras.search){tiaraInstance.search(extras.search);}if(extras.ecommerce){tiaraInstance.ecommerce(extras.ecommerce);}if(extras.ecommerceContents){tiaraInstance.ecommerceContents(extras.ecommerceContents);}if(extras.usage){tiaraInstance.usage(extras.usage);}if(extras.viewImpContents){tiaraInstance.viewImpContents(extras.viewImpContents);}};var setParameters=function setParameters(params){setSection(params.section);setPage(params.page);setExtras(params.extra);};var init=function init(config){if(!tiaraInstance){console.error('Tiara SDK is missing!');return;}if(config&&_typeof(config)==='object'){dt.extend(defaultConfig,config,true);tiaraInstance.init(defaultConfig);}};var trackViewImp=function trackViewImp(params){setParameters(params);tiaraInstance.trackViewImp().track();};var trackEvent=function trackEvent(params){if(!params.action){console.error('action name is missing!');return;}setParameters(params);tiaraInstance.trackEvent(params.action).track();};var trackUsage=function trackUsage(params){setParameters(params);tiaraInstance.trackUsage().track();};init();return {init:init,trackEvent:trackEvent,trackViewImp:trackViewImp,trackUsage:trackUsage};}();\n\n var MonetWebSocket=/*#__PURE__*/function(){function MonetWebSocket(){_classCallCheck(this,MonetWebSocket);this.ws=null;this.listener={};window.monetWS=this;}_createClass(MonetWebSocket,[{key:\"open\",value:function open(server,listener){var protocol=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];this.ws=new WebSocket(server,protocol);this.listener=listener;this.ws.onopen=this.onOpen;this.ws.onmessage=this.onMessage;this.ws.onerror=this.onError;}},{key:\"send\",value:function send(msg){if(this.ws.readyState===WebSocket.OPEN){this.ws.send(JSON.stringify(msg));}}},{key:\"close\",value:function close(){this.ws.close();}},{key:\"onOpen\",value:function onOpen(event){if(window.monetWS.listener.onOpen){window.monetWS.listener.onOpen(event);}}},{key:\"onMessage\",value:function onMessage(event){if(window.monetWS.listener.onMessage){window.monetWS.listener.onMessage(event);}}},{key:\"onError\",value:function onError(event){if(window.monetWS.listener.onError){window.monetWS.listener.onError(event);}}}]);return MonetWebSocket;}();\n\n var parseXmlToJson=function parseXmlToJson(xmldata,option){var helpers=window.monet.helpers;var result={};try{result=window.parser.parse(xmldata,option);}catch(error){helpers.debug.error('parse xml to json',error.message);}return result;};var isNonEmptyArray=function isNonEmptyArray(arr){return Array.isArray(arr)&&arr.length>0;};var isNonEmptyString=function isNonEmptyString(str){return typeof str==='string'&&str.length>0;};var hasValue=function hasValue(item){return item!=null&&isNonEmptyString(item);};var isEmptyObject=function isEmptyObject(obj){return Object.keys(obj).length===0&&obj.constructor===Object;};\n\n exports.MonetWebSocket = MonetWebSocket;\n exports.Tiara = Tiara;\n exports.hasValue = hasValue;\n exports.isEmptyObject = isEmptyObject;\n exports.isNonEmptyArray = isNonEmptyArray;\n exports.isNonEmptyString = isNonEmptyString;\n exports.parseXmlToJson = parseXmlToJson;\n\n Object.defineProperty(exports, '__esModule', { value: true });\n\n return exports;\n\n})({});\n\n(function(exports, dt) {\n 'use strict';\n\n var env = exports.ENV;\n var ua = window.ua_result;\n var constants = exports.constants;\n\n var hp = (exports.helpers = {\n http: {\n ajax: function(url, callbacks, config) {\n if (!config) {\n config = {};\n }\n\n if (typeof callbacks === 'function') {\n var successCallback = callbacks;\n callbacks = {};\n callbacks.onSuccess = successCallback;\n }\n\n try {\n var _async = config.async;\n var _type = config.type ? config.type : constants.HTTP.TYPE.TEXT;\n var _method = config.method ? config.method : constants.HTTP.METHOD.GET;\n var _body = config.body || null;\n\n var xmlHttp = new XMLHttpRequest();\n xmlHttp.open(_method, url, _async);\n xmlHttp.onreadystatechange = function() {\n if (xmlHttp.readyState !== 4) {\n return;\n }\n var result = xmlHttp.responseType === 'arraybuffer' ? xmlHttp.response : xmlHttp.responseText;\n if (_type === constants.HTTP.TYPE.JSON && result) {\n if (result) {\n try {\n result = JSON.parse(result);\n } catch (e) {\n hp.debug.error(e.message);\n }\n }\n }\n\n if (xmlHttp.status === 200) {\n callbacks.onSuccess(result);\n } else if (typeof callbacks.onError === 'function') {\n callbacks.onError(result);\n }\n };\n if (config.credentials === 'include') {\n xmlHttp.withCredentials = true;\n }\n\n if (config.async && config.timeout > 0) {\n if (typeof callbacks.onTimeout === 'function') {\n xmlHttp.timeout = config.timeout;\n xmlHttp.ontimeout = callbacks.onTimeout;\n }\n }\n\n if (config && config.headers) {\n for (var key in config.headers) {\n xmlHttp.setRequestHeader(key, config.headers[key]);\n }\n }\n\n if (config && config.responseType) {\n xmlHttp['responseType'] = config.responseType;\n }\n\n xmlHttp.send(_body);\n } catch (e) {\n if (typeof callbacks.onError === 'function') {\n callbacks.onError();\n }\n }\n },\n fetchMethod: function(url, callbacks, config) {\n var onSuccess = callbacks.onSuccess;\n var onError = callbacks.onError;\n var onTimeout = callbacks.onTimeout;\n var didTimeOut = false;\n var timeout = {};\n\n if (config.timeout > 0) {\n timeout = setTimeout(function() {\n didTimeOut = true;\n onTimeout();\n }, config.timeout);\n }\n\n window\n .fetch(url, config)\n .then(function(response) {\n clearTimeout(timeout);\n\n if (didTimeOut) {\n return;\n }\n\n var result = config.type === constants.HTTP.TYPE.JSON ? response.json() : response.text();\n\n return result.then(function(json) {\n if (response.status === 200) {\n onSuccess(json);\n } else {\n onError(json);\n }\n });\n })\n .catch(function(e) {\n if (didTimeOut) {\n return;\n }\n\n onError(e);\n });\n },\n fetch: function(url, option) {\n var http = this;\n\n return new Promise(function(resolve, reject) {\n var config = http.setConfig(option);\n var httpRequestMethod = http.getHttpRequestMethod(config.async);\n\n httpRequestMethod(\n url,\n {\n onSuccess: resolve,\n onError: http.reject.bind(http, 'onError', reject),\n onTimeout: http.reject.bind(http, 'onTimeout', reject)\n },\n config\n );\n });\n },\n getHttpRequestMethod: function(async) {\n var httpRequestMethod;\n\n if (!this.supportFetch() || !async) {\n httpRequestMethod = this.ajax;\n } else {\n httpRequestMethod = this.fetchMethod;\n }\n\n return httpRequestMethod;\n },\n supportFetch: function() {\n var supportFetch = window.fetch;\n var response = window.Response ? new window.Response() : {};\n var supportResponseJson = response.json;\n\n return !!(supportFetch && supportResponseJson);\n },\n setConfig: function(option) {\n var headers = {};\n var config = option || {};\n\n if (config.headers) {\n headers = option.headers;\n }\n\n if (config.contentType) {\n headers['Content-Type'] = config.contentType;\n } else {\n headers['Content-Type'] = 'application/x-www-form-urlencoded';\n }\n\n if (typeof option.async === 'undefined') {\n config.async = true;\n }\n\n config.headers = headers;\n\n return config;\n },\n reject: function(type, reject, e) {\n var error = e || {};\n error.type = type;\n\n reject(error);\n },\n sendBeacon: function(url) {\n var img = new Image();\n img.src = url;\n return img;\n }\n },\n debug: (function() {\n var _isDebug = env.debugMode;\n var isShowServerSetting = false;\n\n return {\n isDebug: function() {\n return _isDebug;\n },\n setDebug: function(isDebug) {\n _isDebug = isDebug;\n },\n log: function() {\n if (_isDebug) {\n dt.log.apply(null, arguments);\n }\n },\n debug: function() {\n if (_isDebug) {\n dt.debug.apply(null, arguments);\n }\n },\n info: function() {\n if (_isDebug) {\n dt.info.apply(null, arguments);\n }\n },\n warn: function() {\n if (_isDebug) {\n dt.warn.apply(null, arguments);\n }\n },\n error: function() {\n if (_isDebug) {\n dt.error.apply(null, arguments);\n }\n hp.sentry.captureException(arguments);\n },\n table: function() {\n if (_isDebug) {\n dt.table.apply(null, arguments);\n }\n },\n group: function() {\n if (_isDebug) {\n dt.group.apply(null, arguments);\n }\n },\n groupEnd: function() {\n if (_isDebug) {\n dt.groupEnd.apply(null, arguments);\n }\n },\n groupCollapsed: function() {\n if (_isDebug) {\n dt.groupCollapsed.apply(null, arguments);\n }\n },\n tooltip: function(message, log) {\n if (_isDebug) {\n var div = document.createElement('div');\n\n var length = dt.$$('.debug_tooltip div').length;\n div.innerHTML = message + log;\n dt.$$('.debug_tooltip')[0].appendChild(div);\n\n dt.classList.add(div, 'visible');\n dt.classList.remove(div, 'hidden');\n\n var self = this;\n var timer = setTimeout(function() {\n self.hideTooltip(div);\n clearTimeout(timer);\n }, (length + 1) * 1700);\n }\n },\n hideTooltip: function(target) {\n var self = this;\n dt.classList.add(target, 'hidden');\n dt.classList.remove(target, 'visible');\n self.removeTooltip(target);\n },\n removeTooltip: function(target) {\n setTimeout(function() {\n dt.$$('.debug_tooltip')[0].removeChild(target);\n }, 1500);\n },\n isShowServerSetting: function() {\n return isShowServerSetting;\n },\n setShowServerSetting: function(show) {\n isShowServerSetting = show;\n }\n };\n })(),\n device: {\n getDteType: function(ua) {\n if (ua.os.name === 'ios') {\n if (ua.platform === 'tablet') {\n return constants.DTE_TYPE.IPAD;\n } else {\n return constants.DTE_TYPE.IPHONE;\n }\n } else if (ua.os.name === 'android') {\n return constants.DTE_TYPE.ANDROID;\n } else if (ua.platform === 'pc') {\n return constants.DTE_TYPE.PC;\n } else {\n return constants.DTE_TYPE.ETC;\n }\n },\n isTV: function(ua) {\n var televisions = ['netcast', 'smarttv', 'smart-tv'];\n\n function checkDevice(arr, ua) {\n return arr.some(function(arrVal) {\n return ua.ua.indexOf(arrVal) !== -1;\n });\n }\n return checkDevice(televisions, ua);\n },\n isSupportThumbnailVideo: function(ua) {\n return !this.isTV(ua) && !this.isAndroidDown5(ua);\n },\n isSupportUniversalLinks: function(ua) {\n return parseInt(ua.os.version.major, 10) > 8 && ua.os.ios;\n },\n isSupportMutedControl: function(ua) {\n if (ua.os.ios && ua.os.version.major <= 9) {\n return false;\n }\n return true;\n },\n isPCWithSafari: function(ua) {\n var isPC = ua.platform === 'pc';\n return !!(isPC && ua.ua.match(/version\\/[\\d.]+.*safari/));\n },\n isMobileWithSafari: function(ua) {\n var isMobile = ua.platform === 'mobile';\n return !!(isMobile && ua.ua.match(/version\\/[\\d.]+.*safari/));\n },\n isSupportInlinePlayOnIOS: function(ua) {\n // ios이고 playsinline이 true일 경우 => true\n return ua.os.ios && env.playsinline;\n },\n isSupportInlinePlayOnPC: function(ua) {\n var isPC = ua.platform === 'pc';\n var isIE = ua.browser.msie;\n var isIE9Under = isIE && ua.browser.version.major < 9;\n\n return isPC && (!isIE || !isIE9Under);\n },\n isAndroidDown5: function(ua) {\n return !!(ua.os.android && ua.os.version.major < 5);\n },\n isSupportDesktopBrowser: function(ua) {\n var isPC = ua.platform === 'pc';\n var isIE = !!ua.browser.msie;\n var isIE11Under = isIE && ua.browser.version.major < 11;\n return isPC && (!isIE || !isIE11Under);\n },\n isIMASupportedBrowser: function(ua) {\n if (this.isSupportDesktopBrowser(ua) || !this.isAndroidDown5(ua)) {\n return true;\n }\n return false;\n },\n isSupportInlinePlay: function(ua) {\n // iOS환경에서 playsinline 옵션 true인지 확인\n if (this.isSupportInlinePlayOnIOS(ua)) {\n return true;\n }\n\n if (this.isSupportInlinePlayOnPC(ua)) {\n return true;\n }\n\n var androidOver4 = ua.os.android && ua.browser.version.major >= 4;\n var ipad = ua.browser.ipad;\n var androidChrome = ua.browser.chrome;\n var smarttv = /smarttv/gi.test(ua.ua);\n\n return androidOver4 || ipad || androidChrome || smarttv;\n },\n isSupportCustomController: function(ua) {\n if (!this.isSupportInlinePlay(ua)) {\n return false;\n }\n\n if (\n /LG-\\wU540/gi.test(ua.ua) ||\n /KM-S220/gi.test(ua.ua) ||\n (ua.os.version.major === 4 && parseInt(ua.os.version.minor) === 0 && / IM-[AT]/gi.test(ua.ua)) ||\n (ua.os.version.major === 4 && parseInt(ua.os.version.minor) === 0 && / SHV-E160/gi.test(ua.ua)) ||\n (ua.os.version.major === 4 && parseInt(ua.os.version.minor) === 0 && / SHW-M250/gi.test(ua.ua))\n ) {\n return false;\n }\n\n return true;\n },\n isSupportAd: function(ua) {\n if (this.isSupportCustomController(ua)) {\n return true;\n }\n\n var uaStr = ua.ua;\n var major = ua.os.version.major;\n var minor = ua.os.version.minor;\n\n if (/LG-\\w180/gi.test(uaStr) && major === 4 && minor < 2) {\n return false;\n }\n },\n isFacebookWebview: function() {\n try {\n return /.*FBIOS.*/.test(window.navigator.userAgent);\n } catch (e) {}\n\n return false;\n },\n isKakaotalkWebview: function(ua) {\n return ua.ua.indexOf('kakaotalk') !== -1;\n },\n isChannelWebView: function(ua) {\n return ua.ua.indexOf('ch-home') !== -1;\n },\n isKaKaoSubscribeWebView: function(ua) {\n return ua.ua.indexOf('view_subtab') !== -1;\n },\n isTalkWebView: function(ua) {\n return this.isKakaotalkWebview(ua) || this.isChannelWebView(ua) || this.isKaKaoSubscribeWebView(ua);\n },\n isAllowContentAcessTalkWebView: function() {\n var ALLOW_CONTENT_ACCESS_TALK_VERSION = 2309550;\n var match = /(kakaotalk )(\\d+)/.exec(ua.ua);\n var version = match && match[2] ? parseInt(match[2], 10) : 0;\n\n return version >= ALLOW_CONTENT_ACCESS_TALK_VERSION;\n },\n isiPadOS: function() {\n var isIOS =\n (/iPad|iPod/.test(navigator.platform) ||\n (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&\n !window.MSStream;\n\n return isIOS;\n },\n isSupportAjaxAsync: function(ua) {\n var isAllowedChromeVersion = true;\n\n if (ua.browser.chrome && ua.browser.version.major < 66) {\n isAllowedChromeVersion = false;\n }\n\n return !ua.os.ios && !this.isPCWithSafari(ua) && !this.isAndroidDown5(ua) && isAllowedChromeVersion;\n },\n isIeBrowser11Under: function(ua) {\n var isIE = !!ua.browser.msie;\n var isIE11Under = isIE && ua.browser.version.major < 11;\n return isIE && isIE11Under;\n },\n isiOSOver14: function(ua) {\n return ua.os.ios && ua.os.version.major >= 14;\n },\n isMacOSChrome89Over: function(ua) {\n return ua.os.mac && ua.browser.chrome && ua.browser.version.major > 88;\n }\n },\n env: {\n phase: env.phase.toUpperCase(),\n isProd: function() {\n return this.phase === constants.PHASE.PROD;\n },\n isCbt: function() {\n return this.phase === constants.PHASE.CBT;\n },\n isDev: function() {\n return this.phase === constants.PHASE.DEV;\n },\n isSandbox: function() {\n return this.phase === constants.PHASE.SANDBOX;\n },\n isLocal: function() {\n return this.phase === constants.PHASE.LOCAL;\n }\n },\n feature: {\n canPlayHLS: function() {\n var v = document.getElementById(constants.ID.VIDEO_ELEMENT);\n return !!(\n v.canPlayType && v.canPlayType('application/x-mpegURL; codecs=\"avc1.42E01E\"').replace(/^no$/, '')\n );\n },\n supportsH264: function() {\n var v = document.getElementById(constants.ID.VIDEO_ELEMENT);\n return !!(\n v.canPlayType &&\n (this.canPlayType(ua, v, 'video/mp4; codecs=\"avc1.42E01E\"') ||\n this.canPlayType(ua, v, 'video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'))\n );\n },\n getVideoExtra: function(profile) {\n return profile === 'HIGH' ? '1' : profile === 'MAIN' ? '2' : profile === 'BASE' ? '3' : '4';\n },\n canPlayHLSAndroid: function() {\n var osVersion = ua.os.version;\n\n var supportedOS =\n ua.os.android && (osVersion.major > 4 || (osVersion.major > 3 && osVersion.minor > 3));\n var supportedBrowser = ua.browser.chrome && ua.browser.version.major > 35;\n\n if (supportedOS && supportedBrowser && this.canPlayHLS()) {\n return true;\n }\n\n return false;\n },\n /**\n * There is a bug in iOS 4.1 or earlier where probably and maybe are switched around.\n * This bug was reported and fixed in iOS 4.2\n * @param {HTMLElement} element\n * @param {string} type\n * @returns {boolean}\n * @see {@link https://bugs.webkit.org/show_bug.cgi?id=44519|webkit}\n */\n canPlayType: function(ua, element, type) {\n var version = ua.os.version;\n\n if (ua.os === 'ios' && version.major <= 4 && version.minor < 2) {\n return element.canPlayType(type) === 'probably' || element.canPlayType(type) === 'maybe';\n } else {\n return element.canPlayType(type) === 'probably';\n }\n },\n supportsVideoProfile: function(profile) {\n for (var p in constants.PROFILE) {\n if (constants.PROFILE.hasOwnProperty(p)) {\n if (profile === p) {\n return true;\n }\n }\n }\n return false;\n }\n },\n date: {\n hhmmssToDate: function(hhmmss) {\n if (hhmmss) {\n var time = hhmmss.split(':');\n var d = new Date(); // creates a Date Object using the clients current time\n\n d.setHours(+time[0]); // set Time accordingly, using implicit type coercion\n d.setMinutes(time[1]); // you can pass Number or String, it doesn't matter\n d.setSeconds(time[2]);\n\n return d;\n }\n return null;\n }\n },\n fullscreen: function(playerElement, videoElement) {\n var requestFullscreen =\n playerElement.requestFullscreen ||\n playerElement.webkitRequestFullscreen ||\n playerElement.webkitRequestFullScreen ||\n playerElement.mozRequestFullScreen ||\n playerElement.msRequestFullscreen;\n\n var exitFullscreen =\n document.exitFullscreen ||\n document.webkitExitFullscreen ||\n document.webkitCancelFullScreen ||\n document.mozCancelFullScreen ||\n document.msExitFullscreen;\n\n var webkitEnterFullscreen = videoElement.webkitEnterFullscreen;\n var webkitExitFullscreen = videoElement.webkitExitFullScreen;\n\n var supportFullscreen = !!(requestFullscreen && exitFullscreen);\n\n return {\n isSupport: function() {\n return supportFullscreen;\n },\n request: function(options) {\n return requestFullscreen.call(playerElement, options);\n },\n exit: function() {\n if (this.isFullScreen()) {\n exitFullscreen.call(document);\n }\n },\n isSupportOnlyIOS: function() {\n return !!(webkitEnterFullscreen && webkitExitFullscreen);\n },\n setFullscreen: function(state) {\n if (state) {\n try {\n webkitEnterFullscreen.call(videoElement);\n } catch (e) {}\n } else {\n webkitExitFullscreen.call(videoElement);\n }\n },\n isFullScreen: function() {\n var fullscreen =\n !!(\n document.fullScreen ||\n document.fullscreenElement ||\n document.webkitCurrentFullScreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement\n ) || videoElement.webkitDisplayingFullscreen;\n\n if (!fullscreen) {\n return false;\n }\n\n if (\n videoElement.webkitPresentationMode &&\n videoElement.webkitPresentationMode === 'picture-in-picture'\n ) {\n return false;\n }\n\n return fullscreen;\n },\n isFullScreenChangeEvent: function(e) {\n var eventType = e.type && e.type.toLowerCase();\n return eventType && eventType.indexOf('fullscreenchange') !== -1;\n }\n };\n },\n string: {\n escapeHtml: function(unsafe) {\n return unsafe\n .replace(/&/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n },\n jsonToQueryString: function(data) {\n if (typeof data !== 'object') {\n return;\n }\n\n var result = '';\n for (var key in data) {\n if (data.hasOwnProperty(key)) {\n result += key + '=' + data[key] + '&';\n }\n }\n result = result.slice(0, result.length - 1);\n return result;\n },\n separateTimes: function(totalSec) {\n var sec = Math.floor(totalSec % 60);\n var min = Math.floor(totalSec / 60);\n var hour = Math.floor(min / 60);\n\n min = Math.floor(min % 60);\n\n if (min < 10) {\n min = '0' + min;\n }\n\n if (sec < 10) {\n sec = '0' + sec;\n }\n\n return {\n hour: hour,\n min: min,\n sec: sec\n };\n },\n timeToString: function(totalSec) {\n var times = this.separateTimes(totalSec);\n return (times.hour > 0 ? times.hour + '시간' : '') + times.min + '분' + times.sec + '초';\n },\n stringToSec: function(timeString) {\n var sec = 0;\n var splitTime = timeString.split(':').reverse();\n\n for (var i = 0; i < splitTime.length; i++) {\n var calcTime = parseInt(splitTime[i]) * Math.pow(60, i);\n sec += calcTime;\n }\n\n return sec;\n },\n delimitTimes: function(totalSec, de) {\n var times = this.separateTimes(totalSec);\n var delimiter = de || ':';\n return (times.hour > 0 ? times.hour + delimiter : '') + times.min + delimiter + times.sec;\n },\n delimitNumbers: function(str) {\n return (str + '').replace(/\\b(\\d+)((\\.\\d+)*)\\b/g, function(a, b, c) {\n return (\n (b.charAt(0) > 0 && !(c || '.').lastIndexOf('.') ? b.replace(/(\\d)(?=(\\d{3})+$)/g, '$1,') : b) +\n c\n );\n });\n },\n sec2hhmmss: function(timeInSeconds) {\n var time = parseFloat(timeInSeconds).toFixed(0);\n var hours = Math.floor(time / 60 / 60);\n var minutes = Math.floor(time / 60) % 60;\n var seconds = Math.floor(time - minutes * 60);\n\n return this.pad(hours, 2) + ':' + this.pad(minutes, 2) + ':' + this.pad(seconds, 2);\n },\n pad: function(num, size) {\n return ('000' + num).slice(size * -1);\n },\n format: function(string, data) {\n for (var key in data) {\n if (data.hasOwnProperty(key) && key) {\n var value = data[key];\n\n if (value === null || typeof value === 'undefined') {\n value = '';\n }\n if (typeof value === 'string') {\n value = value.replace('$', '$$$$');\n }\n string = string.replace('#{' + key + '}', value);\n }\n }\n return string;\n },\n getThumbnailFarmUrl: function(url, type) {\n if (!url) {\n return '';\n }\n\n if (type) {\n url = url.replace(/thumb\\/(.+)\\/\\?fname/, 'thumb/' + type + '.q50.fjpeg/?fname');\n } else {\n url = url.replace(/thumb\\/(.+)\\/\\?fname/, 'thumb/$1.q50.fjpg/?fname');\n }\n\n return hp.string.format(constants.URL.THUMBNAIL_FARM_URL, {\n type: type,\n url: encodeURIComponent(url)\n });\n },\n replaceLinefeed: function(string) {\n if (!string || typeof string !== 'string') {\n return string;\n }\n return string.replace(/\\n/g, '
');\n }\n },\n orientation: (function() {\n return {\n getOrientation: function() {\n return window.screen.width > window.screen.height ? 'landscape' : 'portrait';\n },\n isSupportOrientation: function() {\n return window.screen.orientation;\n }\n };\n })(),\n window: {\n openPopup: function(url, windowName, features) {\n var windowRef = window.open(url, windowName, features);\n if (windowRef) {\n windowRef.focus();\n windowRef.opener = null;\n }\n }\n },\n url: (function() {\n return {\n getParameter: function(param) {\n if (!window.location.search) {\n return;\n }\n var m = new RegExp(param + '=([^&]*)').exec(window.location.search.substring(1));\n if (!m) {\n return;\n }\n return decodeURIComponent(m[1]);\n },\n setParameter: function(search, name, value) {\n search = this.removeParameter(search, name);\n if (search === '') {\n search = '?';\n }\n if (search.length > 1) {\n search += '&';\n }\n return search + name + '=' + encodeURIComponent(value);\n },\n removeParameter: function(search, name) {\n if (search[0] === '?') {\n search = search.substring(1);\n }\n var parts = search.split('&');\n var res = [];\n for (var i = 0; i < parts.length; i++) {\n var pair = parts[i].split('=');\n if (pair[0] === name) {\n continue;\n }\n res.push(parts[i]);\n }\n search = res.join('&');\n if (search.length > 0) {\n search = '?' + search;\n }\n return search;\n },\n isValidate: function(value) {\n var expression = /[-a-zA-Z0-9@:%_+.~#?&//=]{2,256}\\.[a-z]{2,4}\\b(\\/[-a-zA-Z0-9@:%_+.~#?&//=]*)?/gi;\n var regexp = new RegExp(expression);\n return regexp.test(value);\n },\n addParam: function(url, paramName, value) {\n if (/\\?/.test(url)) {\n return url + '&' + paramName + '=' + value;\n } else {\n return url + '?' + paramName + '=' + value;\n }\n }\n };\n })(),\n store: {\n set: function(name, value, expireDay) {\n var date = new Date();\n var expireTime = (expireDay || 365) * 24 * 60 * 60 * 1000;\n var timeZoneOffset = 9;\n\n date.setTime(date.getTime() + expireTime + timeZoneOffset * 3600000);\n var time = date.toGMTString();\n\n hp.storage.setItem(name, value, time);\n hp.cookie.setItem(name, value, time);\n },\n get: function(name) {\n if (!hp.storage.enabled && !hp.cookie.enabled) {\n return null;\n }\n\n var value = hp.storage.getItem(name);\n if (!value || value === '') {\n value = hp.cookie.getItem(name);\n }\n\n return value;\n }\n },\n cookie: (function() {\n var enabled = true;\n\n function sendError(e, key) {\n enabled = false;\n dt.error(e, key);\n }\n\n try {\n var d = new Date();\n d.setTime(d.getTime() + 1000);\n setItem('testcookie', 'test', d);\n enabled = !!getItem('testcookie');\n removeItem('testcookie');\n } catch (e) {\n enabled = false;\n sendError(e, 'cookie setItem error');\n }\n\n function getItem(name) {\n if (enabled) {\n var ckName = name + '=';\n var cookie = document.cookie;\n var start = cookie.indexOf(ckName);\n var end;\n\n if (start !== -1) {\n start += ckName.length;\n end = cookie.indexOf(';', start);\n if (end === -1) {\n end = cookie.length;\n }\n return decodeURIComponent(cookie.substring(start, end));\n }\n }\n\n return '';\n }\n\n function setItem(name, value, expireTime) {\n if (enabled) {\n var expires = 'expires=' + expireTime;\n document.cookie = name + '=' + value + '; ' + expires;\n }\n }\n\n function removeItem(name) {\n var d = new Date();\n d.setTime(d.getTime() - 1000 * 60 * 60 * 24);\n var expires = 'expires=' + d.toGMTString();\n document.cookie = name + '=' + '; ' + expires;\n }\n\n return {\n enabled: enabled,\n setItem: setItem,\n getItem: getItem\n };\n })(),\n storage: (function(frame) {\n var enabled = true;\n\n function sendError(e, key) {\n enabled = false;\n dt.error(e, key);\n }\n\n try {\n frame.localStorage.setItem('t', 1);\n frame.localStorage.removeItem('t');\n } catch (e) {\n enabled = false;\n }\n\n return {\n enabled: enabled,\n forEach: function(callback) {\n var i;\n var keys = [];\n var length = frame.localStorage.length;\n\n for (i = 0; i < length; i += 1) {\n keys.push(frame.localStorage.key(i));\n }\n for (i = 0; i < length; i += 1) {\n callback(keys[i], i);\n }\n },\n setItem: function(key, value, expireTime) {\n var data = {\n value: value,\n expires: expireTime\n };\n\n if (enabled) {\n try {\n frame.localStorage.setItem(key, JSON.stringify(data));\n } catch (e) {\n sendError(e, 'storage setItem error');\n }\n }\n },\n getItem: function(key) {\n var data;\n\n if (enabled) {\n data = frame.localStorage.getItem(key);\n\n try {\n if (data) {\n data = JSON.parse(data);\n\n if (!this.isExpiredTime(key, data.expires)) {\n return data.value;\n }\n }\n\n return '';\n } catch (e) {\n this.removeItem(key);\n sendError(e, 'storage getItem error');\n }\n }\n return '';\n },\n isExpiredTime: function(key, expires) {\n var isExpired = true;\n var date = new Date();\n var currentTime = date.getTime();\n\n date = new Date(expires);\n var expiredTime = date.getTime();\n\n if (expiredTime) {\n currentTime = parseInt(currentTime, 10);\n expiredTime = parseInt(expiredTime, 10);\n\n if (currentTime < expiredTime) {\n isExpired = false;\n } else {\n hp.debug.info('remove', key, 'from localstorage');\n this.removeItem(key);\n }\n }\n return isExpired;\n },\n removeItem: function(key) {\n if (enabled) {\n try {\n frame.localStorage.removeItem(key);\n } catch (e) {\n sendError(e, 'storage removeItem error');\n }\n }\n }\n };\n })(window),\n webapi: (function() {\n var network = {\n getConnection: function() {\n return navigator.connection || navigator.mozConnection || navigator.webkitConnection;\n },\n isWifi: function() {\n var connection = this.getConnection();\n return connection && connection.type === 'wifi';\n }\n };\n\n var share = {};\n var pip = {\n enabled: document.pictureInPictureEnabled,\n isPipScreen: function() {\n var pip = document.pictureInPictureElement;\n var pipscreen =\n pip ||\n (pip && pip.webkitPresentationMode && pip.webkitPresentationMode === 'picture-in-picture');\n\n return pipscreen;\n },\n request: function(videoElement) {\n return videoElement.requestPictureInPicture().catch(hp.debug.error);\n },\n exit: function() {\n return document.exitPictureInPicture().catch(hp.debug.error);\n }\n };\n\n return {\n share: share,\n network: network,\n pip: pip\n };\n })(),\n traversal: {\n nextAll: function(element) {\n var next = [element];\n while (element.nextElementSibling) {\n next.push((element = element.nextElementSibling));\n }\n return next;\n }\n },\n ui: {\n preventDoubleClick: function(el) {\n if (el.tagName === 'BUTTON') {\n el.disabled = true;\n\n setTimeout(function() {\n el.disabled = false;\n }, 500);\n }\n }\n },\n sdk: {\n getDefaultCallbackParams: function(video) {\n var uuid = hp.uuid.get();\n var params;\n if (video.type === constants.VIDEO_TYPE.VOD) {\n params = [video.vid, video.type, video.id, uuid, video.tid];\n } else if (video.type === constants.VIDEO_TYPE.LIVE) {\n params = [null, video.type, video.id, uuid, video.tid];\n }\n\n return params;\n },\n sendEventCallback: function(cbName, cbParam) {\n var hasProperty = constants.PLAYER_CALLBACK_NAME.hasOwnProperty(cbName);\n var callbackParam = [];\n\n if (hasProperty) {\n if (typeof cbParam !== 'undefined' && cbParam instanceof Array) {\n callbackParam = cbParam;\n }\n\n if (window.apiMessenger) {\n window.apiMessenger.sendCallback(cbName, callbackParam);\n }\n } else {\n hp.debug.warn('[event callback] name or parameter is not valid');\n }\n }\n },\n polyfill: {\n getProps: function(prop) {\n var el = document.createElement('div');\n var prefix = this.getPrefix(el.style, prop);\n\n return prefix ? prefix + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;\n },\n getPrefix: function(target, prop) {\n var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];\n\n for (var p = 0, pl = prefixes.length; p < pl; p++) {\n var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;\n\n if (prefixedProp in target) {\n return prefixes[p];\n }\n }\n }\n },\n web2app: {\n launchTalk: function(urlScheme) {\n var appName = '카카오톡';\n var deviceType = ua.os.android ? 'android' : 'ios';\n var PHASE = constants.PHASE[env.phase.toUpperCase()];\n var phaseHost = hp.serverHost.create(env.klimtServer, PHASE);\n\n if (phaseHost.indexOf('kakaotv.daum.net') !== -1) {\n phaseHost = 'https://tv.kakao.com';\n }\n\n var appBridgeLink = '/talkbridge';\n var storeURL = 'https//play.google.com/store/apps/details?id=com.kakao.talk';\n\n var packageName = 'com.kakao.talk';\n var urlParse = urlScheme && urlScheme.split('://');\n var scheme = urlParse[0];\n var url = urlParse[1];\n var intentURI =\n 'intent://' + url + '#Intent' + ';scheme=' + scheme + ';package=' + packageName + ';end;';\n\n var opt = {\n urlScheme: urlScheme,\n appName: appName,\n intentURI: intentURI,\n storeURL: storeURL\n };\n\n if (deviceType === 'ios') {\n window.top.location.href = phaseHost + appBridgeLink + '?shouldMoveStore=1&appScheme=' + urlScheme;\n } else {\n dt.web2app(opt);\n }\n },\n launchApp: function(runType, linkId, profile, from) {\n var deviceType = ua.os.android ? 'android' : 'ios';\n var phase = '';\n var packageName = 'com.kakao.playball';\n var params = '';\n var path = {\n open: 'open',\n live: 'live',\n vod: 'clip'\n };\n\n if (env.phase !== 'prod' && env.phase !== 'cbt') {\n phase = env.phase;\n packageName = packageName + '.' + env.phase;\n }\n if (runType !== 'open' && linkId !== '') {\n params = linkId + '&profile=' + profile + '&from=' + from;\n path.live += '?liveLinkId=' + params;\n path.vod += '?clipLinkId=' + params;\n }\n\n var urlScheme = 'kakaotvlive' + phase + '://' + path[runType];\n var intentURI = 'intent://' + path[runType];\n\n var storeURL =\n deviceType === 'ios'\n ? 'itms-apps://itunes.apple.com/kr/app/id1180460837'\n : 'https://play.google.com/store/apps/details?id=com.kakao.playball';\n\n var appSuffix =\n '#Intent;scheme=kakaotvlive' +\n phase +\n ';action=android.intent.action.VIEW' +\n ';category=android.intent.category.BROWSABLE' +\n ';package=' +\n packageName +\n ';S.browser_fallback_url=' +\n encodeURIComponent(storeURL) +\n ';end';\n\n var appName = '카카오 TV';\n var opt = {\n urlScheme: urlScheme,\n intentURI: intentURI + appSuffix,\n appName: appName,\n storeURL: storeURL\n };\n\n hp.debug.info('kakaotv web2app config', opt);\n dt.web2app(opt);\n },\n launchKakaoTV: function(ua, linkId, profile) {\n var isSupportUniversalLinks = hp.device.isSupportUniversalLinks(ua);\n var deviceType;\n var phaseScheme = {\n ios: 'kakaotvlive',\n android: 'kakaotvlive'\n };\n\n if (ua.os.android) {\n deviceType = 'android';\n } else {\n deviceType = 'ios';\n }\n\n var packageName = 'com.kakao.playball';\n\n if (env.phase !== 'prod' && env.phase !== 'cbt') {\n phaseScheme.android = phaseScheme.android + env.phase;\n phaseScheme.ios = phaseScheme.ios + env.phase;\n packageName = packageName + '.' + env.phase;\n }\n\n var urlScheme = {\n ios:\n phaseScheme.ios +\n '://live?liveLinkId=' +\n linkId +\n '&profile=' +\n profile +\n '&from=' +\n env.service,\n android:\n phaseScheme.android +\n '://live?liveLinkId=' +\n linkId +\n '&profile=' +\n profile +\n '&from=' +\n env.service\n };\n\n var appName = '카카오 TV';\n var storeURL =\n deviceType === 'ios'\n ? 'https://itunes.apple.com/kr/app/id1180460837'\n : 'https://play.google.com/store/apps/details?id=com.kakao.playball';\n\n var intentURI = 'intent://live?liveLinkId=' + linkId + '&profile=' + profile + '&from=' + env.service;\n var appSuffix =\n '#Intent' +\n ';scheme=' +\n phaseScheme.android +\n ';action=android.intent.action.VIEW' +\n ';category=android.intent.category.BROWSABLE' +\n ';package=' +\n packageName +\n ';S.browser_fallback_url=' +\n encodeURIComponent(storeURL) +\n ';end';\n\n var origin = 'play-tv.kakao.com';\n if (document.domain) {\n if (document.domain.indexOf(origin) !== -1) {\n origin = 'tv.kakao.com';\n }\n }\n var universalLink =\n 'https://' +\n origin +\n '/scheme/live?liveLinkId=' +\n linkId +\n '&profile=' +\n profile +\n '&from=' +\n env.service;\n\n var appBridgeLink = '/appbridge';\n\n var opt = {\n urlScheme: urlScheme[deviceType],\n intentURI: intentURI + appSuffix,\n appName: appName,\n storeURL: storeURL,\n onAppMissing: function() {\n if (top !== self) {\n top.location.href = appBridgeLink;\n } else {\n window.open(appBridgeLink, 'blank');\n }\n }\n };\n\n if (isSupportUniversalLinks) {\n opt.universalLink = universalLink;\n }\n\n dt.web2app(opt);\n },\n launchPlusFriend: function(ua, uuid) {\n var deviceType;\n\n if (ua.os.android) {\n deviceType = 'android';\n } else {\n deviceType = 'ios';\n }\n\n var phaseScheme = 'kakaoplus';\n if (env.phase !== 'prod') {\n phaseScheme = 'alphaplus';\n }\n\n var urlScheme = {\n android: phaseScheme + '://plusfriend/home/' + encodeURIComponent(uuid),\n ios: phaseScheme + '://plusfriend/home/' + encodeURIComponent(uuid)\n };\n\n var intentURI = 'intent://plusfriend/home/' + encodeURIComponent(uuid);\n var appSuffix = '#Intent;scheme=kakaoplus;package=com.kakao.talk;end';\n\n var appName = '플러스친구';\n var storeURL = 'itms-apps://itunes.apple.com/kr/app/da-eum-daum/id365494029?mt=8';\n\n hp.debug.log('urlScheme: ' + urlScheme[deviceType]);\n\n var opt = {\n urlScheme: urlScheme[deviceType],\n intentURI: intentURI + appSuffix,\n appName: appName,\n storeURL: storeURL,\n onAppMissing: function(storeURL) {\n try {\n if (typeof window.top.goStore === 'function') {\n window.top.goStore(storeURL);\n }\n } catch (e) {\n hp.debug.error('An error has occurred: ' + e.message);\n }\n }\n };\n\n dt.web2app(opt);\n }\n },\n sentry: (function() {\n if (window.Sentry) {\n window.Sentry.init({\n dsn: constants.SENTRY.CONFIG.DSN[env.phase.toUpperCase()],\n release: env.playerVersion\n });\n }\n\n function captureException(error) {\n if (!window.Sentry) {\n return;\n }\n\n var keys = Object.keys(error);\n var exceptionMassage = [];\n\n for (var i = 0; i < keys.length; i++) {\n var errorDetail = error[keys[i]];\n\n if (!errorDetail) {\n continue;\n }\n\n if (typeof errorDetail === 'object') {\n for (var property in errorDetail) {\n if (errorDetail.hasOwnProperty(property)) {\n exceptionMassage.push(property + ': ' + errorDetail[property]);\n }\n }\n } else if (\n typeof errorDetail === 'string' &&\n errorDetail &&\n !errorDetail.match(/^(%c%s|color: #\\d+)/)\n ) {\n exceptionMassage.push(errorDetail);\n } else {\n exceptionMassage.push(errorDetail);\n }\n }\n\n window.Sentry.captureException(exceptionMassage.join(', '));\n }\n\n function captureMessage(message) {\n if (window.Sentry) {\n window.Sentry.captureMessage(message, constants.SENTRY.DEFAULT_MESSAGE_OPTION.level);\n }\n }\n\n return {\n captureException: captureException,\n captureMessage: captureMessage\n };\n })(),\n uuid: {\n get: function() {\n var uuid = hp.store.get(constants.STORAGE.UUID);\n return uuid === null ? '-1' : uuid;\n },\n set: function(uuid) {\n var cached = this.get();\n if (uuid) {\n hp.store.set(constants.STORAGE.UUID, uuid !== cached ? uuid : cached);\n }\n }\n },\n serverHost: {\n create: function(envHost, phase, scheme) {\n var host = scheme ? scheme + '://' : '//';\n var locationHost = window.location.host;\n\n if (envHost && phase !== constants.PHASE.PROD) {\n host += envHost;\n } else if (\n locationHost.indexOf('tv.kakao.com') !== -1 ||\n locationHost.indexOf('kakaotv.daum.net') !== -1 ||\n locationHost.indexOf('tv.devel.kakao.com') !== -1 ||\n locationHost.indexOf('dev.daum.net') !== -1\n ) {\n host += window.location.host;\n } else {\n host += constants.SUB_DOMAIN.KAKAO[phase] + '.kakao.com';\n }\n\n return host;\n },\n link: function(phase) {\n return 'https://' + constants.SUB_DOMAIN.KAKAO[phase] + '.kakao.com';\n }\n },\n sendOnAlreadyInited: function() {\n var documentState = document.readyState;\n\n if (documentState !== 'loading') {\n this.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onAlreadyInited);\n }\n },\n parser: {\n xml2json: function(xml) {\n var isValid = true;\n var config = {\n attributeNamePrefix: '@_',\n ignoreNameSpace: true,\n ignoreAttributes: false\n };\n return window.utils.parseXmlToJson(xml, config, isValid);\n }\n },\n validator: {\n hasValue: function(value) {\n return window.utils.hasValue(value);\n },\n isNonEmptyArray: function(arr) {\n return window.utils.isNonEmptyArray(arr);\n },\n isNonEmptyString: function(str) {\n return window.utils.isNonEmptyString(str);\n },\n isEmptyObject: function(obj) {\n return window.utils.isEmptyObject(obj);\n },\n isHlsVideo: function(videoUrl) {\n return videoUrl.indexOf('m3u8') !== -1;\n }\n },\n tiara: {\n init: function(config) {\n return window.utils.Tiara.init(config);\n },\n trackEvent: function(params) {\n return window.utils.Tiara.trackEvent(params);\n },\n trackUsage: function(params) {\n return window.utils.Tiara.trackUsage(params);\n },\n trackViewImp: function(params) {\n return window.utils.Tiara.trackViewImp(params);\n }\n },\n tv: {\n isConnected: function() {\n var state = window.cast && window.cast.framework.CastContext.getInstance().getCastState();\n\n return state === 'CONNECTED';\n },\n isOnTv: function(videoElement) {\n var isOnAirPlay = videoElement.webkitCurrentPlaybackTargetIsWireless;\n var isOnChromecast = this.isConnected();\n\n if (isOnAirPlay || isOnChromecast) {\n return true;\n }\n\n return false;\n }\n },\n waiter: {\n // copied from debounce function of underscore.js\n debounce: function(func, wait, immediate) {\n var timeout, result;\n\n var later = function(context, args) {\n timeout = null;\n if (args) {\n result = func.apply(context, args);\n }\n };\n\n function restArguments(func, startIndex) {\n startIndex = startIndex == null ? func.length - 1 : +startIndex;\n return function() {\n var length = Math.max(arguments.length - startIndex, 0);\n var rest = Array(length);\n var index = 0;\n for (; index < length; index++) {\n rest[index] = arguments[index + startIndex];\n }\n switch (startIndex) {\n case 0:\n return func.call(this, rest);\n case 1:\n return func.call(this, arguments[0], rest);\n case 2:\n return func.call(this, arguments[0], arguments[1], rest);\n }\n var args = Array(startIndex + 1);\n for (index = 0; index < startIndex; index++) {\n args[index] = arguments[index];\n }\n args[startIndex] = rest;\n return func.apply(this, args);\n };\n }\n\n var delay = restArguments(function(func, wait, args) {\n return setTimeout(function() {\n return func.apply(null, args);\n }, wait);\n });\n\n var debounced = restArguments(function(args) {\n if (timeout) {\n clearTimeout(timeout);\n }\n if (immediate) {\n var callNow = !timeout;\n timeout = setTimeout(later, wait);\n if (callNow) {\n result = func.apply(this, args);\n }\n } else {\n timeout = delay(later, wait, this, args);\n }\n\n return result;\n });\n\n debounced.cancel = function() {\n clearTimeout(timeout);\n timeout = null;\n };\n\n return debounced;\n },\n // copied from throttle function of underscore.js\n throttle: function(func, wait, options) {\n var now =\n Date.now ||\n function() {\n return new Date().getTime();\n };\n\n var timeout, context, args, result;\n var previous = 0;\n if (!options) {\n options = {};\n }\n\n var later = function() {\n previous = options.leading === false ? 0 : now();\n timeout = null;\n result = func.apply(context, args);\n if (!timeout) {\n context = args = null;\n }\n };\n\n var throttled = function() {\n var _now = now();\n if (!previous && options.leading === false) {\n previous = _now;\n }\n var remaining = wait - (_now - previous);\n context = this;\n args = arguments;\n if (remaining <= 0 || remaining > wait) {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n previous = _now;\n result = func.apply(context, args);\n if (!timeout) {\n context = args = null;\n }\n } else if (!timeout && options.trailing !== false) {\n timeout = setTimeout(later, remaining);\n }\n return result;\n };\n\n throttled.cancel = function() {\n clearTimeout(timeout);\n previous = 0;\n timeout = context = args = null;\n };\n\n return throttled;\n }\n },\n kakao: {\n sendMe: function(templateID, templateArgs, successCallback, failCallback) {\n window.Kakao.Auth.login({\n scope: 'PROFILE,TALK_MESSAGE',\n success: function() {\n window.Kakao.API.request({\n url: '/v2/api/talk/memo/send',\n data: {\n template_id: templateID,\n template_args: templateArgs\n },\n success: function() {\n if (successCallback) {\n successCallback();\n }\n },\n fail: function() {\n if (failCallback) {\n failCallback();\n }\n }\n });\n },\n fail: function(err) {\n alert('failed to login: ' + JSON.stringify(err));\n }\n });\n }\n },\n encoder: {\n base64EncodeUint8Array: function(input) {\n var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n var output = '';\n var chr1;\n var chr2;\n var chr3;\n var enc1;\n var enc2;\n var enc3;\n var enc4;\n var i = 0;\n while (i < input.length) {\n chr1 = input[i++];\n chr2 = i < input.length ? input[i++] : Number.NaN; // Not sure if the index\n chr3 = i < input.length ? input[i++] : Number.NaN; // checks are needed here\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n output += keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);\n }\n return output;\n }\n },\n drm: {\n getType: function(ua) {\n if (ua.browser.msie || ua.browser.edge) {\n return constants.DRM.TYPE.PLAYREADY;\n } else if (ua.browser.safari || ua.os.name === 'ios') {\n return constants.DRM.TYPE.FAIRPLAY;\n } else {\n return constants.DRM.TYPE.WIDEVINE;\n }\n }\n }\n });\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\nthis[\"monet\"] = this[\"monet\"] || {};\nthis[\"monet\"][\"template\"] = this[\"monet\"][\"template\"] || {};\nthis[\"monet\"][\"template\"][\"m_clip_list\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"clipList\",c,p,1),c,p,0,13,436,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \\\"\\\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.f(\"title\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.f(\"duration\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}if(t.s(t.f(\"noDataList\",c,p,1),c,p,0,465,494,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);t.b(t.rp(\"\");t.b(\"\\n\" + i);});c.pop();}return t.fl(); },partials: {\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \\\"\\\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.f(\"title\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\" 조회수 \");t.b(t.v(t.f(\"viewCount\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}if(t.s(t.f(\"noDataList\",c,p,1),c,p,0,443,472,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);t.b(t.rp(\"\");t.b(\"\\n\" + i);});c.pop();}return t.fl(); },partials: {\"\");t.b(t.v(t.f(\"profileLabel\",c,p,0)));t.b(t.t(t.f(\"supHD\",c,p,0)));t.b(t.t(t.f(\"sup4K\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);});c.pop();}return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"install_agent\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"
    \");t.b(\"\\n\" + i);t.b(\"
    \");t.b(\"\\n\" + i);t.b(\" HD 고화질 라이브\");t.b(\"\\n\" + i);t.b(\"

    고화질로 생생한 라이브를 시청하기 위해서는 아래 프로그램 설치가 필요합니다.

    \");t.b(\"\\n\" + i);t.b(\"

    \");t.b(\"\\n\" + i);if(t.s(t.f(\"installExt\",c,p,1),c,p,0,292,418,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\" 라이브 에이전트는 사용자의 PC자원 일부를 사용합니다.
    프로그램 설치가 안될 경우 설치안내\");t.b(\"\\n\" + i);});c.pop();}t.b(\"

    \");t.b(\"\\n\" + i);t.b(\"
    \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
    \");t.b(\"\\n\" + i);t.b(\"
    \");t.b(\"\\n\" + i);t.b(\" 설치 없이 일반화질로 재생\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
    \");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"link_info\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"문의하기\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"extension_profile_list\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"outputs\",c,p,1),c,p,0,12,160,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"action_button\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(t.t(t.f(\"actionText\",c,p,0)));t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"\");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"ad_noti_text\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"

    \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" 맞춤형 광고 안내\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.t(t.f(\"notiText\",c,p,0)));t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"

    \");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"clip_cover_image\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"thumbnails\",c,p,1),c,p,0,15,195,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \\\"\\\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"keyboard_effect_text\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"\");t.b(t.v(t.f(\"effectText\",c,p,0)));t.b(\"\");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"mobile_profile_text\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");if(t.s(t.f(\"profileAuto\",c,p,1),c,p,0,110,116,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"자동
    \");});c.pop();}t.b(t.v(t.f(\"profile\",c,p,0)));t.b(\"
    \");t.b(\"\\n\" + i);t.b(\"
    화질변경\");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"mobile_subtitle_list\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"textTracks\",c,p,1),c,p,0,15,114,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}t.b(\"
  • \");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"pc_profile_list\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"outputs\",c,p,1),c,p,0,12,165,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"pc_subtitle_list\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"textTracks\",c,p,1),c,p,0,15,114,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}t.b(\"
  • \");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"profile_text\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"profileAuto\",c,p,1),c,p,0,16,50,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"자동\");t.b(\"\\n\" + i);});c.pop();}t.b(\"\");t.b(t.v(t.f(\"profileText\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);if(t.s(t.f(\"profileHD\",c,p,1),c,p,0,126,156,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"HD\");t.b(\"\\n\" + i);});c.pop();}if(t.s(t.f(\"profile4K\",c,p,1),c,p,0,185,215,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"4K\");t.b(\"\\n\" + i);});c.pop();}t.b(\"\");t.b(\"\\n\" + i);t.b(\" 버튼\");t.b(\"\\n\" + i);t.b(\"\");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"rating_level\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"
    \");t.b(\"\\n\" + i);if(t.s(t.f(\"isMobile\",c,p,1),c,p,0,47,90,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
    \");t.b(\"\\n\" + i);});c.pop();}t.b(\"\\n\" + i);if(t.s(t.f(\"ageLimit\",c,p,1),c,p,0,122,225,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.f(\"name\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);});c.pop();}t.b(\"\\n\" + i);t.b(\"
      \");t.b(\"\\n\" + i);if(t.s(t.f(\"ratingList\",c,p,1),c,p,0,296,447,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
    • \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.f(\"name\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.d(\"level.name\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\"
    • \");t.b(\"\\n\" + i);});c.pop();}t.b(\"
    \");t.b(\"\\n\");t.b(\"\\n\" + i);t.b(\"

    \");t.b(\"\\n\" + i);if(t.s(t.f(\"companyName\",c,p,1),c,p,0,530,580,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\" 상호: \");t.b(t.v(t.f(\"companyName\",c,p,0)));t.b(\"\\n\" + i);t.b(\"
    \");t.b(\"\\n\" + i);});c.pop();}t.b(\"\\n\" + i);if(t.s(t.f(\"serialNumber\",c,p,1),c,p,0,623,665,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\" 등급분류번호: \");t.b(t.v(t.f(\"serialNumber\",c,p,0)));t.b(\"\\n\" + i);});c.pop();}t.b(\"

    \");t.b(\"\\n\" + i);t.b(\"
    \");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"still_image\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");if(t.s(t.f(\"thumbnails\",c,p,1),c,p,0,15,257,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(\"
  • \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \\\"\\\"\");t.b(\"\\n\" + i);t.b(\" 구간 타임 : \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.f(\"time\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
  • \");t.b(\"\\n\" + i);});c.pop();}return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"list_no_data\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\" \\\"\\\"\");t.b(\"\\n\" + i);t.b(\" \\\"\\\"\");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"profile_auto\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"자동\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"superscript_4k\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"4K\");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\nthis[\"monet\"][\"template\"][\"superscript_hd\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"HD\");t.b(\"\\n\");return t.fl(); },partials: {}, subs: { }});\n(function(exports) {\n 'use strict';\n\n var env = exports.ENV;\n var daumtools = window.daumtools;\n daumtools.__CONSOLE_QUIET = env.phase === 'prod' && !env.debugMode;\n\n exports.ua = {};\n exports.configure = typeof exports.configure === 'object' ? exports.configure : {};\n exports.ua = window.ua_result;\n exports.modules = {};\n\n var queue = new daumtools.Observable();\n var Sandbox = (exports.Sandbox = daumtools.Class.extend({\n init: function(module) {\n this.module = module;\n },\n on: function(event, callback) {\n var module = this.module;\n var callbackWrapper = function callbackWrapper() {\n try {\n callback.apply(module, arguments);\n } catch (e) {\n daumtools.error(\n 'event handler error. event: ' +\n event +\n ', module \"' +\n module.__moduleName__ +\n '\"' +\n '\\r\\ncaused by ' +\n e.message\n );\n }\n };\n callbackWrapper.__original__ = callback;\n queue.on(event, callbackWrapper);\n },\n emit: function() {\n var params = arguments[1];\n\n queue.emit.apply(queue, arguments);\n\n return new Promise(function(resolve) {\n resolve(params);\n });\n },\n off: function(event, callback) {\n queue.off(event, callback);\n }\n }));\n\n exports.init = function(player) {\n var modules = exports.modules;\n\n daumtools.group('initialize modules');\n for (var moduleName in modules) {\n if (modules.hasOwnProperty(moduleName)) {\n var module = modules[moduleName];\n\n if (module && module.init) {\n try {\n module.init(player, new Sandbox(module));\n } catch (e) {\n daumtools.error('failed to initialize module \"' + moduleName + '\". caused by ' + e.message);\n }\n } else {\n daumtools.warn('Not exsisted module : \"' + moduleName + '\".');\n }\n }\n }\n daumtools.groupEnd();\n };\n\n exports.addModule = function(name, module, overwrite) {\n var modules = exports.modules;\n if (modules[name] && !overwrite) {\n throw new Error('module \"' + name + '\" already registered');\n }\n modules[name] = module;\n module.__moduleName__ = name;\n daumtools.log('module \"' + name + '\" registered');\n return module;\n };\n\n exports.loadModule = function(name) {\n var modules = exports.modules;\n if (modules[name]) {\n return modules[name];\n }\n };\n\n exports.assert = function(condition, message) {\n if (!condition) {\n throw new Error(message);\n }\n };\n\n exports.queue = new Sandbox({\n __moduleName__: 'Global'\n });\n})((window.monet = typeof window.monet === 'object' ? window.monet : {}));\n\n(function(exports) {\n 'use strict';\n\n var Bean;\n\n Bean = (function() {\n function Bean() {}\n\n Bean.prototype.init = function() {};\n\n Bean.prototype.set = function(values) {\n if (typeof values !== 'object') {\n return;\n }\n\n var keys = Object.keys(values);\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n\n if (this.hasOwnProperty(key)) {\n this[key] = values[key];\n }\n }\n };\n\n return Bean;\n })();\n\n exports.addModule('model.bean', new Bean());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var Clip;\n\n Clip = (function() {\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var constants = exports.constants;\n\n var bean = exports.loadModule('model.bean');\n\n function Clip() {\n this.init();\n }\n\n Clip.prototype.init = function() {\n this.id = null;\n this.vid = null;\n this.linkId = null;\n this.channelId = null;\n this.clipId = null;\n this.userId = null;\n this.videoUrl = null;\n this.status = null;\n this.profile = null;\n this.type = constants.VIDEO_TYPE.VOD;\n this.thumbnailList = null;\n this.coverUrl = null;\n this.duration = null;\n this.xylophoneReq = null;\n this.prerollReq = null;\n this.midrollReq = [];\n this.postrollReq = null;\n this.vmapReq = null;\n this.dsp = 'etc';\n this.tracking = {\n pvt: null,\n pct: null,\n qoe: null\n };\n this.title = null;\n this.canScrap = null;\n this.shouldGeoBlock = null;\n this.hasPlusFriend = null;\n this.plusFriendProfile = null;\n this.isOpen = null;\n this.isLegacy = null;\n this.isOriginal = null;\n this.description = null;\n this.isVertical = null;\n this.isFullVod = null;\n this.ageLimit = null;\n this.tid = null;\n this.wasLive = null;\n this.playingInfo = null;\n this.outputList = [];\n this.login = null;\n this.owner = null;\n this.playCount = null;\n this.channelName = null;\n this.profileImageUrl = null;\n this.skipOnErrorOfAdApi = null;\n this.skipOnErrorOfAdContents = null;\n this.seekUrl = null;\n this.abrVideoLocationList = null;\n this.metaUrl = null;\n this.resumeOffset = null;\n this.originVideoUrl = null;\n this.originProfile = null;\n this.originOutputList = null;\n this.hasRating = null;\n this.textTrack = [];\n this.contentType = null;\n this.purchase = null;\n this.kakaoLink = null;\n this.rating = null;\n this.autoplayPreroll = null;\n this.feedBackData = null;\n this.isDrm = null;\n };\n\n Clip.prototype.set = function(values) {\n debug.log('%c%s', 'color: #EF1414', '[Set] Clip', values);\n bean.set.call(this, values);\n };\n\n return Clip;\n })();\n\n exports.addModule('model.clip', new Clip());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var Live;\n\n Live = (function() {\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var constants = exports.constants;\n\n var bean = exports.loadModule('model.bean');\n\n function Live() {\n this.init();\n }\n\n Live.prototype.init = function() {\n this.id = null;\n this.linkId = null;\n this.channelId = null;\n this.liveId = null;\n this.userId = null;\n this.videoUrl = null;\n this.status = null;\n this.profile = null;\n this.type = constants.VIDEO_TYPE.LIVE;\n this.coverUrl = null;\n this.xylophoneReq = null;\n this.prerollReq = null;\n this.midrollReq = [];\n this.postrollReq = null;\n this.vmapReq = null;\n this.tracking = {\n pvt: null,\n pct: null\n };\n this.title = null;\n this.contentType = '';\n this.liveType = null;\n this.canScrap = null;\n this.shouldGeoBlock = null;\n this.hasPlusFriend = null;\n this.isOpen = null;\n this.isOriginal = null;\n this.description = null;\n this.ageLimit = null;\n this.needPassword = null;\n this.ccuCount = null;\n this.tid = null;\n this.playingInfo = null;\n this.login = null;\n this.owner = null;\n this.channelName = null;\n this.profileImageUrl = null;\n this.skipOnErrorOfAdApi = false;\n this.skipOnErrorOfAdContents = false;\n this.coverThumbnailUrl = null;\n this.outputList = [];\n this.metaUrl = null;\n this.kakaoLink = null;\n this.rating = null;\n this.password = null;\n this.needPassword = null;\n this.autoplayPreroll = null;\n this.shouldShowHDLabel = null;\n this.isDrm = null;\n this.playCount = null;\n };\n\n Live.prototype.set = function(values) {\n debug.log('%c%s', 'color: #EF1414', '[Set] Live', values);\n\n bean.set.call(this, values);\n };\n\n return Live;\n })();\n\n exports.addModule('model.live', new Live());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var Ad;\n\n Ad = (function() {\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var constants = exports.constants;\n\n var bean = exports.loadModule('model.bean');\n\n function Ad() {\n this.id = null;\n this.videoUrl = null;\n this.type = null;\n this.breakId = null;\n this.breakType = null;\n this.timeOffset = null;\n this.skipOffset = null;\n this.ad = null;\n this.creative = null;\n this.extension = null;\n this.clickThrough = null;\n this.clickTracking = null;\n this.dsp = 'etc';\n this.adIndexLabel = null;\n this.icon = null;\n }\n\n Ad.prototype.init = function() {\n this.id = null;\n this.videoUrl = null;\n this.type = constants.VIDEO_TYPE.AD;\n this.breakId = null;\n this.breakType = null;\n this.timeOffset = null;\n this.skipOffset = null;\n this.ad = null;\n this.creative = null;\n this.extension = null;\n this.clickThrough = null;\n this.clickTracking = null;\n this.dsp = 'etc';\n this.adIndexLabel = null;\n this.icon = [];\n };\n\n Ad.prototype.set = function(values) {\n debug.log('%c%s', 'color: #EF1414', '[Set] Ad', values);\n\n bean.set.call(this, values);\n };\n\n return Ad;\n })();\n\n exports.addModule('model.ad', new Ad());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var State;\n\n State = (function() {\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var constants = exports.constants;\n\n var ClipBean = exports.loadModule('model.clip');\n var LiveBean = exports.loadModule('model.live');\n\n function State() {\n this.customControlActivated = null;\n this.modalContentActivated = null;\n this.skipAdEnabled = null;\n this.seekEnabled = null;\n this.volumeChanging = null;\n this.seeking = null;\n this.adControlActivated = null;\n this.currentVideo = null;\n this.profile = null;\n this.completionLoaded = null;\n this.allAdsCompleted = null;\n this.pausedBeforeSeek = null;\n this.isSettingMenuOpened = null;\n this.isContextMenuOpened = null;\n this.mutedBeforeSeek = null;\n this.preventTogglePlayPause = null;\n this.ended = null;\n this.isCheckNextVideo = null;\n this.autoplay = null;\n this.hasRelated = null;\n this.continuousPlay = null;\n this.isPrerollEnded = null;\n this.isPostrollEnded = null;\n this.isNonLinearAdShown = null;\n this.hasStillVideo = null;\n this.playbackRate = null;\n this.needSetTrack = null;\n this.autoplayFail = null;\n this.abr = null;\n this.abrError = null;\n this.playerClass = null;\n this.isShowError = null;\n this.isFirstPlay = null;\n this.midrollIndex = null;\n this.needMidrollRequest = null;\n this.isVastRequesting = false;\n this.lockAirplayChangeEvent = null;\n this.hasAction = null;\n this.initialState = null;\n this.onIma = null;\n this.hls = null;\n this.drm = false;\n }\n\n State.prototype.init = function() {\n this.customControlActivated = false;\n this.modalContentActivated = false;\n this.skipAdEnabled = false;\n this.seekEnabled = true;\n this.volumeChanging = false;\n this.seeking = false;\n this.adControlActivated = false;\n this.currentVideo = null;\n this.profile = 'MAIN';\n this.completionLoaded = false;\n this.allAdsCompleted = false;\n this.pausedBeforeSeek = false;\n this.isSettingMenuOpened = false;\n this.isContextMenuOpened = false;\n this.mutedBeforeSeek = false;\n this.preventTogglePlayPause = false;\n this.ended = false;\n this.isCheckNextVideo = false;\n this.autoplay = false;\n this.hasRelated = false;\n this.continuousPlay = false;\n this.isPrerollEnded = false;\n this.isPostrollEnded = false;\n this.isNonLinearAdShown = false;\n this.hasStillVideo = false;\n this.playbackRate = 1;\n this.needSetTrack = false;\n this.autoplayFail = false;\n this.abr = false;\n this.abrError = false;\n this.playerClass = null;\n this.isShowError = false;\n this.isFirstPlay = true;\n this.midrollIndex = null;\n this.needMidrollRequest = false;\n this.isVastRequesting = false;\n this.lockAirplayChangeEvent = false;\n this.hasAction = false;\n this.onIma = false;\n this.hls = false;\n this.drm = false;\n\n debug.info('[state] initialized');\n };\n\n State.prototype.initInitialState = function() {\n this.initialState = this.initialState ? this.initialState : {};\n this.initialState.start = '0';\n this.initialState.startMuted = !!this.initialState.startMuted;\n\n debug.info('[state] initialState initialized');\n };\n\n State.prototype.initCurrentVideo = function(id, type) {\n var currentVideo = {};\n var VIDEO_TYPE = constants.VIDEO_TYPE;\n\n if (type === VIDEO_TYPE.VOD) {\n ClipBean.init();\n currentVideo = ClipBean;\n } else if (type === VIDEO_TYPE.LIVE) {\n LiveBean.init();\n currentVideo = LiveBean;\n }\n\n currentVideo.set({ id: id });\n this.currentVideo = currentVideo;\n };\n\n return State;\n })();\n\n exports.addModule('controller.state', new State());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n function Html5Player() {\n this.videoElement = null;\n }\n\n Html5Player.prototype = (function() {\n return {\n init: function(player) {\n this.el = this.videoElement = player.videoElement;\n this.name = 'html5player';\n this.type = player.type;\n },\n load: function() {\n this.el.load();\n exports.queue.emit('load:videosource');\n },\n play: function() {\n if (this.el.paused || this.el.ended) {\n return this.el.play();\n }\n },\n pause: function() {\n if (!this.el.paused) {\n this.el.pause();\n }\n },\n stop: function() {\n this.pause();\n this.reset();\n this.load();\n },\n reset: function() {\n this.el.removeAttribute('src');\n this.el.setAttribute('aria-hidden', 'true');\n },\n setVolume: function(volume) {\n this.videoElement.volume = volume;\n },\n getVolume: function() {\n return this.videoElement.volume;\n },\n setMute: function(muted) {\n this.videoElement.muted = muted;\n },\n getMute: function() {\n return this.videoElement.muted;\n },\n setTime: function(time) {\n this.el.setAttribute('data-current-time', time);\n },\n seekTo: function(time) {\n if (!isNaN(time)) {\n this.el.currentTime = time;\n }\n },\n setVideoSource: function(url) {\n if (this.el.src === url) {\n return;\n }\n this.el.src = url;\n\n exports.queue.emit('set:videosource');\n },\n setPlaybackRate: function(rate, calcMode) {\n if (rate && !isNaN(rate) && !calcMode) {\n this.el.playbackRate = rate;\n } else {\n if ((rate < 0 && this.el.playbackRate > 0.25) || (rate > 0 && this.el.playbackRate < 2)) {\n this.el.playbackRate += rate;\n }\n }\n return this.el.playbackRate;\n },\n getPlaybackRate: function() {\n return this.el.playbackRate;\n },\n getDurationRound: function() {\n return Math.round(this.el.duration);\n },\n getCurrentTimeRound: function() {\n return Math.round(this.el.currentTime);\n },\n getCurrentTime: function() {\n return this.el.currentTime;\n },\n isPaused: function() {\n return this.el.paused;\n },\n isReady: function() {\n return this.el.readyState > 2;\n },\n setCredential: function() {\n this.el.crossorigin = 'use-credentials';\n },\n setTextTrack: function(subtitle) {\n var trackList = this.el.textTracks;\n\n for (var i = 0; i < trackList.length; i++) {\n if (trackList[i].language === subtitle) {\n trackList[i].mode = 'showing';\n } else {\n trackList[i].mode = 'hidden';\n }\n }\n },\n getTextTracks: function() {\n var textTracks = [];\n var trackList = this.el.textTracks;\n\n for (var i = 0; i < trackList.length; i++) {\n textTracks.push({ language: trackList[i].language });\n }\n\n return textTracks;\n }\n };\n })();\n\n exports.addModule('player.html5', new Html5Player());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports, dt) {\n 'use strict';\n var state = exports.loadModule('controller.state');\n var queue = exports.loadModule('playlist.queue');\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var ua = exports.ua;\n var env = exports.ENV;\n var shakaEvents = [\n 'adaptation',\n 'buffering',\n 'drmsessionupdate',\n 'emsg',\n 'expirationupdated',\n 'largegap',\n 'loading',\n 'streaming',\n 'texttrackvisibility',\n 'timelineregionadded',\n 'timelineregionenter',\n 'timelineregionexit',\n 'trackschanged',\n 'unloading'\n ];\n var bandwidthQueue = [];\n var ABR_KEY = constants.STORAGE.ABR;\n var PROFILE_KEY = constants.STORAGE.PROFILE;\n var MAIN_PROFILE_INDEX = 2;\n\n function ShakaPlayer() {\n this.player = null;\n this.castProxy = null;\n this.tracks = null;\n this.outputList = null;\n this.videoElement = null;\n this.key = '';\n this.preDropFrames = 0;\n this.prevProfile = '';\n this.originPlayer = null;\n this.drmData = {\n token: null,\n type: null,\n server: null,\n cert: null,\n certUrl: null\n };\n }\n\n ShakaPlayer.prototype = (function() {\n function onShakaEvent(event) {\n debug.info('%c%s', 'color: #20b408', '[ShakaPlayer] onShakaEvent type = ' + event.type, event);\n switch (event.type) {\n case 'adaptation':\n exports.queue.emit('change:stream');\n break;\n case 'buffering':\n exports.queue.emit('shaka:buffering', event.buffering);\n break;\n case 'drmsessionupdate':\n break;\n case 'emsg':\n break;\n case 'expirationupdated':\n break;\n case 'largegap':\n break;\n case 'loading':\n break;\n case 'streaming':\n break;\n case 'texttrackvisibility':\n break;\n case 'timelineregionadded':\n break;\n case 'timelineregionexit':\n break;\n case 'trackschanged':\n break;\n case 'unloading':\n break;\n default:\n break;\n }\n }\n\n function changePlayerForFailover() {\n var currentVideo = state.currentVideo;\n var profile = currentVideo.originProfile || currentVideo.profile || constants.PROFILE.BASE;\n state.abr = false;\n state.hls = false;\n state.abrError = true;\n\n if (state.isFirstPlay) {\n exports.queue.emit('set:defaultOptions');\n }\n\n exports.queue.emit('loadAndPlay:videoById', currentVideo.id, profile, 0, null, Object.assign({}, state));\n exports.queue.emit('shaka:error');\n }\n\n function onErrorEvent(event) {\n var video = (queue && queue.front) || state.currentVideo;\n var shakaError = constants.SHAKA.ERROR;\n\n switch (event.code || (event.detail && event.detail.code)) {\n case shakaError.HTTP_ERROR.CODE:\n debug.error('%c%s', 'color: #20b408', '[ShakaPlayer] HTTP_ERROR', event);\n break;\n case shakaError.MEDIA_FORMAT_ERROR.CODE:\n debug.error('%c%s', 'color: #20b408', '[ShakaPlayer] MEDIA_FORMAT_ERROR', event);\n break;\n case shakaError.FAILED_TO_GENERATE_LICENSE_REQUEST.CODE:\n debug.error('%c%s', 'color: #20b408', '[ShakaPlayer] FAILED_TO_GENERATE_LICENSE_REQUEST', event);\n break;\n case shakaError.BAD_HTTP_STATUS.CODE:\n changePlayerForFailover();\n break;\n default:\n debug.error('%c%s', 'color: #20b408', '[ShakaPlayer] onError ', event);\n if (!state.autoplayFail && video && video.type !== 'AD') {\n changePlayerForFailover();\n } else {\n if (dt.StopWatch.has('startPlay')) {\n dt.StopWatch.stop('startPlay');\n }\n\n if (dt.StopWatch.has('rebuffering')) {\n dt.StopWatch.stop('rebuffering');\n }\n }\n break;\n }\n }\n\n function getDrmCert(drmData) {\n return new Promise(function(resolve, reject) {\n helpers.http.ajax(\n drmData.certUrl,\n {\n onSuccess: function(data) {\n drmData.cert = new Uint8Array(data);\n resolve();\n },\n onError: function(e) {\n debug.error('get drm cert error ', e);\n reject();\n }\n },\n {\n async: true,\n timeout: 5000,\n responseType: 'arraybuffer'\n }\n );\n });\n }\n\n return {\n init: function(player) {\n window.shaka.polyfill.installAll();\n if (player.type === 'LIVE' || !this.isBrowserSupported()) {\n return;\n }\n\n if (!this.videoElement) {\n this.videoElement = player.videoElement;\n }\n },\n initPlayer: function() {\n var self = this;\n\n if (\n ua.os.android &&\n !helpers.device.isAllowContentAcessTalkWebView() &&\n helpers.device.isTalkWebView(ua) &&\n state.currentVideo.isDrm &&\n env.feedType\n ) {\n debug.warn('current browser is is not support autoplay for drm content');\n return;\n }\n\n if (!this.player || (this.player.getMediaElement && !this.player.getMediaElement())) {\n this.player = new window.shaka.Player(this.videoElement);\n this.castProxy = new window.shaka.cast.CastProxy(this.videoElement, this.player, 'app ID');\n\n this.player.configure(\n ua.platform === 'pc' ? constants.SHAKA.CONFIGURE.PC : constants.SHAKA.CONFIGURE.MOBILE\n );\n this.player.addEventListener('error', onErrorEvent);\n shakaEvents.forEach(function(v) {\n self.player.addEventListener(v, onShakaEvent);\n });\n\n exports.shakaPlayer = this.player;\n exports.shakaPlayer.castProxy = this.castProxy;\n }\n },\n isBrowserSupported: function() {\n return window.shaka.Player.isBrowserSupported();\n },\n setManifestUri: function(url) {\n if (this.src === url) {\n return;\n }\n\n var subPoint = url.indexOf('?') !== -1 ? url.indexOf('?') : url.length;\n var urlPath = url.substring(0, subPoint);\n var queryString = url.substring(subPoint + 1).replace(/\\?/g, '&');\n\n this.src = urlPath;\n if (queryString) {\n this.key = '?' + queryString;\n this.src += '?' + queryString;\n }\n },\n registerRequestFilter: function() {\n var self = this;\n this.player.getNetworkingEngine().registerRequestFilter(function(type, request) {\n if (type === window.shaka.net.NetworkingEngine.RequestType.LICENSE) {\n var bytes = new Uint8Array(request.body);\n var payload = helpers.encoder.base64EncodeUint8Array(bytes);\n var body = 'token=' + self.drmData.token + '&provider=kakaotv&payload=' + payload;\n request.body = body;\n request.headers = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n };\n } else {\n if (!self.key) {\n request.allowCrossSiteCredentials = true;\n }\n\n if (type === window.shaka.net.NetworkingEngine.RequestType.SEGMENT) {\n if (request && request.uris && self.key) {\n request.uris.forEach(function(v, i) {\n if (request.uris[i].indexOf('?') === -1) {\n request.uris[i] += self.key;\n }\n\n if (request.headers.Range) {\n var range = request.headers.Range;\n var bytes = '';\n if (range.indexOf('bytes=') !== -1) {\n bytes = range.substring(range.indexOf('=') + 1, range.length);\n request.uris[i] += '&range=' + bytes;\n delete request.headers['Range'];\n }\n }\n });\n }\n }\n }\n });\n },\n registerResponseFilter: function() {\n var self = this;\n this.player.getNetworkingEngine().registerResponseFilter(function(type, response) {\n if (type === window.shaka.net.NetworkingEngine.RequestType.LICENSE) {\n var responseString = window.shaka.util.StringUtils.fromUTF8(response.data);\n var responseJson = JSON.parse(responseString);\n var resultCode = responseJson.result_code;\n if (resultCode === 'OK') {\n if (self.drmData.type === 'playready') {\n response.data = window.shaka.util.StringUtils.toUTF8(responseJson.payload);\n } else {\n response.data = window.shaka.util.Uint8ArrayUtils.fromBase64(\n responseJson.payload\n ).buffer;\n }\n }\n } else if (!response.fromCache && type === window.shaka.net.NetworkingEngine.RequestType.SEGMENT) {\n var bandwidth = (response.data.byteLength * 8000) / response.timeMs;\n bandwidthQueue.push(bandwidth);\n }\n });\n },\n load: function(callback) {\n var storeABR = helpers.store.get(ABR_KEY);\n var storeProfile = helpers.store.get(PROFILE_KEY);\n var self = this;\n\n if (!this.player) {\n this.initPlayer();\n }\n\n this.unload();\n this.registerRequestFilter();\n this.registerResponseFilter();\n\n if (storeABR === 'false' && ua.platform !== 'pc') {\n var dashProfileList = constants.DASH_PROFILE;\n var outputList = this.outputList\n ? this.outputList.reduce(function(ob, output) {\n ob[output.profile] = dashProfileList[output.profile];\n return ob;\n }, {})\n : {};\n\n for (var p in dashProfileList) {\n if (\n dashProfileList.hasOwnProperty(p) &&\n storeProfile === dashProfileList[p] &&\n storeProfile === outputList[p]\n ) {\n state.currentVideo.profile = p;\n break;\n }\n }\n\n state.needSetTrack = true;\n }\n\n if (this.drmData.token) {\n if (helpers.device.getDteType(ua) === constants.DTE_TYPE.ANDROID) {\n this.setTrack(MAIN_PROFILE_INDEX);\n state.currentVideo.profile = MAIN_PROFILE_INDEX;\n }\n this.setDrmConfig().then(function() {\n self.player\n .load(self.src)\n .then(function() {\n callback();\n })\n .catch(onErrorEvent);\n });\n } else {\n this.player\n .load(this.src)\n .then(function() {\n callback();\n })\n .catch(onErrorEvent);\n }\n },\n unload: function() {\n try {\n this.player.unload(true);\n this.player.getNetworkingEngine().clearAllRequestFilters();\n this.player.getNetworkingEngine().clearAllResponseFilters();\n } catch (e) {\n debug.error('shaka:unload ', e);\n }\n },\n setTrack: function(index) {\n var config = {\n restrictions: {\n maxPixels: constants.ABR_RESTRICTION_PROFILE[constants.DASH_PROFILE[index]]\n }\n };\n this.player.configure(config);\n },\n setDrmConfig: function() {\n var self = this;\n return new Promise(function(resolve) {\n if (self.drmData.type === constants.DRM.TYPE.FAIRPLAY) {\n getDrmCert(self.drmData).then(function() {\n self.player.configure('drm', {\n servers: {\n 'com.apple.fps.1_0': self.drmData.server\n },\n advanced: {\n 'com.apple.fps.1_0': {\n serverCertificate: self.drmData.cert\n }\n },\n initDataTransform: function(initData) {\n var skdUri = window.shaka.util.StringUtils.fromBytesAutoDetect(initData);\n var contentId = skdUri.substring(skdUri.indexOf('skd://') + 6);\n var cert = self.player.drmInfo().serverCertificate;\n return window.shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);\n }\n });\n resolve();\n });\n } else if (self.drmData.type === constants.DRM.TYPE.PLAYREADY) {\n self.player.configure('drm', {\n servers: {\n 'com.microsoft.playready': self.drmData.server\n }\n });\n resolve();\n } else {\n self.player.configure('drm', {\n servers: {\n 'com.widevine.alpha': self.drmData.server\n }\n });\n resolve();\n }\n });\n },\n setConfig: function(config) {\n this.player.configure(config);\n },\n setPrevProfile: function(currentProfile) {\n this.prevProfile = currentProfile;\n },\n parseTracks: function(variantTrack) {\n var selectedAudio = null;\n var availableAudioList = ['AUDIO', '128-44100', '96-48000', '96-44100', '96-22050', null];\n var validTrack = [];\n var outputs = [];\n var profileIndex = 0;\n var self = this;\n\n variantTrack.sort(function(a, b) {\n return a.bandwidth > b.bandwidth ? 1 : a.bandwidth < b.bandwidth ? -1 : 0;\n });\n\n outputs.push({ profile: constants.PROFILE.AUTO, label: '자동' });\n\n variantTrack.forEach(function(v) {\n if (\n (availableAudioList.indexOf(v.originalAudioId) !== -1 && selectedAudio === null) ||\n selectedAudio === v.audioId ||\n v.originalId\n ) {\n if (selectedAudio === null && !v.originalId) {\n selectedAudio = v.audioId;\n }\n\n var videoId = (v.originalVideoId || v.originalId).split('_').pop();\n var profileResolution = constants.PROFILE_RESOULTION[videoId];\n var label = profileResolution || videoId;\n\n var isAlreadyExists = outputs.filter(function(output) {\n return output.label === label;\n });\n var resolution = v.width * v.height;\n\n if (\n self.drmData.token &&\n helpers.device.getDteType(ua) === constants.DTE_TYPE.ANDROID &&\n resolution > constants.ABR_RESTRICTION_PROFILE[constants.PROFILE.MAIN]\n ) {\n return;\n }\n\n if (isAlreadyExists.length === 0) {\n validTrack.push(v);\n outputs.push({\n profile: profileIndex,\n label: label\n });\n profileIndex++;\n }\n }\n });\n\n this.outputList = outputs;\n this.tracks = validTrack;\n },\n getOutputs: function(cb) {\n var self = this;\n var callback = cb;\n var restrictionProfile =\n this.drmData.token && helpers.device.getDteType(ua) === constants.DTE_TYPE.ANDROID\n ? constants.PROFILE.MAIN\n : constants.PROFILE.HIGH4;\n\n if (!this.player) {\n this.initPlayer();\n }\n\n this.player.configure({\n restrictions: {\n maxPixels: constants.ABR_RESTRICTION_PROFILE[restrictionProfile]\n }\n });\n\n var variantTrack = this.player.getVariantTracks();\n this.parseTracks(variantTrack);\n\n if (this.tracks.length === 0) {\n var parser = new window.shaka.dash.DashParser();\n\n parser.configure({\n retryParameters: null,\n dash: {}\n });\n\n this.player.getNetworkingEngine().clearAllRequestFilters();\n this.registerRequestFilter();\n\n var playerInterface = {\n networkingEngine: this.player.getNetworkingEngine(),\n filterAllPeriods: function() {},\n filter: function() {},\n makeTextStreamsForClosedCaptions: function() {},\n onError: onErrorEvent\n };\n\n parser\n .start(this.src, playerInterface)\n .then(function(e) {\n var variants = e.variants;\n var tracks = [];\n\n for (var i = 0; i < variants.length; i++) {\n tracks.push(variants[i].video);\n }\n\n self.parseTracks(tracks);\n callback(self.outputList);\n })\n .catch(function(e) {\n debug.warn('shaka:getOutputs e.message = ', e.message);\n });\n } else {\n callback(this.outputList);\n }\n },\n getCurrentProfile: function() {\n var profile = '';\n var currentHeight = 0;\n\n if (this.player && this.tracks !== null) {\n var stats = this.getStats();\n currentHeight = stats && stats.height;\n\n this.tracks.forEach(function(v) {\n var videoId = (v.originalVideoId || v.originalId).split('_').pop();\n if (v.height === currentHeight) {\n profile = constants.PROFILE_RESOULTION[videoId]\n ? constants.PROFILE_RESOULTION[videoId]\n : videoId || '';\n }\n });\n }\n\n return profile;\n },\n getDropFrames: function() {\n var stats;\n var dropFrames = 0;\n\n if (!this.player) {\n return false;\n }\n\n stats = this.getStats();\n if (stats && stats.droppedFrames) {\n dropFrames = stats.droppedFrames - this.preDropFrames;\n this.preDropFrames = stats.droppedFrames;\n }\n\n return dropFrames;\n },\n getBandwidth: function() {\n var avgBandwidth = 0;\n\n if (!this.player) {\n return false;\n }\n\n if (bandwidthQueue.length > 0) {\n avgBandwidth =\n bandwidthQueue.reduce(function(a, b) {\n return a + b;\n }) / bandwidthQueue.length;\n }\n\n bandwidthQueue = [];\n var stats = this.getStats();\n var ewmaBandwidth = stats && stats.estimatedBandwidth && stats.estimatedBandwidth.toFixed(0) / 1000;\n if (!isNaN(ewmaBandwidth)) {\n debug.tooltip('[shaka] EWMA Bandwidth = ', ewmaBandwidth.toFixed(0) + 'Kbps');\n }\n\n return parseInt(avgBandwidth.toFixed(0), 10);\n },\n getStats: function() {\n var stats = {};\n\n try {\n stats = this.player.getStats();\n } catch (e) {\n debug.log('[shaka error] getStats ', e);\n }\n\n return stats;\n },\n getPrevProfile: function() {\n return this.prevProfile;\n },\n setTextTrack: function(subtitle) {\n this.player.setTextTrackVisibility(false);\n\n if (subtitle !== constants.SUBTITLE.STATUS.OFF) {\n var selectTrack = null;\n this.player.getTextTracks().forEach(function(v) {\n if (v.language === subtitle) {\n selectTrack = v;\n }\n });\n\n if (selectTrack !== null) {\n this.player.selectTextTrack(selectTrack);\n this.player.setTextTrackVisibility(true);\n }\n }\n },\n getTextTracks: function() {\n var textTracks = [];\n this.player.getTextTracks().forEach(function(v) {\n textTracks.push({ language: v.language });\n });\n\n return textTracks;\n },\n detach: function() {\n this.unload();\n return this.player.detach();\n },\n attach: function(videoElement) {\n return this.player.attach(videoElement);\n },\n reset: function(videoElement) {\n var shaka = this;\n\n if (!this.player) {\n return;\n }\n\n shaka.detach().then(function() {\n shaka.attach(videoElement);\n });\n },\n setDrmData: function(drmData) {\n this.drmData.token = drmData.token;\n this.drmData.server = drmData.server;\n this.drmData.type = drmData.type;\n },\n setDrmCertUrl: function(certUrl) {\n this.drmData.certUrl = certUrl;\n }\n };\n })();\n\n exports.addModule('player.shaka', new ShakaPlayer());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports) {\n 'use strict';\n\n var constants = exports.constants;\n var helpers = exports.helpers;\n var ua = exports.ua;\n var debug = helpers.debug;\n var ERROR_STATUS = constants.ERROR.STATUS;\n var state = exports.loadModule('controller.state');\n var isInstalledExtension = null;\n var isInstalledLiveAgent = null;\n\n function KampPlayer() {\n this.player = null;\n this.videoElement = null;\n this.videoUrl = null;\n }\n\n KampPlayer.prototype = (function() {\n function onNeedInstall() {\n if (state.currentVideo.contentType === constants.CONTENT_TYPE.NPP) {\n debug.info('Live Agent 실행 또는 설치가 필요합니다.');\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.LiveAgentNotInstalled.NAME,\n profile: constants.PROFILE.HIGH\n }\n });\n }\n }\n\n function onInstalled() {\n debug.info('Live Agent 설치되어, 실행 중 입니다.');\n }\n\n function onConnectedAgent() {\n debug.info('Live Agent와 연결이 되었습니다.');\n }\n\n function onDisconnectedAgent() {\n debug.info('Live Agent와 연결이 끊겼습니다.');\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.NETWORK_OFFLINE.NAME\n }\n });\n helpers.sentry.captureMessage('Live Agent와 연결이 끊겼습니다.');\n }\n\n function checkInstalled() {\n try {\n if (window.kamp) {\n window.kamp.util.checkLiveAgent(function(isInstalledExt, isInstalledAgent) {\n isInstalledExtension = isInstalledExt;\n isInstalledLiveAgent = isInstalledAgent;\n });\n } else {\n isInstalledLiveAgent = false;\n }\n } catch (e) {\n isInstalledLiveAgent = false;\n }\n }\n\n function checkForAgentInstallation(profile) {\n if (window.kamp) {\n window.kamp.util.checkForAgentInstallation(function(err) {\n if (err) {\n debug.info('Live Agent 설치가 되지 않았습니다.');\n return;\n }\n isInstalledLiveAgent = true;\n exports.queue.emit('live:getLocation', profile);\n exports.queue.emit('hide:error');\n debug.info('Live Agent 설치가 완료 되었습니다.');\n });\n }\n }\n\n function checkForExtInstallation(profile) {\n if (window.kamp) {\n window.kamp.util.checkForExtInstallation(function(err) {\n if (err) {\n debug.info('Chrome Extension 설치가 되지 않았습니다.');\n return;\n }\n isInstalledExtension = true;\n exports.queue.emit('live:updateSetupView', profile);\n checkForAgentInstallation(profile);\n debug.info('Chrome Extension 설치가 완료 되었습니다.');\n });\n }\n }\n\n function onClosed() {\n exports.queue.emit('reset:playList');\n exports.queue.emit('onClosed:videoEvent');\n }\n\n function onForbbidenError() {\n var errorCode = ERROR_STATUS.UNAVAILABLE.NAME;\n var doNotTrack = window.navigator.doNotTrack || window.doNotTrack || window.navigator.msDoNotTrack;\n if (!window.navigator.cookieEnabled || doNotTrack || ua.browser.msie) {\n errorCode = ERROR_STATUS.UNAVAILABLE_COOKIE.NAME;\n }\n exports.queue.emit('show:error', {\n info: {\n code: errorCode\n }\n });\n }\n\n function onPlayerReset() {\n debug.info('Reset kamp player!');\n }\n\n function bindEvent(player) {\n player.on('abort', function() {\n exports.queue.emit('video:abort');\n });\n player.on('canplay', function() {\n exports.queue.emit('video:canplay');\n });\n player.on('durationchange', function() {\n exports.queue.emit('video:durationchange');\n });\n player.on('emptied', function() {\n exports.queue.emit('video:emptied');\n });\n player.on('ended', function() {\n exports.queue.emit('video:ended');\n });\n player.on('error', function() {\n exports.queue.emit('video:error');\n });\n player.on('loadeddata', function() {\n exports.queue.emit('video:loadeddata');\n });\n player.on('loadedmetadata', function() {\n exports.queue.emit('video:loadedmetadata');\n });\n player.on('loadstart', function() {\n exports.queue.emit('video:loadstart');\n });\n player.on('pause', function() {\n exports.queue.emit('video:pause');\n });\n player.on('play', function() {\n exports.queue.emit('video:play');\n });\n player.on('playing', function() {\n exports.queue.emit('video:playing');\n });\n player.on('progress', function() {\n exports.queue.emit('video:progress');\n });\n player.on('seeking', function() {\n exports.queue.emit('video:seeking');\n });\n player.on('seeked', function() {\n exports.queue.emit('video:seeked');\n });\n player.on('suspend', function() {\n exports.queue.emit('video:suspend');\n });\n player.on('timeupdate', function() {\n exports.queue.emit('video:timeupdate');\n });\n player.on('volumechange', function() {\n exports.queue.emit('video:volumechange');\n });\n player.on('waiting', function() {\n exports.queue.emit('video:waiting');\n });\n\n player.on('onconnected', onConnectedAgent);\n player.on('ondisconnected', onDisconnectedAgent);\n player.on('closed', onClosed);\n player.on('forbbiden', onForbbidenError);\n player.on('playerreset', onPlayerReset);\n player.on('ready', function() {\n // exports.queue.emit('addlistener:videoEvent', player.$('video'));\n });\n player.tech().on('needInstallLiveAgent', onNeedInstall);\n player.tech().on('installedLiveAgent', onInstalled);\n }\n\n return {\n load: function(videoUrl) {\n if (videoUrl) {\n this.videoUrl = videoUrl;\n }\n\n var mediaType = constants.MEDIA_TYPE[state.currentVideo.contentType];\n var sourceDatas = {\n src: this.videoUrl,\n type: mediaType,\n withCredentials: true\n };\n var options = {\n autoplay: true,\n techOrder: ['Kamp'],\n controls: false,\n preload: 'auto',\n children: ['MediaLoader']\n };\n\n if (window.videojs) {\n if (this.player) {\n this.reset();\n } else {\n this.player = window.videojs(this.videoElement, options);\n bindEvent(this.player);\n }\n\n this.videoElement = this.player.$('video');\n this.player.src(sourceDatas);\n this.play();\n\n exports.kampPlayer = this.player;\n }\n },\n init: function(player) {\n this.videoElement = player.videoElement;\n checkInstalled();\n },\n isReady: function() {\n if (this.player) {\n return this.player.isReady_;\n }\n return false;\n },\n reset: function() {\n this.player.tech(1).trigger('stop');\n },\n pause: function() {\n if (!this.player.paused()) {\n this.player.pause();\n }\n },\n play: function() {\n if (this.player.paused() || this.player.ended()) {\n return this.player.play();\n }\n },\n stop: function() {\n this.player.pause();\n },\n isPaused: function() {\n return this.player.paused();\n },\n getVolume: function() {\n return this.player.volume();\n },\n setVolume: function(volume) {\n this.player.volume(volume);\n },\n getMute: function() {\n return this.player.muted();\n },\n setMute: function(muted) {\n this.player.muted(muted);\n },\n getCurrentTimeRound: function() {\n return Math.round(this.player.$('video').currentTime);\n },\n getCurrentTime: function() {\n return this.player.$('video').currentTime;\n },\n isSupportedLiveAgentHLS: function() {\n return window.kamp ? window.kamp.isSupportedLiveAgentHLS() : false;\n },\n isInstalledLiveAgent: function() {\n return isInstalledLiveAgent;\n },\n isInstalledExtension: function() {\n return isInstalledExtension;\n },\n checkForAgentInstallation: function(profile) {\n checkForAgentInstallation(profile);\n },\n checkForExtInstallation: function(profile) {\n checkForExtInstallation(profile);\n }\n };\n })();\n\n exports.addModule('player.kamp', new KampPlayer());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var state = exports.loadModule('controller.state');\n\n function CastPlayer() {\n this.videoElement = null;\n }\n\n CastPlayer.prototype = (function() {\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n var chrome = {};\n var session = {};\n\n function loadCastPlay(videoInfo) {\n chrome = window.chrome;\n\n var bean = state.currentVideo;\n var videoUrl = videoInfo.url;\n var mediaType = videoInfo.mediaType;\n var mediaInfo = new chrome.cast.media.MediaInfo(videoUrl, mediaType);\n\n mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();\n mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC;\n mediaInfo.metadata.title = bean.title;\n mediaInfo.metadata.images = [{ url: bean.coverUrl }];\n\n var request = new chrome.cast.media.LoadRequest(mediaInfo);\n session = window.cast.framework.CastContext.getInstance().getCurrentSession();\n return session.loadMedia(request);\n }\n\n function onErrorEvent(error) {\n var errorCode = chrome.cast.ErrorCode;\n\n switch (error.code) {\n case errorCode.API_NOT_INITIALIZED:\n debug.error('[CastPlayer] API_NOT_INITIALIZED: ' + error.description);\n break;\n case errorCode.SESSION_ERROR:\n debug.error('[CastPlayer] SESSION_ERROR: ' + error.description);\n break;\n default:\n debug.log('[CastPlayer] On Error: ' + error);\n break;\n }\n }\n\n return {\n init: function() {\n this.el = {};\n this.originPlayer = {};\n this.name = 'castPlayer';\n this.player = {};\n this.controller = {};\n this.activate = false;\n },\n setPlayer: function(originPlayer, player, controller) {\n this.el = this.videoElement = originPlayer.videoElement;\n this.originPlayer = originPlayer;\n this.player = player || this.player;\n this.controller = controller || this.controller;\n },\n load: function(videoInfo, start, callback) {\n var player = this;\n this.activate = true;\n\n loadCastPlay(videoInfo)\n .then(function() {\n if (start > 0) {\n player.seekTo(start);\n }\n\n if (callback) {\n callback();\n }\n\n player.play();\n })\n .catch(onErrorEvent);\n },\n play: function() {\n if (this.player.isPaused) {\n this.controller.playOrPause();\n }\n },\n stop: function() {\n this.controller.stop();\n\n if (session.endSession) {\n session.endSession(true);\n }\n },\n pause: function() {\n if (!this.player.isPaused) {\n this.controller.playOrPause();\n }\n },\n setVolume: function(volume) {\n this.player.volumeLevel = parseFloat(volume);\n this.controller.setVolumeLevel();\n },\n getVolume: function() {\n return this.player.volumeLevel;\n },\n setMute: function(muted) {\n if (this.player.isMuted && !muted) {\n this.controller.muteOrUnmute();\n } else if (!this.player.isMuted && muted) {\n this.controller.muteOrUnmute();\n }\n },\n getMute: function() {\n return this.player.isMuted;\n },\n setTime: function(time) {\n this.el.setAttribute('data-current-time', time);\n },\n seekTo: function(time) {\n this.player.currentTime = time;\n this.controller.seek();\n },\n getDurationRound: function() {\n var duration = this.player.duration ? this.player.duration : 1;\n return Math.round(duration);\n },\n getCurrentTimeRound: function() {\n return Math.round(this.getCurrentTime());\n },\n getCurrentTime: function() {\n return this.player.currentTime ? this.player.currentTime : 0;\n },\n getPlayerInstance: function() {\n return this;\n },\n isPaused: function() {\n return this.player.isPaused;\n },\n isReady: function() {\n return this.activate;\n },\n getSession: function() {\n return session;\n }\n };\n })();\n\n exports.addModule('player.cast', new CastPlayer());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n var state = exports.loadModule('controller.state');\n var html5 = exports.loadModule('player.html5');\n var kamp = exports.loadModule('player.kamp');\n var shaka = exports.loadModule('player.shaka');\n var cast = exports.loadModule('player.cast');\n\n function PlayerAdapter() {}\n\n PlayerAdapter.prototype = (function() {\n var constants = exports.constants;\n\n return {\n init: function(player) {\n this.player = html5;\n this.videoElement = player.videoElement;\n this.name = 'player';\n this.type = player.type;\n this.duration = 0;\n },\n load: function(loadDatas) {\n var videoUrl = loadDatas.videoUrl;\n var callback = loadDatas.callback;\n var playerClass = loadDatas.playerClass;\n var remote = loadDatas.remote;\n this.duration = 0;\n\n if (playerClass === constants.PLAYERCLASS.KAMP) {\n kamp.load(videoUrl);\n kamp.setMute(this.getMute());\n kamp.setVolume(this.getVolume());\n this.player = kamp;\n } else if (playerClass === constants.PLAYERCLASS.SHAKA) {\n shaka.load(callback);\n } else if (playerClass === constants.PLAYERCLASS.CAST) {\n cast.setPlayer(this.player, remote.player, remote.controller);\n cast.load(remote.videoInfo, remote.start, callback);\n this.player = cast;\n } else {\n if (videoUrl.indexOf('m3u8') > -1) {\n html5.setCredential();\n state.hls = true;\n }\n html5.setVideoSource(videoUrl);\n html5.load();\n }\n this.videoElement = this.player.videoElement;\n },\n play: function() {\n if (this.player.play) {\n return this.player.play();\n }\n },\n pause: function() {\n if (this.player.pause) {\n this.player.pause();\n }\n },\n stop: function() {\n if (this.player.stop) {\n this.player.stop();\n }\n },\n reset: function() {\n this.player.reset();\n },\n setVolume: function(volume) {\n this.player.setVolume(volume);\n },\n getVolume: function() {\n return this.player.getVolume();\n },\n setMute: function(muted) {\n this.player.setMute(muted);\n },\n getMute: function() {\n if (this.player.getMute) {\n return this.player.getMute();\n }\n },\n setTime: function(time) {\n if (this.player.setTime) {\n this.player.setTime(time);\n }\n },\n seekTo: function(time) {\n if (this.player.seekTo) {\n this.videoElement.setAttribute('data-time-before-seek', this.getCurrentTimeRound());\n this.player.seekTo(time);\n }\n },\n setVideoSource: function(url) {\n if (this.player.setVideoSource) {\n this.player.setVideoSource(url);\n }\n },\n setPlaybackRate: function(rate, calcMode) {\n if (this.player.setPlaybackRate) {\n return this.player.setPlaybackRate(rate, calcMode);\n }\n },\n getPlaybackRate: function() {\n if (this.player.getPlaybackRate) {\n return this.player.getPlaybackRate();\n }\n },\n setDuration: function(duration) {\n this.duration = duration;\n },\n getDurationRound: function() {\n if (this.duration > 0) {\n return this.duration;\n }\n\n if (this.player.getDurationRound) {\n return this.player.getDurationRound();\n }\n },\n getCurrentTimeRound: function() {\n if (this.player.getCurrentTimeRound) {\n return this.player.getCurrentTimeRound();\n }\n },\n getCurrentTime: function() {\n if (this.player.getCurrentTime) {\n return this.player.getCurrentTime();\n }\n },\n getPlayerInstance: function() {\n if (this.player.getPlayerInstance) {\n return this.player.getPlayerInstance();\n }\n },\n getOriginPlayer: function() {\n if (this.player.originPlayer) {\n return this.player.originPlayer;\n }\n },\n isPaused: function() {\n if (this.player.isPaused) {\n return this.player.isPaused();\n }\n },\n isReady: function() {\n if (this.player.isReady) {\n return this.player.isReady();\n }\n },\n isSupportedLiveAgentHLS: function() {\n return kamp.isSupportedLiveAgentHLS();\n },\n isInstalledLiveAgent: function() {\n return kamp.isInstalledLiveAgent();\n },\n isInstalledExtension: function() {\n return kamp.isInstalledExtension();\n },\n checkForAgentInstallation: function(profile) {\n kamp.checkForAgentInstallation(profile);\n },\n checkForExtInstallation: function(profile) {\n kamp.checkForExtInstallation(profile);\n },\n setTextTrack: function(subtitle) {\n if (state.abr) {\n shaka.setTextTrack(subtitle);\n } else {\n if (this.player.setTextTrack) {\n this.player.setTextTrack(subtitle);\n }\n }\n },\n getTextTracks: function() {\n var textTracks = [];\n if (state.abr) {\n textTracks = shaka.getTextTracks();\n } else {\n if (this.player.getTextTracks) {\n textTracks = this.player.getTextTracks();\n }\n }\n return textTracks;\n },\n getBeforeSeekedTime: function() {\n return this.videoElement.getAttribute('data-time-before-seek');\n }\n };\n })();\n\n exports.addModule('player.adapter', new PlayerAdapter());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var A11y;\n\n A11y = (function() {\n function A11Y() {}\n\n A11Y.prototype.init = function() {};\n\n A11Y.prototype.setAria = function(target, attr, value) {\n target.setAttribute('aria-' + attr, value);\n };\n\n A11Y.prototype.removeAria = function(target, attr) {\n target.removeAttribute('aria-' + attr);\n };\n\n A11Y.prototype.onTabIndex = function(target) {\n target.setAttribute('tabindex', '0');\n };\n\n A11Y.prototype.offTabIndex = function(target) {\n target.setAttribute('tabindex', '-1');\n };\n\n A11Y.prototype.removeTabIndex = function(target) {\n target.removeAttribute('tabindex');\n };\n\n return A11Y;\n })();\n exports.addModule('etc.a11y', new A11y());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var state = exports.loadModule('controller.state');\n var PCTTracker;\n\n PCTTracker = (function() {\n var helpers = exports.helpers;\n var constants = exports.constants;\n var debug = helpers.debug;\n\n function track(url) {\n helpers.http.sendBeacon(url);\n }\n\n function PCTTracker() {}\n\n function setExternalData(data) {\n data.protocol = state.abr ? constants.CONTENT_TYPE.DASH : constants.CONTENT_TYPE.MP4;\n return data;\n }\n\n PCTTracker.prototype.init = function() {\n debug.log('[pct:tracker] initialized');\n };\n\n PCTTracker.prototype.create = function(pct) {\n this.url = pct.url;\n };\n\n PCTTracker.prototype.track = function(literal1, literal2, literal3) {\n // todo literal이 추가로 설정될 여지가 있으므로 리팩토링 필요\n var defaults = {\n literal1: literal1 || '',\n literal2: literal2 || '',\n literal3: literal3 || ''\n };\n\n defaults = setExternalData(defaults);\n\n if (typeof this.url !== 'undefined') {\n this.trackURLs(this.url, defaults);\n\n debug.info('[pct:tracker] click event params', defaults);\n }\n };\n\n PCTTracker.prototype.trackURLs = function(url, variables) {\n var queryString = helpers.string.jsonToQueryString(variables);\n var trackUrl = url + '&' + queryString;\n\n return track(trackUrl);\n };\n\n return PCTTracker;\n })();\n\n exports.addModule('pct.tracker', new PCTTracker());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports, dt) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n var state = exports.loadModule('controller.state');\n\n var PVTTracker = (function() {\n var helpers = exports.helpers;\n var constants = exports.constants;\n var debug = helpers.debug;\n var connection = helpers.webapi.network.getConnection();\n\n var intervalTimer = null;\n var passedByTimer = {};\n\n function track(trackingURL) {\n var results = [];\n var url;\n var externalData = {};\n\n if (!Array.isArray(trackingURL)) {\n externalData = setExternalData(externalData);\n url = trackingURL.shift();\n url += '&' + helpers.string.jsonToQueryString(externalData);\n helpers.http.sendBeacon(url);\n return trackingURL;\n } else {\n while (trackingURL.length > 0) {\n if (typeof window !== 'undefined' && window !== null) {\n externalData = setExternalData(externalData);\n url = trackingURL.shift();\n url += '&' + helpers.string.jsonToQueryString(externalData);\n results.push(helpers.http.sendBeacon(url));\n }\n }\n return results;\n }\n }\n\n function trackPassedByTime(_url, eventName, delay) {\n if (passedByTimer[delay]) {\n return;\n }\n\n passedByTimer[delay] = new dt.Timer(function() {\n debug.log('%c%s', 'color: #795548;', '[pvt:tracker]', eventName, _url);\n\n if (passedByTimer[delay]) {\n passedByTimer[delay].clear();\n passedByTimer[delay] = null;\n }\n track(_url);\n }, delay * 1000);\n passedByTimer[delay].start();\n }\n\n function trackIntervalTime(_url, eventName, _delay) {\n if (typeof _delay !== 'number') {\n return;\n }\n\n var intervalCallback = function() {\n var url = [];\n var time = player.getCurrentTimeRound();\n var connectionType = (connection && connection.type) || 'unknown';\n\n for (var i = 0; i < _url.length; i++) {\n var urlReplace = _url[i];\n\n if (urlReplace.includes('[[curt]]')) {\n urlReplace = urlReplace.replace('[[curt]]', time);\n }\n\n if (urlReplace.includes('[[connt]]')) {\n urlReplace = urlReplace.replace('[[connt]]', connectionType);\n }\n\n url.push(urlReplace);\n }\n\n debug.log('%c%s', 'color: #795548;', '[pvt:tracker]', eventName, url);\n track(url);\n };\n\n intervalTimer = new dt.Interval(intervalCallback, _delay * 1000);\n intervalTimer.start();\n }\n\n function PVTTracker() {\n this.pvtEvents = ['impression', 'start', 'playing:interval', 'profile_change', 'complete'];\n }\n\n function setExternalData(data) {\n data.protocol = state.abr ? constants.CONTENT_TYPE.DASH : constants.CONTENT_TYPE.MP4;\n return data;\n }\n\n function applyRunningTimers(pause) {\n for (var timer in passedByTimer) {\n if (passedByTimer.hasOwnProperty(timer) && passedByTimer[timer]) {\n if (pause) {\n passedByTimer[timer].pause();\n } else {\n passedByTimer[timer].resume();\n }\n }\n }\n }\n\n PVTTracker.prototype.init = function(player, sandbox) {\n this.sandbox = sandbox;\n this.startedTracking = false;\n debug.log('[pvt:tracker] initialized');\n };\n\n PVTTracker.prototype.clear = function() {\n this.startedTracking = false;\n\n if (intervalTimer) {\n intervalTimer.stop();\n intervalTimer = null;\n }\n\n for (var timer in passedByTimer) {\n if (passedByTimer.hasOwnProperty(timer) && passedByTimer[timer]) {\n passedByTimer[timer].clear();\n passedByTimer = {};\n }\n }\n };\n\n PVTTracker.prototype.create = function(pvt) {\n var eventName, tracking, duration, time, eventtype;\n\n if (this.startedTracking) {\n return;\n }\n\n this.trackingEvents = {};\n\n this.pvt = pvt;\n this.offsetTiles = [];\n this.runningTiles = [];\n\n this.assetDuration = -1;\n\n if (!this.pvt.events) {\n return;\n }\n\n tracking = this.pvt.events;\n duration = player.getDurationRound();\n\n for (var item in tracking) {\n if (tracking.hasOwnProperty(item)) {\n eventName = tracking[item].name;\n eventtype = tracking[item].type;\n time = tracking[item].time;\n\n if (eventName === 'playing') {\n if (eventtype === 'interval') {\n this.interval = time;\n eventName += ':interval';\n } else if (eventtype === 'offset') {\n eventName += ':offset-' + time;\n this.offsetTiles[eventName] = time;\n } else if (eventtype === 'running_time') {\n eventName += ':running_time-' + time;\n this.runningTiles[eventName] = time;\n }\n }\n\n if (!this.trackingEvents[eventName]) {\n this.trackingEvents[eventName] = [];\n }\n\n this.trackingEvents[eventName].push(tracking[item].url);\n }\n }\n\n this.setDuration(duration);\n };\n\n PVTTracker.prototype.setDuration = function(duration) {\n if (this.assetDuration > 0) {\n return;\n }\n\n if (!(duration > 1)) {\n return;\n }\n\n this.assetDuration = duration;\n };\n\n PVTTracker.prototype.setProgress = function(progress) {\n var eventName, events, time, ref, rtTime, rtRef;\n var trackingURL;\n\n if (this.pvt && progress > 0) {\n events = [];\n events.push('start');\n\n if (!this.startedTracking) {\n this.startedTracking = true;\n\n eventName = 'playing:interval';\n trackingURL = this.trackingEvents[eventName];\n if (trackingURL && !intervalTimer) {\n trackIntervalTime(trackingURL, eventName, this.interval);\n }\n\n rtRef = this.runningTiles;\n\n for (var runningTile in rtRef) {\n rtTime = rtRef[runningTile];\n\n eventName = 'playing:running_time-' + rtTime;\n trackingURL = this.trackingEvents[eventName];\n trackPassedByTime(trackingURL, eventName, rtTime);\n }\n }\n\n ref = this.offsetTiles;\n for (var offsetTile in ref) {\n time = ref[offsetTile];\n\n if (time === progress) {\n events.push(offsetTile);\n }\n }\n\n for (var i = 0, len = events.length; i < len; i++) {\n eventName = events[i];\n this.track(eventName, true);\n }\n }\n };\n\n PVTTracker.prototype.complete = function() {\n this.clear();\n return this.track('complete');\n };\n\n PVTTracker.prototype.track = function(eventName, once) {\n var idx, trackingURL;\n if (once == null) {\n once = false;\n }\n\n trackingURL = this.trackingEvents && this.trackingEvents[eventName];\n\n idx = this.pvtEvents.indexOf(eventName);\n if (trackingURL != null) {\n this.emit(eventName, '');\n\n while (trackingURL.length > 0) {\n debug.log('%c%s', 'color: #795548;', '[pvt:tracker]', eventName);\n\n this.trackURLs(trackingURL);\n }\n }\n\n if (once === true) {\n delete this.trackingEvents[eventName];\n if (idx > -1) {\n this.pvtEvents.splice(idx, 1);\n }\n }\n };\n\n PVTTracker.prototype.trackURLs = function(url, variables) {\n if (variables == null) {\n variables = {};\n }\n\n return track(url, variables);\n };\n\n PVTTracker.prototype.emit = function(event, param) {\n this.sandbox.emit(event, param);\n };\n\n PVTTracker.prototype.on = function(event, callback) {\n this.sandbox.on(event, callback);\n };\n\n PVTTracker.prototype.off = function(event, callback) {\n this.sandbox.off(event, callback);\n };\n\n PVTTracker.prototype.pause = function() {\n if (intervalTimer && intervalTimer.isRunning) {\n intervalTimer.stop();\n }\n\n applyRunningTimers(true);\n };\n\n PVTTracker.prototype.resume = function() {\n if (intervalTimer && !intervalTimer.isRunning) {\n intervalTimer.start();\n }\n\n applyRunningTimers(false);\n };\n\n PVTTracker.prototype.end = function(playingTime) {\n var endUrl = this.trackingEvents && this.trackingEvents['end'];\n\n if (endUrl) {\n endUrl[0] = endUrl[0].replace('[[playTime]]', playingTime);\n helpers.http\n .fetch(endUrl[0], {\n async: true,\n timeout: 1000,\n type: constants.HTTP.TYPE.JSON,\n keepalive: true\n })\n .then(function() {\n debug.info('PVTTracker::end Call Log Success');\n })\n .catch(function(e) {\n debug.warn('PVTTracker::end Call Log Error e = ', e);\n });\n }\n };\n\n return PVTTracker;\n })();\n\n exports.addModule('pvt.tracker', new PVTTracker());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var shaka = exports.loadModule('player.shaka');\n var player = exports.loadModule('player.adapter');\n var state = exports.loadModule('controller.state');\n var QOETracker;\n\n QOETracker = (function() {\n var helpers = exports.helpers;\n var constants = exports.constants;\n var debug = helpers.debug;\n var connection = helpers.webapi.network.getConnection();\n var qoeUrl = '';\n var events = [];\n var intervalEvents = {};\n var intervalCallback = {};\n var qoeEvent = constants.QOE.EVENT;\n var prevDroppedFrames = 0;\n\n function track(eventName, data) {\n var qoeData = data;\n debug.info('[qoe:tracker] Qoe Tracking name = ', eventName, data);\n if (eventName === qoeEvent.REBUFFERING) {\n debug.tooltip('[qoe:tracker] Qoe Tracking name = ' + eventName, ' data = ' + (data.l1 || data.n1));\n } else if (eventName === qoeEvent.RESOLUTION_CHANGE) {\n debug.tooltip(\n '[qoe:tracker] Qoe Tracking name = ' + eventName,\n ' literal1 = ' + data.l1 + ', resolution = ' + data.resolution\n );\n }\n\n if (typeof qoeUrl === 'undefined' || !qoeUrl) {\n return;\n }\n\n qoeData.event = getEventName(eventName);\n qoeData = setExternalData(qoeData, eventName);\n\n helpers.http\n .fetch(qoeUrl, {\n async: true,\n type: constants.HTTP.TYPE.JSON,\n method: constants.HTTP.METHOD.POST,\n body: JSON.stringify(qoeData),\n contentType: 'text/plain;charset=UTF-8'\n })\n .then(function() {\n debug.info('qoeTracker::complete Call Log Success');\n })\n .catch(function() {\n debug.warn('qoeTracker::complete Call Log Error');\n });\n }\n\n function QOETracker() {}\n\n function bandwidthTrack() {\n var bandwidth = shaka.getBandwidth();\n var resolution;\n var connectionType;\n\n if (!bandwidth || !state.currentVideo || !state.currentVideo.profile) {\n return;\n }\n\n resolution = shaka.getCurrentProfile();\n connectionType = (connection && connection.type) || 'unknown';\n resolution = state.currentVideo.profile === 'AUTO' ? resolution : 'manual_' + resolution;\n if ((!player.videoElement.paused || bandwidth > 0) && state.abr) {\n bandwidth = bandwidth === 0 ? null : bandwidth;\n track(qoeEvent.BANDWIDTH, {\n n1: bandwidth,\n connt: connectionType,\n rslu: resolution\n });\n }\n }\n\n function dropFrameTrack() {\n var trackDroppedFrames = 0;\n\n if (state.abr) {\n trackDroppedFrames = shaka.getDropFrames();\n } else {\n var elementDroppedFrames =\n (player.videoElement.getVideoPlaybackQuality &&\n player.videoElement.getVideoPlaybackQuality().droppedVideoFrames) ||\n 0;\n if (elementDroppedFrames === prevDroppedFrames) {\n return;\n }\n trackDroppedFrames = elementDroppedFrames - prevDroppedFrames;\n prevDroppedFrames = elementDroppedFrames;\n }\n\n if (trackDroppedFrames && parseInt(trackDroppedFrames, 10) > 0) {\n track(qoeEvent.FRAME_DROP, { n1: trackDroppedFrames });\n }\n }\n\n function createInterval(name, time) {\n if (intervalCallback[name]) {\n if (intervalEvents[name]) {\n intervalEvents[name].stop();\n }\n intervalEvents[name] = new dt.Interval(intervalCallback[name], time * 1000);\n intervalEvents[name].start();\n }\n }\n\n function setExternalData(data, eventName) {\n if (eventName === qoeEvent.PLAYBACK_FAIL) {\n data.protocol = constants.CONTENT_TYPE.DASH;\n } else {\n data.protocol = state.abr ? constants.CONTENT_TYPE.DASH : constants.CONTENT_TYPE.MP4;\n }\n return data;\n }\n\n function getEventName(type) {\n for (var item in events) {\n if (events.hasOwnProperty(item) && events[item].type === type) {\n return events[item].name;\n } else if (events[item].type === 'interval') {\n return type;\n }\n }\n }\n\n QOETracker.prototype.init = function() {\n debug.log('[qoe:tracker] initialized');\n events = [];\n\n intervalCallback[qoeEvent.FRAME_DROP] = dropFrameTrack;\n intervalCallback[qoeEvent.BANDWIDTH] = bandwidthTrack;\n };\n\n QOETracker.prototype.create = function(qoe) {\n var eventName, time, eventType;\n\n events = qoe && qoe.events;\n qoeUrl = qoe && qoe.url;\n\n for (var item in events) {\n if (events.hasOwnProperty(item)) {\n eventName = events[item].name;\n eventType = events[item].type;\n\n if (eventType === 'interval') {\n time = events[item].time;\n createInterval(eventName, time);\n }\n }\n }\n };\n\n QOETracker.prototype.track = function(eventName, data) {\n track(eventName, data);\n };\n\n QOETracker.prototype.clear = function() {\n for (var item in intervalEvents) {\n if (intervalEvents.hasOwnProperty(item)) {\n intervalEvents[item].stop();\n }\n }\n };\n\n return QOETracker;\n })();\n\n exports.addModule('qoe.tracker', new QOETracker());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var constants = exports.constants;\n var vastLogData = {\n videoUrl: '',\n vastDuration: '',\n videoDuration: '',\n unTrackingEvents: []\n };\n\n function track(url) {\n if (!Array.isArray(url)) {\n helpers.http.sendBeacon(url);\n return url;\n } else {\n var results = [];\n\n for (var i = 0; i < url.length; i++) {\n if (typeof window !== 'undefined' && window !== null) {\n results.push(helpers.http.sendBeacon(url[i]));\n }\n }\n }\n\n return results;\n }\n\n var ExtensionTracker = (function() {\n function ExtensionTracker() {}\n\n ExtensionTracker.prototype.create = function(extensions) {\n var textAd = extensions[0].customObject.TextAd;\n debug.info('%c%s', 'color: #9c27b0;', '[vast:extensionTracker] created');\n debug.table(extensions);\n\n if (!textAd) {\n return;\n }\n\n this.impression = [].concat(textAd.Impression);\n this.clickTracking = [].concat(textAd.ClickTracking);\n };\n\n ExtensionTracker.prototype.click = function() {\n while (this.clickTracking.length > 0) {\n var uri = this.clickTracking.shift();\n track(uri);\n debug.info('%c%s', 'color: #9c27b0;', '[vast:extensionTracker] click');\n }\n };\n\n ExtensionTracker.prototype.load = function() {\n while (this.impression && this.impression.length > 0) {\n var uri = this.impression.shift();\n track(uri);\n debug.info('%c%s', 'color: #9c27b0;', '[vast:extensionTracker creativeView]');\n }\n };\n\n return ExtensionTracker;\n })();\n\n var MidTextAdTracker = (function() {\n function MidTextAdTracker() {}\n\n MidTextAdTracker.prototype.create = function(midTextAd) {\n debug.info('%c%s', 'color: #9c27b0;', '[vast:MidTextAdTracker] created');\n debug.table(midTextAd);\n\n this.impression = [].concat(midTextAd.Impression);\n this.clickTracking = [].concat(midTextAd.ClickTracking);\n };\n\n MidTextAdTracker.prototype.click = function() {\n while (this.clickTracking.length > 0) {\n var uri = this.clickTracking.shift();\n track(uri);\n debug.info('%c%s', 'color: #9c27b0;', '[vast:MidTextAdTracker] click');\n }\n };\n\n MidTextAdTracker.prototype.load = function() {\n while (this.impression.length > 0) {\n var url = this.impression.shift();\n track(url);\n debug.info('%c%s', 'color: #9c27b0;', '[vast:MidTextAdTracker creativeView]');\n }\n };\n\n return MidTextAdTracker;\n })();\n\n var MidImageAdTracker = (function() {\n function MidImageAdTracker() {}\n\n MidImageAdTracker.prototype.create = function(remindBanner) {\n debug.info('%c%s', 'color: #9c27b0;', '[vast:MidImageAdTracker] created');\n debug.table(remindBanner);\n\n this.impression = [].concat(remindBanner.Impression);\n this.clickTracking = [].concat(remindBanner.ClickTracking);\n };\n\n MidImageAdTracker.prototype.click = function() {\n while (this.clickTracking.length > 0) {\n var uri = this.clickTracking.shift();\n track(uri);\n debug.info('%c%s', 'color: #9c27b0;', '[vast:MidImageAdTracker] click');\n }\n };\n\n MidImageAdTracker.prototype.load = function() {\n while (this.impression.length > 0) {\n var url = this.impression.shift();\n track(url);\n debug.info('%c%s', 'color: #9c27b0;', '[vast:MidImageAdTracker creativeView]');\n }\n };\n\n return MidImageAdTracker;\n })();\n\n var VASTTracker = (function() {\n function VASTTracker() {\n this.skipDelayDefault = -1;\n this.trackingEvents = {};\n this.vastEvents = [\n 'creativeView',\n 'start',\n 'firstQuartile',\n 'midpoint',\n 'thirdQuartile',\n 'complete',\n 'resume',\n 'pause',\n 'rewind',\n 'skip',\n 'closeLinear',\n 'close'\n ];\n }\n\n VASTTracker.prototype.init = function(player, sandbox) {\n this.videoEl = player.videoElement;\n this.sandbox = sandbox;\n\n debug.log('[vast:tracker] initialized');\n };\n\n VASTTracker.prototype.create = function(ad, creative) {\n this.trackingEvents = {};\n this.muteOn = false;\n this.impressed = false;\n this.skipable = false;\n this.assetDuration = -1;\n\n this.ad = ad;\n this.impressions = this.ad.inline.impression;\n this.errors = this.ad.inline.error;\n\n if (creative.linear) {\n this.linear = creative.linear;\n\n var trackings = this.linear.trackingEvents.tracking;\n\n var clicks = this.linear.videoClicks;\n var skipoffset = this.linear.skipoffset;\n\n var creativeExtension = creative.creativeExtensions && creative.creativeExtensions.creativeExtension;\n\n if (creativeExtension && creativeExtension.length > 0) {\n this.extension = new ExtensionTracker();\n this.extension.create(creativeExtension);\n }\n\n var i = 0;\n while (i < trackings.length) {\n var eventName = trackings[i]['@_event'];\n\n if (eventName === 'progress') {\n var offset = trackings[i]['@_offset'];\n\n if (offset) {\n eventName = 'progress-' + helpers.date.hhmmssToDate(offset).getSeconds();\n }\n }\n\n if (!this.trackingEvents[eventName]) {\n this.trackingEvents[eventName] = [];\n }\n this.trackingEvents[eventName].push(trackings[i]['@_uri']);\n i++;\n }\n\n this.skipDelay = skipoffset;\n\n if (clicks) {\n this.videoClickThrough = clicks.clickThrough;\n this.videoClickTracking = clicks.clickTracking;\n }\n debug.info('%c%s', 'color: #607d8b;', '[vast:tracker] created');\n debug.table(this.trackingEvents);\n } else {\n this.skipDelay = -1;\n }\n };\n\n VASTTracker.prototype.setNonLinearTracker = function(extensions) {\n if (extensions) {\n this.midTextAdTracker = new MidTextAdTracker();\n this.midImageAdTracker = new MidImageAdTracker();\n\n for (var i = 0; i < extensions.length; i++) {\n if (extensions[i].customObject.MidTextAd) {\n this.midTextAdTracker.create(extensions[i].customObject.MidTextAd);\n }\n if (extensions[i].customObject.RemindBanner) {\n this.midImageAdTracker.create(extensions[i].customObject.RemindBanner);\n }\n }\n }\n };\n\n VASTTracker.prototype.emit = function(event, param) {\n this.sandbox.emit(event, param);\n };\n\n VASTTracker.prototype.on = function(event, callback) {\n this.sandbox.on(event, callback);\n };\n\n VASTTracker.prototype.off = function(event, callback) {\n this.sandbox.off(event, callback);\n };\n\n VASTTracker.prototype.setDuration = function(duration) {\n if (this.assetDuration > 0) {\n return;\n }\n\n if (!(duration > 1)) {\n return;\n }\n var creativeDuration = helpers.string.stringToSec(this.linear.duration);\n\n if (creativeDuration !== duration) {\n this.error('202');\n if (creativeDuration < duration) {\n player.setDuration(creativeDuration);\n }\n }\n\n this.assetDuration = creativeDuration < duration ? creativeDuration : duration;\n this.quartiles = {\n firstQuartile: Math.ceil(0.25 * this.assetDuration),\n midpoint: Math.ceil(0.5 * this.assetDuration),\n thirdQuartile: Math.ceil(0.75 * this.assetDuration)\n };\n };\n\n VASTTracker.prototype.setProgress = function(progress) {\n var eventName, events, quartile, skipDelay, time, _i, _len, ref;\n\n skipDelay = this.skipDelay ? this.skipDelay : this.skipDelayDefault;\n\n if (skipDelay !== -1 && !this.skipable) {\n skipDelay = helpers.date.hhmmssToDate(skipDelay).getSeconds();\n\n if (skipDelay > progress) {\n debug.info('%c%s', 'color: #607d8b;', '[vast:tracker event] skip-countdown', skipDelay - progress);\n } else {\n this.skipable = true;\n }\n }\n if (this.linear && progress > 0) {\n events = [];\n\n if (!this.impressed) {\n this.load();\n }\n\n events.push('start');\n events.push('progress-' + Math.round(progress));\n\n if (this.assetDuration > 0) {\n ref = this.quartiles;\n for (quartile in ref) {\n if (ref.hasOwnProperty(quartile)) {\n if (this.trackingEvents[quartile]) {\n time = ref[quartile];\n }\n\n if (time && time <= progress) {\n events.push(quartile);\n }\n }\n }\n }\n\n for (_i = 0, _len = events.length; _i < _len; _i++) {\n eventName = events[_i];\n this.track(eventName, true);\n }\n }\n };\n\n VASTTracker.prototype.setMute = function(muteOn) {\n if (this.muteOn !== muteOn) {\n this.track(muteOn ? 'mute' : 'unmute');\n }\n this.muteOn = muteOn;\n };\n\n VASTTracker.prototype.pause = function(paused) {\n if (this.paused !== paused) {\n this.track(paused ? 'pause' : 'resume', false);\n }\n this.paused = paused;\n };\n\n VASTTracker.prototype.fullscreen = function(fullscreen) {\n if (this.fullscreen !== fullscreen) {\n this.track(fullscreen ? 'fullscreen' : 'exitFullscreen');\n }\n this.fullscreen = fullscreen;\n };\n\n VASTTracker.prototype.expand = function(expanded) {\n if (this.expanded !== expanded) {\n this.track(expanded ? 'expand' : 'collapse');\n }\n this.expanded = expanded;\n };\n\n VASTTracker.prototype.setSkipDelay = function(duration) {\n if (typeof duration === 'number') {\n this.skipDelay = duration;\n }\n };\n\n VASTTracker.prototype.load = function() {\n this.impressed = true;\n\n if (!this.impressions) {\n return;\n }\n\n debug.group('%c%s', 'color: #607d8b;', '[vast:tracker event]');\n while (this.impressions.length > 0) {\n var impression = this.impressions.shift();\n if (impression['@_uri'] && impression['@_uri'] !== '') {\n this.trackURLs(impression['@_uri']);\n }\n\n debug.info('%c%s', 'color: #607d8b;', '[vast:tracker event] creativeView');\n }\n debug.groupEnd();\n\n return this.track('creativeView');\n };\n\n VASTTracker.prototype.error = function(code) {\n if (this.error['@_uri']) {\n var error = JSON.parse(JSON.stringify(this.error['@_uri']));\n for (var i = 0; i < error.length; i++) {\n error[i] = error[i].replace('[ERRORCODE]', code);\n }\n debug.info('%c%s', 'color: #607d8b;', '[vast:tracker event] error', '\\n', error);\n\n return this.trackURLs(error);\n }\n };\n\n VASTTracker.prototype.complete = function() {\n if (\n this.trackingEvents['firstQuartile'] ||\n this.trackingEvents['midpoint'] ||\n this.trackingEvents['thirdQuartile']\n ) {\n vastLogData.videoUrl = this.videoEl.currentSrc;\n vastLogData.videoDuration = this.videoEl.duration;\n vastLogData.vastDuration = this.linear.duration;\n for (var event in this.trackingEvents) {\n if (this.trackingEvents.hasOwnProperty(event)) {\n vastLogData.unTrackingEvents.push(event);\n }\n }\n\n helpers.http\n .fetch(constants.URL.KEMI_LOG_URL, {\n async: true,\n type: constants.HTTP.TYPE.JSON,\n method: constants.HTTP.METHOD.POST,\n body: JSON.stringify(vastLogData),\n contentType: 'application/json'\n })\n .then(function() {\n debug.info('vastTracker::complete Call Log Success');\n })\n .catch(function() {\n debug.warn('vastTracker::complete Call Log Error');\n });\n\n debug.info(\n '%c%s',\n 'color: #607d8b;',\n 'VastTracker::complete Warning!! When call end event but, there is pre events'\n );\n } else {\n this.track('complete');\n }\n this.clear();\n };\n\n VASTTracker.prototype.clear = function() {\n this.trackingEvents = {};\n };\n\n VASTTracker.prototype.close = function() {\n return this.track(this.linear ? 'closeLinear' : 'close');\n };\n\n VASTTracker.prototype.skip = function() {\n this.track('skip');\n this.clear();\n };\n\n VASTTracker.prototype.click = function() {\n var clickThroughURL, clickTracking;\n\n if (this.videoClickTracking && this.videoClickTracking.length) {\n debug.group('%c%s', 'color: #607d8b;', '[vast:tracker event]');\n while (this.videoClickTracking.length > 0) {\n clickTracking = this.videoClickTracking.shift();\n this.trackURLs(clickTracking['@_uri']);\n\n debug.info('%c%s', 'color: #607d8b;', '[vast:tracker event] clickTracking', clickTracking['@_uri']);\n }\n debug.groupEnd();\n }\n\n if (this.videoClickThrough) {\n clickThroughURL = this.videoClickThrough;\n return this.emit('clickthrough', clickThroughURL);\n }\n };\n\n VASTTracker.prototype.track = function(eventName, once) {\n var idx, trackingURL;\n if (once == null) {\n once = true;\n }\n if (eventName === 'closeLinear' && !this.trackingEvents[eventName] && this.trackingEvents['close']) {\n eventName = 'close';\n }\n\n if (this.trackingEvents[eventName]) {\n trackingURL = JSON.parse(JSON.stringify(this.trackingEvents[eventName]));\n idx = this.vastEvents.indexOf(eventName);\n }\n\n if (trackingURL) {\n this.emit(eventName, '');\n\n debug.group('%c%s', 'color: #607d8b;', '[vast:tracker event]');\n while (trackingURL.length > 0) {\n var url = trackingURL.shift();\n this.trackURLs(url);\n debug.info('%c%s', 'color: #607d8b;', '[vast:tracker event] ' + eventName);\n }\n debug.groupEnd();\n } else if (idx !== -1) {\n this.emit(eventName, '');\n }\n if (once === true) {\n delete this.trackingEvents[eventName];\n if (idx > -1) {\n this.vastEvents.splice(idx, 1);\n }\n }\n };\n\n VASTTracker.prototype.trackURLs = function(url, variables) {\n if (variables == null) {\n variables = {};\n }\n\n return track(url, variables);\n };\n\n return VASTTracker;\n })();\n\n exports.addModule('vast.tracker', new VASTTracker());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var Websocket;\n\n Websocket = (function() {\n var helpers = exports.helpers;\n var ws = null;\n var serverUrl = '';\n var timerInterval = null;\n var healthCheckValue = 0;\n var retry = null;\n var subscribe = null;\n var connectionTiming = '';\n var maxAttempts = 3;\n var isOpened = false;\n\n function Websocket() {}\n\n function setHealthTimer(time) {\n if (timerInterval) {\n clearInterval(timerInterval);\n }\n healthCheckValue = parseInt(time);\n\n timerInterval = setInterval(function() {\n healthCheckValue--;\n\n if (healthCheckValue <= 0) {\n isOpened = false;\n clearInterval(timerInterval);\n\n if (maxAttempts > 0) {\n maxAttempts--;\n\n setTimeout(function() {\n Websocket.prototype.open(serverUrl);\n }, retry.backoff * 1000);\n }\n }\n }, 1000);\n }\n\n function onOpen() {\n isOpened = true;\n maxAttempts = retry.maxAttempts;\n\n if (subscribe) {\n for (var i = 0; i < subscribe.length; i++) {\n var msg = {\n type: 'SUBSCRIBE',\n data: JSON.stringify(subscribe[i])\n };\n ws.send(msg);\n }\n }\n }\n\n function onMessage(event) {\n var message = JSON.parse(event.data);\n\n switch (message.type) {\n case 'HEALTH':\n setHealthTimer(message.data);\n break;\n case 'CLIP':\n if (message.event === 'VIDEO_REFRESH') {\n window.location.reload();\n }\n break;\n case 'LIVE':\n if (message.event === 'VIDEO_REFRESH') {\n helpers.sdk.sendEventCallback('pageReload');\n window.location.reload();\n }\n break;\n case 'COUNT':\n break;\n }\n }\n\n function onError(event) {\n console.log('onError ', event);\n }\n\n Websocket.prototype.init = function() {\n ws = new window.utils.MonetWebSocket();\n };\n\n Websocket.prototype.setConfig = function(config) {\n serverUrl = config.url;\n connectionTiming = config.connectionTiming;\n retry = config.retry;\n subscribe = config.subscribe;\n };\n\n Websocket.prototype.getConnectionTiming = function() {\n return connectionTiming;\n };\n\n Websocket.prototype.open = function() {\n var listener = {\n onOpen: onOpen,\n onMessage: onMessage,\n onError: onError\n };\n\n if (!isOpened) {\n ws.open(serverUrl, listener);\n }\n };\n\n Websocket.prototype.send = function(data) {\n ws.send(data);\n };\n\n return Websocket;\n })();\n\n exports.addModule('etc.websocket', new Websocket());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var VMAP;\n var AdBreak;\n var AdSource;\n var Extensions;\n\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n Extensions = (function() {\n function Extension($extensions) {\n this['extension'] = [];\n this.create($extensions);\n }\n\n Extension.prototype.create = function($extensions) {\n var extension = $extensions.Extension;\n if (extension) {\n extension = Array.isArray(extension) ? extension : [extension];\n\n this['extension'] = extension.map(function(obj) {\n return obj;\n });\n }\n };\n\n return Extension;\n })();\n\n AdSource = (function() {\n function AdSource($adSource) {\n debug.log('%c[vmap:adsource] initialized', $adSource);\n\n this['@_id'] = $adSource['@_id'];\n this['@_allowMultipleAds'] = $adSource['@_allowMultipleAds'];\n this['@_followRedirects'] = $adSource['@_followRedirects'];\n this['vastAdData'] = null;\n this['adTagURI'] = null;\n this['customData'] = null;\n this.create($adSource);\n }\n\n AdSource.prototype.create = function($adSource) {\n for (var item in $adSource) {\n if ($adSource.hasOwnProperty(item)) {\n var entry = $adSource[item];\n\n if (item === 'VASTAdData') {\n this['vastAdData'] = entry;\n } else if (item === 'AdTagURI') {\n this['adTagURI'] = {\n '@_uri': entry['#text'],\n '@_templateType': entry['@_templateType']\n };\n } else if (item === 'CustomAdData') {\n this['customData'] = entry;\n }\n }\n }\n };\n\n return AdSource;\n })();\n\n AdBreak = (function() {\n function AdBreak($adBreak) {\n debug.log('%c%s', 'color:#d9a221', '[vmap:adbreak] initialized', $adBreak);\n this['adSource'] = null;\n this['trackingEvents'] = [];\n this['extensions'] = [];\n this.create($adBreak);\n }\n\n AdBreak.prototype.create = function($adBreak) {\n for (var item in $adBreak) {\n if ($adBreak.hasOwnProperty(item)) {\n var entry = $adBreak[item];\n\n if (item === 'AdSource') {\n this['adSource'] = new AdSource(entry);\n } else if (item === 'TrackingEvents') {\n var tracking = Array.isArray(entry.Tracking) ? entry.Tracking : [entry.Tracking];\n this['trackingEvents'] = tracking.map(function($tracking) {\n return {\n uri: $tracking['#text'],\n event: $tracking['@_event']\n };\n });\n } else if (item === 'Extensions') {\n this['extensions'] = new Extensions(entry);\n } else {\n this[item] = entry;\n }\n }\n }\n };\n\n return AdBreak;\n })();\n\n VMAP = (function() {\n function VMAP() {}\n\n VMAP.prototype.init = function() {\n this['@_version'] = null;\n this['adBreak'] = [];\n this['extensions'] = [];\n\n debug.log('[vmap:parser] initialized');\n };\n\n VMAP.prototype.create = function($vmap) {\n this.init();\n debug.info('vmap json', $vmap);\n\n try {\n this['@_version'] = $vmap['@_version'];\n\n for (var item in $vmap) {\n if ($vmap.hasOwnProperty(item)) {\n var entry = $vmap[item];\n\n if (item === 'AdBreak') {\n entry = Array.isArray(entry) ? entry : [entry];\n this['adBreak'] = entry.map(function(adbreak) {\n return new AdBreak(adbreak);\n });\n } else if (item === 'Extensions') {\n this['extensions'] = new Extensions(entry);\n }\n }\n }\n return this;\n } catch (error) {\n debug.error(error);\n }\n };\n\n return VMAP;\n })();\n\n exports.addModule('ads.vmap', new VMAP());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var VAST;\n var Ad;\n var InLine;\n var Wrapper;\n var Impression;\n var Survey;\n var Creative;\n var Extension;\n var Linear;\n var Companion;\n var NonLinear;\n var Tracking;\n var MediaFile;\n var VideoClicks;\n var Icon;\n var Resource;\n var Error;\n\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n var model = {\n VAST: function() {\n this['@_version'] = null;\n this['ad'] = [];\n this['error'] = [];\n },\n Ad: function() {\n this['@_id'] = null;\n this['@_sequence'] = null;\n this['@_adType'] = null;\n this['inline'] = null;\n this['wrapper'] = null;\n },\n Inline: function() {\n this.adSystem = [];\n this.adTitle = null;\n this.descrition = null;\n this.advertiser = null;\n this.pricing = [];\n this.survey = [];\n this.error = [];\n this.impression = [];\n this.creatives = {};\n this.extensions = {};\n },\n Wrapper: function() {\n this.adSystem = [];\n this.vastAdTagURI = null;\n this.error = {};\n this.impression = [];\n this.creatives = {};\n },\n Creative: function() {\n this['@_id'] = null;\n this['@_sequence'] = null;\n this['@_adId'] = null;\n this['@_apiFramework'] = null;\n this.creativeExtensions = {};\n this.linear = null;\n this.companionAds = {\n '@_required': null\n };\n this.nonLinearAds = null;\n },\n Linear: function() {\n this['@_skipoffset'] = null;\n this.adParameters = null;\n this.duration = null;\n this.mediaFiles = {};\n this.trackingEvents = {};\n this.videoClicks = null;\n this.icons = {};\n },\n Companion: function() {\n this['@_id'] = null;\n this['@_width'] = null;\n this['@_height'] = null;\n this['@_assetWidth'] = null;\n this['@_assetHeight'] = null;\n this['@_expandedWidth'] = null;\n this['@_expandedHeight'] = null;\n this['@_apiFramework'] = null;\n this['@_adSlotID'] = null;\n this.adParameters = null;\n this.altText = null;\n this.clickThrough = {};\n this.clickTracking = [];\n this.trackingEvents = {};\n },\n NonLinear: function() {\n this['@_id'] = null;\n this['@_width'] = null;\n this['@_height'] = null;\n this['@_expandedWidth'] = null;\n this['@_expandedHeight'] = null;\n this['@_scalable'] = null;\n this['@_maintainAspectRatio'] = null;\n this['@_minSuggestedDuration'] = null;\n this['@_apiFramework'] = null;\n this.clickThrough = {};\n this.clickTracking = [];\n this.adParameters = null;\n },\n MediaFile: function() {\n this['@_uri'] = null;\n this['@_delivery'] = null;\n this['@_type'] = null;\n this['@_bitrate'] = null;\n this['@_minBitrate'] = null;\n this['@_maxBitrate'] = null;\n this['@_width'] = null;\n this['@_height'] = null;\n this['@_scalable'] = null;\n this['@_mantainAspectRatio'] = null;\n this['@_codec'] = null;\n this['@_apiFramework'] = null;\n },\n Tracking: function() {\n this['@_uri'] = null;\n this['@_event'] = null;\n this['@_offset'] = null;\n },\n VideoClicks: function() {\n this.clickThrough = {};\n this.clickTracking = [];\n this.customClick = [];\n },\n Icon: function() {\n this['@_program'] = null;\n this['@_width'] = null;\n this['@_height'] = null;\n this['@_xPosition'] = null;\n this['@_yPosition'] = null;\n this['@_duration'] = null;\n this['@_offset'] = null;\n this['@_apiFramework'] = null;\n this.iconClicks = null;\n this.iconViewTracking = null;\n },\n Resource: function() {\n this.staticResource = [];\n this.iframeResource = [];\n this.htmlResource = [];\n },\n IconClicks: function() {\n this.iconClickThrough = {};\n this.iconClickTracking = [];\n },\n Impression: function() {\n this['@_id'] = null;\n this['@_uri'] = null;\n },\n Extension: function() {\n this['@_type'] = null;\n this.customObject = {};\n },\n Survey: function() {\n this['@_uri'] = null;\n this['@_type'] = null;\n },\n Error: function() {\n this['@_uri'] = null;\n }\n };\n\n function getType(target) {\n return Object.prototype.toString.call(target).slice(8, -1);\n }\n\n function getStringValueOfNode(obj) {\n return obj['#text'] ? obj['#text'] : obj;\n }\n\n function marshalToArray(data, creator) {\n var result = [];\n var type = getType(data);\n\n if (type === 'String') {\n result.push(creator(data));\n return result;\n }\n\n if (type === 'Array') {\n result = data;\n }\n\n if (type === 'Object') {\n result.push(data);\n }\n result = result.map(creator);\n return result;\n }\n\n Resource = function($resourceParent) {\n var resource = new model.Resource();\n\n if ($resourceParent.StaticResource) {\n resource.staticResource = marshalToArray($resourceParent.StaticResource, function(sr) {\n return {\n '@_uri': getStringValueOfNode(sr),\n '@_creativeType': sr['@_creativeType'] != null ? sr['@_creativeType'] : null\n };\n });\n }\n if ($resourceParent.IFrameResource) {\n resource.iframeResource = marshalToArray($resourceParent.IFrameResource, function(ir) {\n return {\n '@_uri': getStringValueOfNode(ir)\n };\n });\n }\n if ($resourceParent.HTMLResource) {\n resource.htmlResource = marshalToArray($resourceParent.HTMLResource, function(hr) {\n return {\n '@_uri': getStringValueOfNode(hr)\n };\n });\n }\n return resource;\n };\n\n Icon = function($icon) {\n // inherit Resource(static, iframe, html)\n model.Icon.prototype = Resource($icon);\n model.Icon.prototype.constructor = model.Icon;\n var icon = new model.Icon();\n\n icon['@_program'] = $icon['@_program'] != null ? $icon['@_program'] : '';\n icon['@_width'] = $icon['@_width'] != null ? $icon['@_width'] : null;\n icon['@_height'] = $icon['@_height'] != null ? $icon['@_height'] : null;\n icon['@_xPosition'] = $icon['@_xPosition'] != null ? $icon['@_xPosition'] : null;\n icon['@_yPosition'] = $icon['@_yPosition'] != null ? $icon['@_yPosition'] : null;\n icon['@_duration'] = $icon['@_duration'] != null ? $icon['@_duration'] : null;\n icon['@_offset'] = $icon['@_offset'] != null ? $icon['@_offset'] : null;\n icon['@_apiFramework'] = $icon['@_apiFramework'] != null ? $icon['@_apiFramework'] : null;\n\n if ($icon.IconClicks) {\n icon.iconClicks = {\n iconClickThrough: {\n '@_uri': $icon.IconClicks.IconClickThrough != null ? $icon.IconClicks.IconClickThrough : null\n },\n iconClickTrackings: marshalToArray($icon.IconClicks.IconClickTracking, function(ict) {\n return {\n '@_uri': getStringValueOfNode(ict),\n '@_id': ict['@_id'] != null ? ict['@_id'] : null\n };\n })\n };\n }\n\n icon.iconViewTracking = marshalToArray($icon.IconViewTracking, function(ivt) {\n return {\n '@_uri': getStringValueOfNode(ivt)\n };\n });\n\n return icon;\n };\n\n VideoClicks = function($videoClicks) {\n var videoClicks = new model.VideoClicks();\n\n if ($videoClicks.ClickThrough) {\n videoClicks.clickThrough = {\n '@_uri': getStringValueOfNode($videoClicks.ClickThrough),\n '@_id': $videoClicks.ClickThrough['@_id'] != null ? $videoClicks.ClickThrough['@_id'] : null\n };\n }\n\n if ($videoClicks.ClickTracking) {\n videoClicks.clickTracking = marshalToArray($videoClicks.ClickTracking, function(ct) {\n return {\n '@_uri': getStringValueOfNode(ct),\n '@_id': ct['@_id'] != null ? ct['@_id'] : null\n };\n });\n }\n\n if ($videoClicks.CustomClick) {\n videoClicks.customClick = marshalToArray($videoClicks.CustomClick, function(cc) {\n return {\n '@_uri': getStringValueOfNode(cc),\n '@_id': cc['@_id'] != null ? cc['@_id'] : null\n };\n });\n }\n\n return videoClicks;\n };\n\n Tracking = function($tracking) {\n var tracking = new model.Tracking();\n tracking['@_uri'] = getStringValueOfNode($tracking);\n tracking['@_event'] = $tracking['@_event'] != null ? $tracking['@_event'] : null;\n tracking['@_offset'] = $tracking['@_offset'] != null ? $tracking['@_offset'] : null;\n return tracking;\n };\n\n MediaFile = function($mediaFile) {\n var mediaFile = new model.MediaFile();\n\n mediaFile['@_uri'] = getStringValueOfNode($mediaFile);\n mediaFile['@_delivery'] = $mediaFile['@_delivery'] != null ? $mediaFile['@_delivery'] : null;\n mediaFile['@_type'] = $mediaFile['@_type'] != null ? $mediaFile['@_type'] : null;\n mediaFile['@_bitrate'] = $mediaFile['@_bitrate'] != null ? $mediaFile['@_bitrate'] : null;\n mediaFile['@_minBitrate'] = $mediaFile['@_minBitrate'] != null ? $mediaFile['@_minBitrate'] : null;\n mediaFile['@_maxBitrate'] = $mediaFile['@_maxBitrate'] != null ? $mediaFile['@_maxBitrate'] : null;\n mediaFile['@_width'] = $mediaFile['@_width'] != null ? $mediaFile['@_width'] : null;\n mediaFile['@_height'] = $mediaFile['@_height'] != null ? $mediaFile['@_height'] : null;\n mediaFile['@_scalable'] = $mediaFile['@_scalable'] != null ? $mediaFile['@_scalable'] : null;\n mediaFile['@_mantainAspectRatio'] =\n $mediaFile['@_mantainAspectRatio'] != null ? $mediaFile['@_mantainAspectRatio'] : null;\n mediaFile['@_codec'] = $mediaFile['@_codec'] != null ? $mediaFile['@_codec'] : null;\n mediaFile['@_apiFramework'] = $mediaFile['@_apiFramework'] != null ? $mediaFile['@_apiFramework'] : null;\n\n return mediaFile;\n };\n\n Companion = function($companion) {\n // inherit Rsource(static, iframe, html)\n model.Companion.prototype = Resource($companion);\n model.Companion.prototype.constructor = model.Companion;\n var companion = new model.Companion();\n\n companion['@_id'] = $companion['@_id'] != null ? $companion['@_id'] : null;\n companion['@_width'] = $companion['@_width'] != null ? $companion['@_width'] : null;\n companion['@_height'] = $companion['@_height'] != null ? $companion['@_height'] : null;\n companion['@_assetWidth'] = $companion['@_assetWidth'] != null ? $companion['@_assetWidth'] : null;\n companion['@_assetHeight'] = $companion['@_assetHeight'] != null ? $companion['@_assetHeight'] : null;\n companion['@_expandedWidth'] = $companion['@_expandedWidth'] != null ? $companion['@_expandedWidth'] : null;\n companion['@_expandedHeight'] = $companion['@_expandedHeight'] != null ? $companion['@_expandedHeight'] : null;\n companion['@_apiFramework'] = $companion['@_apiFramework'] != null ? $companion['@_apiFramework'] : null;\n companion['@_adSlotID'] = $companion['@_adSlotID'] != null ? $companion['@_adSlotID'] : null;\n\n if ($companion.AdParameters != null) {\n companion.adParameters = {\n '@_content': getStringValueOfNode($companion.AdParameters),\n '@_xmlEncoded': $companion.AdParameters['@_xmlEncoded']\n };\n }\n companion.altText = $companion.AltText != null ? $companion.AltText : null;\n companion.clickThrough['@_uri'] =\n $companion.CompanionClickThrough != null ? $companion.CompanionClickThrough : null;\n\n if ($companion.CompanionClickTracking) {\n companion.clickTracking = marshalToArray($companion.CompanionClickTracking, function(cct) {\n return {\n '@_uri': getStringValueOfNode(cct),\n '@_id': cct['@_id'] != null ? cct['@_id'] : null\n };\n });\n }\n\n if ($companion.TrackingEvents != null) {\n companion.trackingEvents.tracking = marshalToArray($companion.TrackingEvents.Tracking, Tracking);\n }\n };\n\n Linear = function($linear) {\n var linear = new model.Linear();\n linear['@_skipoffset'] = $linear['@_skipoffset'] != null ? $linear['@_skipoffset'] : null;\n if ($linear.AdParameters != null) {\n linear.adParameters = {\n '@_content': getStringValueOfNode($linear.AdParameters),\n '@_xmlEncoded': $linear.AdParameters['@_xmlEncoded']\n };\n }\n if ($linear.Duration != null) {\n linear.duration = $linear.Duration;\n }\n if ($linear.MediaFiles != null) {\n linear.mediaFiles.mediaFile = marshalToArray($linear.MediaFiles.MediaFile, MediaFile);\n }\n\n if ($linear.TrackingEvents != null) {\n linear.trackingEvents.tracking = marshalToArray($linear.TrackingEvents.Tracking, Tracking);\n }\n\n if ($linear.VideoClicks != null) {\n linear.videoClicks = VideoClicks($linear.VideoClicks);\n }\n\n if ($linear.Icons != null) {\n linear.icons.icon = marshalToArray($linear.Icons.Icon, Icon);\n }\n\n return linear;\n };\n\n NonLinear = function($nonlinear) {\n // inherit Rsource(static, iframe, html)\n model.NonLinear.prototype = Resource($nonlinear);\n model.NonLinear.prototype.constructor = model.NonLinear;\n\n var nonlinear = new model.NonLinear();\n nonlinear['@_id'] = $nonlinear['@_id'] != null ? $nonlinear['@_id'] : null;\n nonlinear['@_width'] = $nonlinear['@_width'] != null ? $nonlinear['@_width'] : null;\n nonlinear['@_height'] = $nonlinear['@_height'] != null ? $nonlinear['@_height'] : null;\n nonlinear['@_expandedWidth'] = $nonlinear['@_expandedWidth'] != null ? $nonlinear['@_expandedWidth'] : null;\n nonlinear['@_expandedHeight'] = $nonlinear['@_expandedHeight'] != null ? $nonlinear['@_expandedHeight'] : null;\n nonlinear['@_scalable'] = $nonlinear['@_scalable'] != null ? $nonlinear['@_scalable'] : null;\n nonlinear['@_maintainAspectRatio'] =\n $nonlinear['@_maintainAspectRatio'] != null ? $nonlinear['@_maintainAspectRatio'] : null;\n nonlinear['@_minSuggestedDuration'] =\n $nonlinear['@_minSuggestedDuration'] != null ? $nonlinear['@_minSuggestedDuration'] : null;\n nonlinear['@_apiFramework'] = $nonlinear['@_apiFramework'] != null ? $nonlinear['@_apiFramework'] : null;\n\n if ($nonlinear.AdParameters != null) {\n nonlinear.adParameters = {\n '@_content': getStringValueOfNode($nonlinear.AdParameters),\n '@_xmlEncoded': $nonlinear.AdParameters['@_xmlEncoded']\n };\n }\n nonlinear.clickThrough['@_uri'] =\n $nonlinear.CompanionClickThrough != null ? $nonlinear.CompanionClickThrough : null;\n\n if ($nonlinear.CompanionClickTracking) {\n nonlinear.clickTracking = marshalToArray($nonlinear.CompanionClickTracking, function(cct) {\n return {\n '@_uri': getStringValueOfNode(cct),\n '@_id': cct['@_id'] != null ? cct['@_id'] : null\n };\n });\n }\n\n if ($nonlinear.TrackingEvents != null) {\n nonlinear.trackingEvents.tracking = marshalToArray($nonlinear.TrackingEvents.Tracking, Tracking);\n }\n };\n\n Extension = function($extension) {\n var extension = new model.Extension();\n for (var item in $extension) {\n if ($extension.hasOwnProperty(item)) {\n if (item === 'type') {\n extension['@_type'] = $extension[item];\n } else {\n extension.customObject[item] = $extension[item];\n }\n }\n }\n return extension;\n };\n\n Creative = function($creative) {\n var creative = {};\n\n if ($creative['@_id']) {\n creative['@_id'] = $creative['@_id'];\n }\n\n if ($creative['@_sequence']) {\n creative['@_sequence'] = $creative['@_sequence'];\n }\n\n if ($creative['@_adId']) {\n creative['@_adId'] = $creative['@_adId'];\n }\n\n if ($creative['@_apiFramework']) {\n creative['@_apiFramework'] = $creative['@_apiFramework'];\n }\n\n if ($creative.CreativeExtensions) {\n creative.creativeExtensions = {};\n creative.creativeExtensions.creativeExtension = marshalToArray(\n $creative.CreativeExtensions.CreativeExtension,\n Extension\n );\n }\n\n if ($creative.Linear) {\n creative.linear = Linear($creative.Linear);\n }\n\n if ($creative.CompanionAds) {\n creative.companionAds = {};\n creative.companionAds['@_required'] =\n $creative.CompanionAds['@_required'] != null ? $creative.CompanionAds['@_required'] : null;\n creative.companionAds.companion = marshalToArray($creative.CompanionAds.Companion, Companion);\n }\n\n if ($creative.NonLinearAds) {\n creative.nonLinearAds = marshalToArray($creative.NonLinearAds.NonLinear, NonLinear);\n }\n return creative;\n };\n\n Survey = function($survey) {\n var survey = new model.Survey();\n survey['@_uri'] = getStringValueOfNode($survey);\n survey['@_type'] = $survey['@_type'];\n return survey;\n };\n\n Impression = function($impression) {\n var impression = new model.Impression();\n impression['@_uri'] = getStringValueOfNode($impression);\n impression['@_id'] = $impression['@_id'];\n return impression;\n };\n\n Error = function($error) {\n var error = new model.Error();\n error['@_uri'] = getStringValueOfNode($error);\n return error;\n };\n\n InLine = function($inline) {\n var inline = new model.Inline();\n\n inline.adSystem = $inline.AdSystem != null ? $inline.AdSystem : null;\n inline.adTitle = $inline.AdTitle != null ? $inline.AdTitle : null;\n inline.descrition = $inline.Description != null ? $inline.Description : null;\n inline.advertiser = $inline.Advertiser != null ? $inline.Advertiser : null;\n inline.pricing = $inline.Pricing != null ? $inline.Pricing : null;\n\n if ($inline.Error != null) {\n inline.error = marshalToArray($inline.Error, Error);\n }\n\n if ($inline.Survey != null) {\n inline.survey = marshalToArray($inline.Survey, Survey);\n }\n if ($inline.Impression != null) {\n inline.impression = marshalToArray($inline.Impression, Impression);\n }\n if ($inline.Creatives != null) {\n inline.creatives.creative = marshalToArray($inline.Creatives.Creative, Creative);\n }\n if ($inline.Extensions != null) {\n inline.extensions.extension = marshalToArray($inline.Extensions.Extension, Extension);\n }\n\n return inline;\n };\n\n Wrapper = function($wrapper) {\n var wrapper = new model.Wrapper();\n wrapper.adSystem = $wrapper.AdSystem != null ? $wrapper.AdSystem : null;\n return wrapper;\n };\n\n Ad = function($ad) {\n var ad = new model.Ad();\n ad['@_id'] = $ad['@_id'];\n ad['@_sequence'] = $ad['@_sequence'];\n ad['@_adType'] = $ad['@_adType'];\n\n if ($ad.InLine != null) {\n ad.inline = InLine($ad.InLine);\n }\n if ($ad.Wrapper != null) {\n ad.wrapper = Wrapper($ad.Wrapper);\n }\n return ad;\n };\n\n VAST = (function() {\n function VAST() {}\n\n VAST.prototype.init = function() {};\n\n VAST.prototype.create = function($vast) {\n try {\n var vast = new model.VAST();\n vast['@_version'] = $vast['@_version'];\n\n if ($vast.Ad != null) {\n var ads = Array.isArray($vast.Ad) ? $vast.Ad : [$vast.Ad];\n vast.ad = ads.map(Ad);\n }\n\n if ($vast.Error != null) {\n vast.error = marshalToArray($vast.Error, Error);\n }\n\n return vast;\n } catch (error) {\n debug.error(error);\n }\n };\n\n return VAST;\n })();\n\n exports.addModule('ads.vast', new VAST());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var PARSER = (function() {\n var vmap = exports.loadModule('ads.vmap');\n var vast = exports.loadModule('ads.vast');\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n function PARSER() {}\n\n PARSER.prototype.init = function() {};\n\n PARSER.prototype.parseVmap = function(xml) {\n var result = helpers.parser.xml2json(xml);\n if (result.VMAP) {\n return vmap.create(result.VMAP);\n }\n };\n\n PARSER.prototype.parseVast = function(xml) {\n var result = helpers.parser.xml2json(xml);\n debug.info('parse vast to json -', result);\n if (result.VAST) {\n return vast.create(result.VAST);\n }\n };\n\n return PARSER;\n })();\n\n exports.addModule('ads.parser', new PARSER());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports, dt) {\n 'use strict';\n\n var state = exports.loadModule('controller.state');\n var pvtTracker = exports.loadModule('pvt.tracker');\n var vastTracker = exports.loadModule('vast.tracker');\n var pctTracker = exports.loadModule('pct.tracker');\n var qoeTracker = exports.loadModule('qoe.tracker');\n\n var Tracker;\n\n Tracker = (function() {\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var ua = exports.ua;\n\n var externalTracker = {\n beacons: null,\n checkBeaconData: function(percent) {\n try {\n if (this.beacons && this.beacons.length > 0) {\n var beacon = this.beacons[0];\n if (percent.toFixed(6) >= beacon.ratio) {\n helpers.http.sendBeacon(beacon.url);\n this.beacons.shift();\n\n debug.info('[extenal:tracker event] - ratio:', beacon.ratio);\n }\n }\n } catch (e) {\n debug.error(e);\n }\n },\n sendLeftBeaconData: function() {\n if (this.beacons && this.beacons.length > 0) {\n while (this.beacons.length > 0) {\n var beacon = this.beacons.shift();\n if (beacon.ratio === 1) {\n helpers.http.sendBeacon(beacon.url);\n\n debug.info('[extenal:tracker event] - ratio:', beacon.ratio, ', url:', beacon.url);\n }\n }\n }\n }\n };\n\n var tiaraTracker = {\n params: {\n section: constants.TIARA.SECTION.PLAYER_HTML5,\n page: '',\n action: '',\n extra: {}\n },\n setPage: function() {\n this.params.page = constants.TIARA.PC_VOD.PAGE_VIEW.PAGE_NAME;\n\n if (state.currentVideo.type === 'LIVE') {\n this.params.page = constants.TIARA.PC_LIVE.PAGE_VIEW.PAGE_NAME;\n\n if (ua.platform === 'mobile') {\n this.params.page = constants.TIARA.MOBILE_LIVE.PAGE_VIEW.PAGE_NAME;\n }\n } else {\n if (ua.platform === 'mobile') {\n this.params.page = constants.TIARA.MOBILE_VOD.PAGE_VIEW.PAGE_NAME;\n }\n }\n },\n setAction: function(actionType) {\n this.params.action = constants.TIARA.PC_VOD.PAGE_VIEW.ACTION_NAME;\n\n if (state.currentVideo.type === 'LIVE') {\n this.params.action = constants.TIARA.PC_LIVE[actionType].ACTION_NAME;\n\n if (ua.platform === 'mobile') {\n this.params.action = constants.TIARA.MOBILE_LIVE[actionType].ACTION_NAME;\n }\n } else {\n if (ua.platform === 'mobile') {\n this.params.action = constants.TIARA.MOBILE_VOD[actionType].ACTION_NAME;\n }\n }\n },\n trackViewImp: function(params) {\n this.setPage();\n\n if (params && typeof params === 'object') {\n dt.extend(this.params, params, true);\n }\n\n helpers.tiara.trackViewImp(this.params);\n },\n trackEvent: function(params) {\n this.setPage();\n this.setAction('EVENT');\n\n if (params && typeof params === 'object') {\n dt.extend(this.params, params, true);\n }\n\n helpers.tiara.trackEvent(this.params);\n },\n trackUsage: function(params) {\n this.setPage();\n\n if (params && typeof params === 'object') {\n dt.extend(this.params, params, true);\n }\n\n helpers.tiara.trackUsage(this.params);\n }\n };\n\n function Tracker() {}\n\n Tracker.prototype.init = function() {\n debug.log('[tracker] initialized');\n };\n\n Tracker.prototype.setTracker = function(video) {\n if (video.type === constants.VIDEO_TYPE.AD) {\n vastTracker.create(video.ad, video.creative);\n } else {\n pvtTracker.create(video.tracking.pvt);\n }\n };\n\n Tracker.prototype.setNonLinearTracker = function(extensions) {\n vastTracker.setNonLinearTracker(extensions);\n };\n\n Tracker.prototype.setPCTTracker = function(pct) {\n pctTracker.create(pct);\n };\n\n Tracker.prototype.setQOETracker = function(qoe) {\n qoeTracker.create(qoe);\n };\n\n Tracker.prototype.setBeaconData = function(beacons) {\n externalTracker.beacons = JSON.parse(beacons);\n };\n\n Tracker.prototype.checkBeaconData = function(percent) {\n externalTracker.checkBeaconData(percent);\n };\n\n Tracker.prototype.sendLeftBeaconData = function() {\n externalTracker.sendLeftBeaconData();\n };\n\n Tracker.prototype.tiara = tiaraTracker;\n\n return Tracker;\n })();\n\n exports.addModule('etc.tracker', new Tracker());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n var state = exports.loadModule('controller.state');\n\n var KEYCODE = {\n LEFT: 37,\n UP: 38,\n RIGHT: 39,\n DOWN: 40,\n SPACE: 32,\n Z: 90,\n COMMA: 188,\n PERIOD: 190,\n PAGEUP: 33,\n PAGEDOWN: 34,\n END: 35,\n HOME: 36,\n TAB: 9,\n ESC: 27,\n F: 70\n };\n\n var KeyboardAddon;\n\n KeyboardAddon = (function() {\n function KeyboardAddon() {}\n\n var event = dt.event;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n KeyboardAddon.prototype.init = function() {};\n\n KeyboardAddon.prototype.initWithConfig = function(config) {\n var keyDownCount = 0;\n var keydownCallback = config.keydownCallback;\n var keyupCallback = config.keyupCallback;\n\n event.on(document.body, 'keydown', function(e) {\n debug.info('keydown');\n\n if (helpers.debug.isShowServerSetting() || state.isShowError || state.onIma) {\n return;\n }\n\n for (var name in KEYCODE) {\n if (KEYCODE.hasOwnProperty(name)) {\n if (KEYCODE[name] === e.keyCode && KEYCODE[name] !== KEYCODE.TAB) {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n }\n\n switch (e.keyCode) {\n case KEYCODE.LEFT:\n keydownCallback.left(keyDownCount);\n break;\n case KEYCODE.RIGHT:\n keydownCallback.right(keyDownCount);\n break;\n case KEYCODE.UP:\n keydownCallback.up();\n break;\n case KEYCODE.DOWN:\n keydownCallback.down();\n break;\n case KEYCODE.SPACE:\n keydownCallback.space();\n break;\n case KEYCODE.Z:\n keydownCallback.z();\n break;\n case KEYCODE.COMMA:\n keydownCallback.comma();\n break;\n case KEYCODE.PERIOD:\n keydownCallback.period();\n break;\n case KEYCODE.PAGEUP:\n keydownCallback.pageUp(keyDownCount);\n break;\n case KEYCODE.PAGEDOWN:\n keydownCallback.pageDown(keyDownCount);\n break;\n case KEYCODE.END:\n keydownCallback.end();\n break;\n case KEYCODE.HOME:\n keydownCallback.home();\n break;\n case KEYCODE.TAB:\n keydownCallback.tab();\n break;\n case KEYCODE.ESC:\n keydownCallback.esc();\n break;\n case KEYCODE.F:\n keydownCallback.f();\n break;\n }\n\n keyDownCount++;\n });\n\n event.on(\n document.body,\n 'keyup',\n helpers.waiter.debounce(function(e) {\n keyDownCount = 0;\n\n switch (e.keyCode) {\n case KEYCODE.LEFT:\n player.setMute(state.mutedBeforeSeek);\n keyupCallback.left();\n break;\n case KEYCODE.RIGHT:\n player.setMute(state.mutedBeforeSeek);\n keyupCallback.right();\n break;\n case KEYCODE.UP:\n keyupCallback.up();\n break;\n case KEYCODE.DOWN:\n keyupCallback.down();\n break;\n case KEYCODE.SPACE:\n keyupCallback.space();\n break;\n case KEYCODE.Z:\n keyupCallback.z();\n break;\n case KEYCODE.COMMA:\n keyupCallback.comma();\n break;\n case KEYCODE.PERIOD:\n keyupCallback.period();\n break;\n case KEYCODE.PAGEUP:\n player.setMute(state.mutedBeforeSeek);\n keyupCallback.pageUp();\n break;\n case KEYCODE.PAGEDOWN:\n player.setMute(state.mutedBeforeSeek);\n keyupCallback.pageDown();\n break;\n case KEYCODE.END:\n keyupCallback.end();\n break;\n case KEYCODE.HOME:\n keyupCallback.home();\n break;\n case KEYCODE.F:\n keyupCallback.f();\n break;\n }\n }),\n 500\n );\n };\n\n return KeyboardAddon;\n })();\n\n exports.addModule('addon.keyboard', new KeyboardAddon());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports) {\n 'use strict';\n\n var Playlist;\n\n Playlist = (function() {\n function Playlist() {}\n\n Playlist.prototype.init = function() {\n this.isAutoPlay = false;\n this.vidList = [];\n };\n\n Playlist.prototype.getVidList = function() {\n return this.vidList;\n };\n\n Playlist.prototype.setVidList = function(vidList) {\n this.vidList = vidList;\n };\n\n Playlist.prototype.getIndex = function(vid) {\n return this.vidList.indexOf(vid);\n };\n\n Playlist.prototype.getNext = function(vid) {\n return this.vidList[this.getIndex(vid) + 1];\n };\n\n Playlist.prototype.getPrev = function(vid) {\n return this.vidList[this.getIndex(vid) - 1];\n };\n\n Playlist.prototype.hasNext = function(vid) {\n return !!this.getNext(vid);\n };\n\n return Playlist;\n })();\n\n exports.addModule('playlist.playlist', new Playlist());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var Queue;\n\n Queue = (function() {\n function Queue() {\n this.init();\n }\n\n Queue.prototype.init = function() {\n this.playList = [];\n this.front = null;\n\n this.prerolls = [];\n this.contents = [];\n this.midrolls = [];\n this.postrolls = [];\n\n this.overlayAds = [];\n this.sdkAds = [];\n };\n\n Queue.prototype.set = function(arr) {\n this.playList = arr;\n };\n\n Queue.prototype.get = function() {\n return this.playList;\n };\n\n Queue.prototype.enqueue = function(data) {\n this.front = data;\n this.playList.push(data);\n };\n\n Queue.prototype.enqueueArray = function(array) {\n this.playList = this.playList.concat(array);\n };\n\n Queue.prototype.dequeue = function() {\n this.front = this.playList.shift();\n return this.front;\n };\n\n Queue.prototype.dequeueCancel = function(data) {\n if (data) {\n this.front = data;\n this.playList.unshift(data);\n }\n };\n\n Queue.prototype.size = function() {\n return this.playList.length;\n };\n\n Queue.prototype.isEmpty = function() {\n return !(this.size() > 0);\n };\n\n Queue.prototype.peek = function() {\n return this.front;\n };\n\n Queue.prototype.hasNextQueue = function() {\n return this.prerolls.length > 0 || this.postrolls.length > 0 || this.contents.length > 0;\n };\n\n Queue.prototype.resetQueue = function() {\n this.playList = [];\n };\n\n return Queue;\n })();\n\n exports.addModule('playlist.queue', new Queue());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports, dt) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n\n function DataLoader() {}\n\n DataLoader.prototype = (function() {\n var ua = exports.ua;\n var helpers = exports.helpers;\n var constants = exports.constants;\n var debug = helpers.debug;\n var env = exports.ENV;\n var PHASE = constants.PHASE[env.phase.toUpperCase()];\n var ERROR_STATUS = constants.ERROR.STATUS;\n var URL_HOST = helpers.serverHost.create(env.klimtServer, PHASE);\n\n var isIE9 = (function() {\n var isPC = ua.platform === 'pc';\n return isPC && ua.browser.msie && ua.browser.version.major === '9';\n })();\n\n function normalizeAdUrl(url) {\n if (!isIE9) {\n return url;\n }\n var urlArray = url.split('/');\n urlArray[2] = URL_HOST.replace('//', '');\n return urlArray.join('/');\n }\n\n var API = {\n CLIP_READY: {\n URL: '/katz/v2/ft/cliplink/{CLIP_LINK_ID}/ready',\n PARAM: {\n player: 'monet_html5',\n referer: env.referer ? encodeURIComponent(env.referer) : '',\n uuid: '',\n service: '',\n section: '',\n dteType: '',\n profile: 'MAIN',\n contentType: '',\n playerVersion: env.playerVersion\n }\n },\n CLIP_PLAY: {\n URL: '/katz/v2/ft/cliplink/{CLIP_LINK_ID}/play',\n PARAM: {\n player: 'monet_html5',\n referer: env.referer ? encodeURIComponent(env.referer) : '',\n uuid: '',\n profile: 'MAIN',\n service: '',\n section: '',\n tid: '',\n playerVersion: env.playerVersion\n }\n },\n CLIP_READY_AND_PLAY: {\n URL: '/katz/v3/ft/cliplink/{CLIP_LINK_ID}/readyNplay',\n PARAM: {\n player: 'monet_html5',\n referer: env.referer ? encodeURIComponent(env.referer) : '',\n pageReferer: env.referer ? encodeURIComponent(env.referer) : '',\n uuid: '',\n profile: 'MAIN',\n service: '',\n section: '',\n fields: 'seekUrl,abrVideoLocationList',\n playerVersion: env.playerVersion,\n appVersion: '',\n startPosition: '0',\n tid: ''\n }\n },\n CLIP_META: {\n PARAM: {\n fileds: '@html5vod',\n service: ''\n }\n },\n CLIP_LOCATION: {\n URL: '/katz/v3/ft/cliplink/{CLIP_LINK_ID}/videoLocation',\n PARAM: {\n service: '',\n section: '',\n player: 'monet_html5'\n }\n },\n LIVE_READY_AND_PLAY: {\n URL: '/katz/v2/ft/livelink/{LIVE_LINK_ID}/readyNplay',\n PARAM: {\n player: 'monet_html5',\n referer: env.referer ? encodeURIComponent(env.referer) : '',\n pageReferer: env.referer ? encodeURIComponent(env.referer) : '',\n uuid: '',\n service: '',\n section: '',\n dteType: '',\n profile: 'MAIN',\n playerVersion: env.playerVersion\n }\n },\n LIVE_META: {\n PARAM: {\n fileds: '@html5live',\n service: ''\n }\n },\n LIVE_LOCATION: {\n URL: '/katz/v2/ft/livelink/{LIVE_LINK_ID}/videoLocation',\n PARAM: {\n service: '',\n section: '',\n contentType: constants.CONTENT_TYPE.NPP\n }\n },\n LIVE_STAT: {\n URL: '/api/v2/ft/livelinks/{LIVE_LINK_ID}/stat'\n },\n RELATED_CLIP: {\n URL: '/api/v3/ft/cliplinks/{CLIP_LINK_ID}/related/cliplinks',\n PARAM: {\n uuid: ''\n },\n EXCLUDE_PARAM: 'fields=-user,-clipChapterThumbnailList,-tagList,-channel&fulllevels=list'\n },\n RECOMMENDED_CLIP: {\n URL: '/api/v1/ft/livelinks/{LIVE_LINK_ID}/recommended/cliplinks',\n EXCLUDE_PARAM: 'fields=-user,-clipChapterThumbnailList,-tagList,-channel,-feedBackData&fulllevels=list'\n },\n CLIP_INFO_MODIFY: {\n URL: '/api/v1/ft/clips/{CLIP_ID}'\n },\n CLIP_COVER_MODIFY: {\n URL: '/api/v1/ft/clips/{CLIP_ID}/chapterthumbnails/{THUMB_INDEX}'\n },\n OUTPUT_PROCESSING_INFO: {\n URL: '/api/v1/ft/clips/{CLIP_ID}/outputProcessingInfo'\n },\n AUTH_VERFICATION: {\n URL:\n PHASE === constants.PHASE.SANDBOX\n ? '//sandbox-auth.kakao.com/ageauths/ageauth_status.json'\n : '//auth.kakao.com/ageauths/ageauth_status.json',\n PARAM: {\n service: ''\n }\n },\n ANALYTICS_CLIP_PLAY: {\n URL:\n PHASE === constants.PHASE.SANDBOX\n ? '//sandbox-pollock.kakao.com/mongodb-api/api/playchart/v1/clip/stat?clipLinkId={CLIP_LINK_ID}'\n : PHASE === constants.PHASE.CBT\n ? '//cbt-pollock.kakao.com/mongodb-api/api/playchart/v1/clip/stat?clipLinkId={CLIP_LINK_ID}'\n : '//pollock.kakao.com/mongodb-api/api/playchart/v1/clip/stat?clipLinkId={CLIP_LINK_ID}'\n }\n };\n\n function getCurrentDate() {\n var date = new Date();\n var month = date.getMonth() + 1;\n if (month < 10) {\n month = '0' + month;\n }\n var day = date.getDate();\n if (day < 10) {\n day = '0' + day;\n }\n var hour = date.getHours();\n if (hour < 10) {\n hour = '0' + hour;\n }\n var min = date.getMinutes();\n if (min < 10) {\n min = '0' + min;\n }\n\n return date.getFullYear() + '' + month + '' + day + '' + hour + '' + min + '00';\n }\n\n function addMockData(vmapReq) {\n if (helpers.url.isValidate(env.adMediaFile)) {\n vmapReq.preview = {};\n vmapReq.preview.video_url = env.adMediaFile;\n\n if (helpers.url.isValidate(env.adClickThrough)) {\n vmapReq.preview.landing_url = env.adClickThrough;\n }\n if (!isNaN(env.adSkipoffset) && env.adSkipoffset > 0) {\n vmapReq.preview.skip_seconds = env.adSkipoffset;\n }\n }\n\n return vmapReq;\n }\n\n function buildVmapRequest(req) {\n var vmapReq = addMockData(req);\n var reqString = JSON.stringify(vmapReq);\n var reqtime = getCurrentDate();\n\n var resolution = {\n width: window.screen.width,\n height: window.screen.height\n };\n\n var viewport = {\n width: document.documentElement.clientWidth,\n height: document.documentElement.clientHeight\n };\n\n var devicePixelRatio = window.getDevicePixelRatio();\n var orientation = helpers.orientation.getOrientation();\n var connection = helpers.webapi.network.getConnection();\n var connectionType = (connection && connection.type) || 'unknown';\n\n reqString = reqString\n .replace('#IMP_REQUEST__REPLAY#', '0')\n .replace('#IMP_REQUEST__PLAYER_TYPE#', '0')\n .replace('#DEVICE__ORIENTATION#', orientation === 'landscape' ? '1' : '0')\n .replace('#DEVICE__ID#', helpers.uuid.get())\n .replace('#DEVICE__OS#', '' + ua.os.name)\n .replace('#DEVICE__PX_RATIO#', devicePixelRatio)\n .replace('#DEVICE__RESOLUTION__WIDTH#', resolution.width)\n .replace('#DEVICE__RESOLUTION__HEIGHT#', resolution.height)\n .replace('#DEVICE__DPI#', '1')\n .replace('#DEVICE__CONNECTION_TYPE#', connectionType)\n .replace('#DEVICE__VERSION#', '' + ua.os.version.info)\n .replace('#PLAYER__WIDTH_DP#', viewport.width)\n .replace('#PLAYER__HEIGHT_DP#', viewport.height)\n .replace('#PLAYER__VERSION#', env.playerVersion)\n .replace('#INFO__REQ_TIME#', reqtime);\n\n return reqString;\n }\n\n return {\n init: function() {},\n getClipReady: function(clipLinkId, params) {\n var url, pathname, queryString;\n var defaults = API.CLIP_READY.PARAM;\n\n dt.extend(defaults, params, true);\n\n pathname = API.CLIP_READY.URL.replace('{CLIP_LINK_ID}', clipLinkId);\n queryString = helpers.string.jsonToQueryString(defaults);\n\n url = URL_HOST + pathname + '?' + queryString;\n\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(url, {\n async: true,\n timeout: 5000,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n resolve(data);\n return data;\n })\n .then(function(data) {\n exports.queue.emit('complete:ready', {\n status: 'success',\n data: data,\n videoType: constants.VIDEO_TYPE.VOD\n });\n })\n .catch(function(e) {\n if (e.code) {\n exports.queue.emit('show:error', { info: e });\n }\n reject(e);\n });\n });\n },\n getClipPlay: function(clipLinkId, params) {\n var url, pathname, queryString;\n var defaults = API.CLIP_PLAY.PARAM;\n\n dt.extend(defaults, params, true);\n\n pathname = API.CLIP_PLAY.URL.replace('{CLIP_LINK_ID}', clipLinkId);\n queryString = helpers.string.jsonToQueryString(defaults);\n\n url = URL_HOST + pathname + '?' + queryString;\n\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(url, {\n async: true,\n timeout: 5000,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n resolve(data);\n return data;\n })\n .then(function(data) {\n exports.queue.emit('complete:play', {\n status: 'success',\n data: data,\n videoType: constants.VIDEO_TYPE.VOD\n });\n })\n .catch(function(e) {\n if (e.code) {\n exports.queue.emit('show:error', { info: e });\n }\n reject(e);\n });\n });\n },\n getClipReadyAndPlay: function(clipLinkId, params) {\n var url, pathname, queryString;\n var defaults = API.CLIP_READY_AND_PLAY.PARAM;\n\n dt.extend(defaults, params, true);\n\n pathname = API.CLIP_READY_AND_PLAY.URL.replace('{CLIP_LINK_ID}', clipLinkId);\n queryString = helpers.string.jsonToQueryString(defaults);\n\n url = URL_HOST + pathname + '?' + queryString + '&' + Date.now();\n\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(url, {\n async: true,\n timeout: 5000,\n type: constants.HTTP.TYPE.JSON,\n credentials: 'include'\n })\n .then(function(data) {\n resolve(data);\n return data;\n })\n .then(function(data) {\n exports.queue.emit('complete:readyAndPlay', {\n status: 'success',\n data: data,\n videoType: constants.VIDEO_TYPE.VOD\n });\n })\n .catch(function(e) {\n if (e.code) {\n exports.queue.emit('show:error', { info: e });\n }\n reject(e);\n });\n });\n },\n getMeta: function(url, params) {\n var defaults = API.CLIP_META.PARAM;\n\n if (params.type === constants.VIDEO_TYPE.LIVE) {\n defaults = API.LIVE_META.PARAM;\n }\n\n dt.extend(defaults, params, true);\n var queryString = helpers.string.jsonToQueryString(defaults);\n\n url = url + '?' + queryString;\n\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(url, {\n async: true,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n resolve(data);\n return data;\n })\n .then(function(data) {\n exports.queue.emit('complete:meta', {\n status: 'success',\n data: data\n });\n })\n .catch(function(e) {\n debug.warn('Meta error status :', e);\n\n reject();\n });\n });\n },\n getAction: function(url) {\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(url, {\n async: true,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n resolve(data);\n return data;\n })\n .catch(function(e) {\n debug.warn('getAction error status :', e);\n\n reject();\n });\n });\n },\n getClipLocation: function(clipBean, params, callback) {\n var url, pathname, queryString;\n var defaults = API.CLIP_LOCATION.PARAM;\n\n dt.extend(defaults, params, true);\n\n pathname = API.CLIP_LOCATION.URL.replace('{CLIP_LINK_ID}', clipBean.id);\n queryString = helpers.string.jsonToQueryString(defaults);\n\n url = URL_HOST + pathname + '?' + queryString;\n\n helpers.http.ajax(\n url,\n {\n onSuccess: function(data) {\n var videoLocation = data && data.videoLocation;\n\n if (!videoLocation) {\n debug.warn('failed to get clip location. caused data empty');\n return;\n }\n\n var videoUrl = videoLocation.url;\n var profile = videoLocation.profile;\n\n clipBean.videoUrl = videoUrl;\n clipBean.profile = profile;\n\n exports.queue.emit('complete:location', {\n status: 'success',\n callback: callback\n });\n },\n onError: function(e) {\n if (e.code) {\n debug.warn('failed to get clip location. caused by error:', e);\n exports.queue.emit('show:error', { info: e });\n }\n }\n },\n {\n async: false,\n type: constants.HTTP.TYPE.JSON\n }\n );\n },\n getLiveReadyAndPlay: function(liveLinkId, params) {\n var url, pathname, queryString;\n var defaults = API.LIVE_READY_AND_PLAY.PARAM;\n\n dt.extend(defaults, params, true);\n\n pathname = API.LIVE_READY_AND_PLAY.URL.replace('{LIVE_LINK_ID}', liveLinkId);\n queryString = helpers.string.jsonToQueryString(defaults);\n\n url = URL_HOST + pathname + '?' + queryString + '&' + Date.now();\n\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(url, {\n async: true,\n timeout: 5000,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n resolve(data);\n return data;\n })\n .then(function(data) {\n exports.queue.emit('complete:readyAndPlay', {\n status: 'success',\n data: data,\n params: params\n });\n })\n .catch(function(e) {\n var error = e || {};\n\n if (error.type === 'onTimeout') {\n error.code = ERROR_STATUS.LivefarmServerError.NAME;\n }\n\n if (error.code) {\n exports.queue.emit('show:error', { info: error });\n }\n\n reject();\n });\n });\n },\n getLiveLocation: function(liveBean, params, callback) {\n var url, pathname, queryString;\n var defaults = API.LIVE_LOCATION.PARAM;\n\n dt.extend(defaults, params, true);\n\n pathname = API.LIVE_LOCATION.URL.replace('{LIVE_LINK_ID}', liveBean.id);\n queryString = helpers.string.jsonToQueryString(defaults);\n\n url = URL_HOST + pathname + '?' + queryString;\n\n helpers.http.ajax(\n url,\n {\n onSuccess: function(data) {\n var videoLocation = data && data.videoLocation;\n\n if (!videoLocation) {\n debug.warn('failed to get live location. caused data empty');\n return;\n }\n\n var videoUrl = videoLocation.url;\n var profile = videoLocation.profile;\n\n liveBean.videoUrl = videoUrl;\n liveBean.profile = profile;\n\n exports.queue.emit('complete:location', {\n status: 'success',\n callback: callback\n });\n },\n onError: function(e) {\n if (e.code) {\n debug.warn('failed to get live location. caused by error:', e);\n exports.queue.emit('show:error', { info: e });\n }\n }\n },\n {\n async: false,\n type: constants.HTTP.TYPE.JSON\n }\n );\n },\n getLiveStat: function(liveLinkId) {\n var pathname = API.LIVE_STAT.URL.replace('{LIVE_LINK_ID}', liveLinkId);\n var url = URL_HOST + pathname;\n\n helpers.http\n .fetch(url, {\n async: true,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n exports.queue.emit('complete:stat', data);\n })\n .catch(function(e) {\n if (e.code) {\n debug.warn('failed to get live stat. caused by error:', e);\n }\n });\n },\n fetchVmap: function(req) {\n if (!req) {\n debug.log('Vmap request has not pre property!!');\n return;\n }\n\n var vmapUrl = normalizeAdUrl(req.req_url);\n var reqString = buildVmapRequest(req);\n\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(vmapUrl, {\n async: true,\n type: constants.HTTP.TYPE.TEXT,\n credentials: 'include',\n method: constants.HTTP.METHOD.POST,\n body: reqString,\n timeout: 5000,\n contentType: 'application/json',\n headers: {\n Accept: 'application/xml'\n }\n })\n .then(function(data) {\n exports.queue\n .emit('complete:vmap', {\n status: 'success',\n req: req,\n res: data\n })\n .then(function() {\n resolve();\n });\n })\n .catch(function(e) {\n exports.queue\n .emit('complete:vmap', {\n status: 'error',\n error: e\n })\n .then(function() {\n reject(e);\n });\n });\n });\n },\n fetchVast: function(req) {\n var isAsync = helpers.device.isSupportAjaxAsync(ua);\n var adTagURI = req.adSource && req.adSource.adTagURI;\n\n if (!adTagURI) {\n debug.log('xylophone vast adTagURI does not exist!!');\n return false;\n }\n\n var uri = adTagURI['@_uri'];\n if (!uri || uri === '') {\n debug.log('xylophone vast ad uri is empty!!');\n return false;\n }\n\n var vastUrl = normalizeAdUrl(uri);\n vastUrl = vastUrl\n .replace('[PLAYTIME]', (dt.StopWatch.has('midrollPlayingTime') / 1000).toFixed(0))\n .replace('[SEEKFROM]', helpers.string.sec2hhmmss(player.getBeforeSeekedTime()))\n .replace('[CONTENTPLAYHEAD]', helpers.string.sec2hhmmss(player.getCurrentTime()));\n debug.tooltip(\n 'Midroll AD Request PLAYTIME : ' +\n (dt.StopWatch.has('midrollPlayingTime') / 1000).toFixed(0) +\n ', CONTENTPLAYHEAD : ',\n helpers.string.sec2hhmmss(player.getCurrentTime())\n );\n\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(vastUrl, {\n async: isAsync,\n type: constants.HTTP.TYPE.TEXT,\n credentials: 'include',\n method: constants.HTTP.METHOD.GET,\n timeout: 5000,\n contentType: 'application/json',\n headers: {\n Accept: 'application/xml'\n }\n })\n .then(function(data) {\n exports.queue\n .emit('complete:vast', {\n status: 'success',\n req: req,\n res: data\n })\n .then(resolve)\n .catch(reject);\n })\n .catch(function(e) {\n if (req.timeOffset === 'start') {\n exports.queue\n .emit('complete:vast', {\n status: 'error',\n error: e\n })\n .then(function() {\n reject();\n });\n }\n });\n });\n },\n getRelatedClip: function(clipLinkId, params, size) {\n var url, pathname, queryString;\n var defaults = API.RELATED_CLIP.PARAM;\n\n dt.extend(defaults, params, true);\n queryString = helpers.string.jsonToQueryString(defaults);\n\n pathname = API.RELATED_CLIP.URL.replace('{CLIP_LINK_ID}', clipLinkId);\n url = URL_HOST + pathname + '?' + queryString + '&' + API.RELATED_CLIP.EXCLUDE_PARAM + '&size=' + size;\n\n helpers.http\n .fetch(url, {\n async: true,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n exports.queue.emit('load:clip:related', { status: 'success', data: data });\n })\n .catch(function(e) {\n exports.queue.emit('load:clip:related', { status: 'error', error: e });\n });\n },\n getRecommendedClip: function(liveLinkId, callback) {\n var url, pathname;\n\n pathname = API.RECOMMENDED_CLIP.URL.replace('{LIVE_LINK_ID}', liveLinkId);\n url = URL_HOST + pathname + '?' + API.RECOMMENDED_CLIP.EXCLUDE_PARAM;\n\n helpers.http\n .fetch(url, {\n async: true,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n exports.queue.emit('load:clip:recommended', {\n status: 'success',\n data: data,\n callback: callback\n });\n })\n .catch(function(e) {\n exports.queue.emit('load:clip:recommended', {\n status: 'error',\n error: e\n });\n });\n },\n updateClipInfo: function(clipId, params) {\n var url = API.CLIP_INFO_MODIFY.URL.replace('{CLIP_ID}', clipId);\n\n var reqString = JSON.stringify(params);\n\n helpers.http\n .fetch(url, {\n async: true,\n method: constants.HTTP.METHOD.PUT,\n type: constants.HTTP.TYPE.JSON,\n body: reqString,\n contentType: 'application/json'\n })\n .then(function(data) {\n exports.queue.emit('update:clipinfo', { status: 'success', result: data });\n })\n .catch(function(e) {\n exports.queue.emit('update:clipinfo', { status: 'error', error: e });\n });\n },\n updateClipCover: function(clipId, params, index) {\n var url = API.CLIP_COVER_MODIFY.URL.replace('{CLIP_ID}', clipId).replace('{THUMB_INDEX}', index);\n\n var reqString = JSON.stringify(params);\n\n helpers.http\n .fetch(url, {\n async: true,\n method: constants.HTTP.METHOD.PUT,\n type: constants.HTTP.TYPE.JSON,\n body: reqString,\n contentType: 'application/json'\n })\n .then(function(data) {\n exports.queue.emit('update:clipcover', { status: 'success', result: data, index: index });\n })\n .catch(function(e) {\n exports.queue.emit('update:clipcover', { status: 'error', error: e });\n });\n },\n getOutputProcessingInfo: function(clipId) {\n var url = API.OUTPUT_PROCESSING_INFO.URL.replace('{CLIP_ID}', clipId);\n\n helpers.http\n .fetch(url, {\n async: true,\n type: constants.HTTP.TYPE.JSON\n })\n .then(function(data) {\n exports.queue.emit('output:processing', { status: 'success', result: data });\n })\n .catch(function(e) {\n if (e.code) {\n debug.warn('failed to get clip location. caused by error:', e);\n }\n\n exports.queue.emit('output:processing', { status: 'error' });\n });\n },\n checkAuthStatus: function(chekUrl, params) {\n var url, queryString;\n var defaults = API.AUTH_VERFICATION.PARAM;\n\n dt.extend(defaults, params, true);\n\n queryString = helpers.string.jsonToQueryString(defaults);\n\n url = URL_HOST + chekUrl + '&' + queryString;\n\n helpers.http.ajax(\n url,\n {\n onSuccess: function(data) {\n debug.log('auth status', data);\n\n exports.queue.emit('check:auth', { status: 'success', result: data });\n },\n onError: function(e) {\n exports.queue.emit('check:auth', { status: 'error', result: e });\n }\n },\n {\n async: false,\n timeout: 5000,\n type: constants.HTTP.TYPE.JSON\n }\n );\n },\n getAnalyticsClipPlay: function(clipLinkId) {\n var url = API.ANALYTICS_CLIP_PLAY.URL.replace('{CLIP_LINK_ID}', clipLinkId);\n\n helpers.http.ajax(\n url,\n {\n onSuccess: function(data) {\n exports.queue.emit('analytics:clip:play', { status: 'success', data: data });\n },\n onError: function(e) {\n exports.queue.emit('analytics:clip:play', { status: 'error', error: e });\n }\n },\n {\n async: true,\n type: constants.HTTP.TYPE.JSON,\n contentType: 'text/plain;charset=UTF-8'\n }\n );\n }\n };\n })();\n\n exports.addModule('playlist.dataloader', new DataLoader());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports) {\n 'use strict';\n\n var queue = exports.loadModule('playlist.queue');\n var player = exports.loadModule('player.adapter');\n var state = exports.loadModule('controller.state');\n\n var MediaSession = (function() {\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var ua = exports.ua;\n var constants = exports.constants;\n\n function updatePositionState() {\n if ('setPositionState' in navigator.mediaSession) {\n var playbackRate = player.getPlaybackRate();\n var duration = player.getDurationRound();\n var position = player.getCurrentTimeRound();\n\n navigator.mediaSession.setPositionState({\n duration: duration,\n playbackRate: playbackRate === 0 ? 1 : playbackRate,\n position: position\n });\n }\n }\n\n function updateMetadata(title, isPlayingGdn) {\n var size = ua.platform === 'pc' ? 'C640x360' : 'C480x270';\n var coverUrl = helpers.string.getThumbnailFarmUrl(state.currentVideo.coverUrl, size);\n\n if ('mediaSession' in navigator) {\n navigator.mediaSession.metadata = new window.MediaMetadata({\n title: title || '',\n artist: '',\n artwork: [\n { src: coverUrl, sizes: '96x96', type: 'image/png' },\n { src: coverUrl, sizes: '128x128', type: 'image/png' },\n { src: coverUrl, sizes: '192x192', type: 'image/png' },\n { src: coverUrl, sizes: '256x256', type: 'image/png' },\n { src: coverUrl, sizes: '384x384', type: 'image/png' },\n { src: coverUrl, sizes: '512x512', type: 'image/png' }\n ]\n });\n\n if (!isPlayingGdn && queue.front.type === constants.VIDEO_TYPE.VOD) {\n updatePositionState(navigator.mediaSession);\n }\n }\n }\n\n function setPlaybackState(isPaused) {\n var state = 'none';\n\n if ('mediaSession' in navigator) {\n if (typeof isPaused === 'boolean') {\n state = isPaused ? 'paused' : 'playing';\n }\n navigator.mediaSession.playbackState = state;\n }\n }\n\n function resetMediaSession() {\n if ('mediaSession' in navigator) {\n setPlaybackState('none');\n\n if (navigator.mediaSession.setPositionState) {\n navigator.mediaSession.setPositionState(null);\n }\n navigator.mediaSession.metadata = null;\n }\n }\n\n function registerMediaSessionActionHandlers() {\n if ('mediaSession' in navigator) {\n navigator.mediaSession.setActionHandler('play', function() {\n debug.log('[media.session] user clicked play');\n if (state.ended && queue.front.type === constants.VIDEO_TYPE.LIVE) {\n return;\n }\n\n player.play();\n setPlaybackState('playing');\n\n exports.queue.emit('play:ima');\n });\n\n navigator.mediaSession.setActionHandler('pause', function() {\n debug.log('[media.session] user clicked pause');\n player.pause();\n setPlaybackState('paused');\n\n exports.queue.emit('pause:ima');\n });\n\n navigator.mediaSession.setActionHandler('seekbackward', function(details) {\n debug.log('[media.session] user clicked seekbackward', details);\n\n if (\n queue.front.type === constants.VIDEO_TYPE.AD ||\n queue.front.type === constants.VIDEO_TYPE.LIVE\n ) {\n return;\n }\n\n var currentTime = player.getCurrentTimeRound() - 10;\n if (currentTime > 0) {\n player.seekTo(currentTime);\n updatePositionState(navigator.mediaSession);\n }\n });\n\n navigator.mediaSession.setActionHandler('seekforward', function(details) {\n debug.log('[media.session] user clicked seekforward', details);\n\n if (\n queue.front.type === constants.VIDEO_TYPE.AD ||\n queue.front.type === constants.VIDEO_TYPE.LIVE\n ) {\n return;\n }\n\n var currentTime = player.getCurrentTimeRound() + 10;\n if (currentTime < player.getDurationRound()) {\n player.seekTo(currentTime);\n updatePositionState();\n }\n });\n\n try {\n navigator.mediaSession.setActionHandler('skipad', function(details) {\n debug.log('[media.session] user clicked skipad', details);\n });\n } catch (error) {\n debug.log(error);\n }\n }\n }\n\n function MediaSession() {}\n\n MediaSession.prototype.init = function(player, sandbox) {\n registerMediaSessionActionHandlers();\n\n sandbox.on('onClosed:videoEvent', function() {\n var title = '라이브 방송이 종료되었습니다.';\n\n updateMetadata(title);\n setPlaybackState(false);\n });\n };\n\n MediaSession.prototype.updateMetadata = function(title, isPlayingGdn) {\n updateMetadata(title, isPlayingGdn);\n };\n\n MediaSession.prototype.resetMediaSession = function() {\n resetMediaSession();\n };\n\n MediaSession.prototype.setPlaybackState = function(isPaused) {\n setPlaybackState(isPaused);\n };\n\n return MediaSession;\n })();\n\n exports.addModule('media.session', new MediaSession());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports, dt) {\n 'use strict';\n\n var ServerSetting;\n\n ServerSetting = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n\n var constants = exports.constants;\n var ua = exports.ua;\n var env = exports.ENV;\n var helpers = exports.helpers;\n\n var phase = constants.PHASE[env.phase.toUpperCase()];\n\n var klimtServer = '';\n var playerServer = '';\n\n var EL = {\n SERVER_SETTING_CONTAINER: $('serverSettingContainer'),\n FINISH_BUTTON: $$('#serverSettingContainer .btn_finish')[0],\n CANCEL_BUTTON: $$('#serverSettingContainer .btn_cancel')[0],\n KLIMT_INPUT: $$('#klimtServer .server_input')[0],\n PLAYER_INPUT: $$('#playerServer .server_input')[0],\n KLIMT_SELECT: $$('#klimtServer .server_select')[0],\n PLAYER_SELECT: $$('#playerServer .server_select')[0]\n };\n\n var server = {\n el: EL.SERVER_SETTING_CONTAINER,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n }\n };\n\n var listener = {\n viewEvent: function() {\n event.on(EL.SERVER_SETTING_CONTAINER, 'click', function(e) {\n var playerUrl = '//';\n event.preventDefault(e);\n\n if (e.target === EL.FINISH_BUTTON) {\n var queryString = window.location.search;\n klimtServer = EL.KLIMT_INPUT.value;\n playerServer = EL.PLAYER_INPUT.value;\n\n if (queryString.indexOf('klimt') !== -1) {\n queryString = queryString.substr(0, queryString.indexOf('&klimt'));\n }\n\n playerUrl += playerServer + window.location.pathname + '/' + queryString;\n window.open(playerUrl + '&klimt=' + klimtServer, '_self');\n helpers.debug.setShowServerSetting(false);\n server.hide();\n }\n\n if (e.target === EL.CANCEL_BUTTON) {\n EL.KLIMT_INPUT.value = klimtServer;\n EL.PLAYER_INPUT.value = playerServer;\n helpers.debug.setShowServerSetting(false);\n server.hide();\n }\n });\n\n event.on(EL.KLIMT_SELECT, 'change', function(e) {\n EL.KLIMT_INPUT.value = getKlimtServer(e.target.value);\n });\n\n event.on(EL.PLAYER_SELECT, 'change', function(e) {\n EL.PLAYER_INPUT.value = getPlayerServer(e.target.value);\n });\n }\n };\n\n function getKlimtServer(serverNum) {\n var defaultServerHost = 'tv.devel.kakao.com';\n var klimtServerHost = defaultServerHost;\n var klimtPhase = phase;\n\n if (phase === constants.PHASE.CBT) {\n klimtPhase = 'beta';\n } else if (phase === constants.PHASE.DEV) {\n klimtPhase = 'alpha';\n }\n\n if (phase !== constants.PHASE.PROD) {\n if (serverNum > 1) {\n klimtServerHost =\n klimtPhase + (serverNum === '10' ? '10' : '0' + serverNum) + '-' + defaultServerHost;\n } else {\n klimtServerHost = klimtPhase + '-' + defaultServerHost;\n }\n }\n\n if (phase !== constants.PHASE.SANDBOX || parseInt(serverNum, 10) <= 5) {\n klimtServerHost = klimtServerHost.replace('devel.', '');\n }\n\n return klimtServerHost.toLowerCase();\n }\n\n function getPlayerServer(serverNum) {\n var defaultServerHost = 'player.devel.kakao.com';\n var playerServerHost = 'pg-' + defaultServerHost;\n\n if (phase !== constants.PHASE.PROD) {\n if (serverNum > 1) {\n playerServerHost = phase + (serverNum === '10' ? '10' : '0' + serverNum) + '-' + defaultServerHost;\n } else {\n playerServerHost = phase + '-' + defaultServerHost;\n }\n } else {\n playerServerHost = playerServerHost.replace('devel.', '');\n }\n\n return playerServerHost.toLowerCase();\n }\n\n function ServerSetting() {}\n\n ServerSetting.prototype.init = function() {\n if (ua.platform !== 'pc') {\n return;\n }\n\n if (env.klimtServer) {\n klimtServer = env.klimtServer;\n } else if (window.location.host.indexOf('tv.kakao.com') !== -1) {\n klimtServer = window.location.host;\n } else {\n klimtServer = getKlimtServer(1);\n }\n\n playerServer = env.host.replace(/^http:\\/\\/|^https:\\/\\//g, '');\n\n if (EL.KLIMT_INPUT) {\n EL.KLIMT_INPUT.value = klimtServer;\n }\n\n if (EL.PLAYER_INPUT) {\n EL.PLAYER_INPUT.value = playerServer;\n }\n\n listener.viewEvent();\n };\n\n ServerSetting.prototype.show = function() {\n helpers.debug.setShowServerSetting(true);\n server.show();\n };\n\n return ServerSetting;\n })();\n\n exports.addModule('view.serversetting', new ServerSetting());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var html5 = exports.loadModule('player.html5');\n var state = exports.loadModule('controller.state');\n var pctTracker = exports.loadModule('pct.tracker');\n var Analytics;\n\n Analytics = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n var playDatas = [];\n var ageDatas = [];\n var genderDatas = [];\n var minSec = 10;\n var playChart = null;\n var genderChart = null;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var CHART_KEY = constants.STORAGE.CHART;\n\n var SELECTOR = {\n CHART_CIRCLE: '#chartContainer circle',\n BUTTON_CHART_DATA: '.btn_chartdata',\n BUTTON_CLOSE: '#videoDetailContainer .btn_close'\n };\n\n var EL = {\n CHART_CONTAINER: $('chartContainer'),\n CHART_MENU: $$('.box_chart')[0],\n CHART_CONTEXT_MENU: $$('.btn_chart_toggle')[0],\n DETAIL_CONTAINER: $('videoDetailContainer'),\n DETAIL_BUTTON: $$('.btn_chartdata')[0],\n DETAIL_CONTEXT_MENU: $$('.btn_video_data')[0],\n PLAYER_CONTAINER: $('playerContainer'),\n PROGRESSBAR: $('progress')\n };\n\n function createPlayChart() {\n playChart = window.AmCharts.makeChart('playChartDiv', {\n type: 'serial',\n categoryField: 'time',\n hideCredits: true,\n color: '#FFFFFF',\n theme: 'default',\n categoryAxis: {\n startOnAxis: true,\n labelsEnabled: false,\n axisThickness: 0,\n tickLength: 0,\n gridThickness: 0\n },\n graphs: [\n {\n balloonText: '구간별 재생수 [[value]]',\n bullet: 'round',\n bulletHitAreaSize: 20,\n bulletBorderAlpha: 0,\n bulletSize: 8,\n fillAlphas: 0,\n type: 'line',\n valueField: 'series',\n fillColors: '#ff0962',\n lineColor: '#ff0962',\n lineThickness: 3\n }\n ],\n valueAxes: [\n {\n labelsEnabled: false,\n axisThickness: 0,\n tickLength: 0,\n gridThickness: 0,\n gridAlpha: 0\n }\n ],\n balloon: {\n borderThickness: 0,\n fontSize: 12,\n fillAlpha: 1,\n fontFamily: 'Apple SD Gothic Neo',\n color: '#FFFFFF',\n fillColor: '#363d50'\n },\n dataProvider: playDatas\n });\n }\n\n function createAgeChart() {\n window.AmCharts.makeChart('ageChartDiv', {\n type: 'serial',\n categoryField: 'age',\n categoryAxis: {\n axisThickness: 0,\n tickLength: 0,\n gridThickness: 0,\n labelFrequency: 1,\n color: '#FFFFFF'\n },\n valueAxes: [\n {\n color: '#FFFFFF',\n axisThickness: 0,\n tickLength: 0,\n gridThickness: 0,\n labelFrequency: 1,\n unit: '명'\n }\n ],\n balloon: {\n borderThickness: 0,\n fontSize: 12,\n fontFamily: 'Apple SD Gothic Neo',\n color: '#FFFFFF',\n fillColor: '#363d50'\n },\n graphs: [\n {\n balloonText: '[[value]]명',\n columnWidth: 0.35,\n fillAlphas: 1,\n fillColorsField: 'color',\n lineThickness: 0,\n type: 'column',\n valueField: 'series'\n }\n ],\n dataProvider: ageDatas\n });\n }\n\n function createGenderChart() {\n genderChart = window.AmCharts.makeChart('genderChartDiv', {\n type: 'pie',\n innerRadius: '70%',\n titleField: 'gender',\n valueField: 'value',\n gradientType: 'linear',\n labelsEnabled: true,\n labelText: '[[percents]]%',\n color: '#FFFFFF',\n fontFamily: 'Apple SD Gothic Neo',\n baseColor: '#01fae0',\n colorField: 'color',\n outlineAlpha: 0.8,\n outlineColor: '#000000',\n outlineThickness: 1,\n radius: '40%',\n labelRadius: -55,\n pullOutRadius: '0%',\n startRadius: '0%',\n balloonText: '[[percents]]% ([[value]]명)',\n balloon: {\n borderThickness: 0,\n fontSize: 12,\n fontFamily: 'Apple SD Gothic Neo',\n color: '#FFFFFF',\n fillColor: '#363d50'\n },\n dataProvider: genderDatas\n });\n }\n\n function setChartDatas(data) {\n ageDatas = [];\n genderDatas = [];\n playDatas = [];\n\n setPlayDatas(data.playSection);\n setAgeDatas(data.demography.age);\n setGenderDatas(data.demography.gender);\n }\n\n function setPlayDatas(playSection) {\n var duration = state.currentVideo.duration;\n\n if (playSection.series && playSection.series.length > 0) {\n minSec = playSection.sectionSize || 10;\n playDatas.push({ time: 0, series: playSection.series[0][0] });\n for (var i = 0; i < playSection.series[0].length; i++) {\n playDatas.push({\n time: playSection.labels[i],\n series: playSection.series[0][i]\n });\n }\n playDatas.push({ time: duration, series: playSection.series[0][playSection.series[0].length - 1] });\n }\n }\n\n function setAgeDatas(age) {\n var maxPlayAgeIndex = 0;\n var maxPlayAge = 0;\n\n if (age.series.length > 0) {\n for (var i = 0; i < age.series[0].length; i++) {\n ageDatas.push({\n age: age.labels[i] + '대',\n series: age.series[0][i],\n color: '#00baff'\n });\n\n if (maxPlayAge < age.series[0][i]) {\n maxPlayAge = age.series[0][i];\n maxPlayAgeIndex = i;\n }\n }\n ageDatas[maxPlayAgeIndex].color = '#ff0962';\n }\n }\n\n function setGenderDatas(gender) {\n if (gender) {\n genderDatas.push({ gender: '남성', value: gender.maleCount, color: '#01fae0' });\n genderDatas.push({ gender: '여성', value: gender.femaleCount, color: '#bf50f6' });\n }\n }\n\n var analytics = {\n chart: {\n isShow: false,\n isCanShow: true,\n el: EL.CHART_CONTAINER,\n show: function() {\n this.isShow = true;\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n this.reSize();\n }\n },\n hide: function() {\n this.isShow = false;\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n },\n reSize: function() {\n if (this.el) {\n var playerWidth =\n parseInt(EL.PLAYER_CONTAINER.style.width.replace('px', '')) ||\n EL.PLAYER_CONTAINER.clientWidth;\n var isMaxSize = playerWidth >= 1920 || EL.PLAYER_CONTAINER.parentElement.offsetWidth >= 1920;\n var defaultCahrtHeight = isMaxSize ? 200 : 110;\n var defaultProgressBottom = 41;\n var chartHeight = this.el.clientHeight ? this.el.clientHeight : defaultCahrtHeight;\n var chartTop =\n EL.PLAYER_CONTAINER.clientHeight - defaultProgressBottom + EL.PLAYER_CONTAINER.offsetTop;\n this.el.style.width = EL.PLAYER_CONTAINER.style.width;\n this.el.style.left = EL.PLAYER_CONTAINER.style.left;\n this.el.style.top = chartTop - chartHeight + 'px';\n\n if (playChart) {\n playChart.graphs[0].lineThickness = isMaxSize ? 6 : 3;\n playChart.graphs[0].bulletSize = isMaxSize ? 16 : 8;\n }\n\n if (genderChart) {\n genderChart.labelRadius = isMaxSize ? -80 : -55;\n }\n }\n }\n },\n detail: {\n isCanShow: true,\n el: EL.DETAIL_CONTAINER,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n }\n }\n };\n\n var listener = {\n viewEvent: function() {\n event.delegate(EL.PLAYER_CONTAINER, SELECTOR.CHART_CIRCLE, 'click', function(e) {\n event.preventDefault(e);\n\n var childCount = e.target.parentNode.childElementCount;\n for (var i = 0; i < childCount; i++) {\n if (e.target.parentNode.childNodes[i] === e.target) {\n var seekTime = parseInt(i / 2);\n html5.seekTo(seekTime * minSec);\n break;\n }\n }\n pctTracker.track('chart', 'pointer');\n });\n\n event.delegate(EL.PLAYER_CONTAINER, SELECTOR.BUTTON_CHART_DATA, 'click', function(e) {\n event.preventDefault(e);\n\n analytics.detail.show();\n exports.queue.emit('hide:controller');\n exports.queue.emit('analytics:chart', true);\n pctTracker.track('detail_data');\n });\n\n event.delegate(EL.PLAYER_CONTAINER, SELECTOR.BUTTON_CLOSE, 'click', function(e) {\n event.preventDefault(e);\n\n analytics.detail.hide();\n\n if (helpers.store.get(CHART_KEY) !== 'false') {\n exports.queue.emit('analytics:chart', false);\n }\n });\n },\n customEvent: function(sandbox) {\n sandbox.on('analytics:clip:play', function(result) {\n var status = result.status;\n var data = result.data;\n\n if (status === 'success') {\n setChartDatas(data);\n\n if (playDatas.length > 0) {\n createPlayChart();\n dt.classList.remove(EL.CHART_MENU, 'hide');\n } else {\n analytics.chart.isCanShow = false;\n dt.classList.add(EL.CHART_CONTEXT_MENU, 'hide');\n }\n\n if (ageDatas.length > 0) {\n createAgeChart();\n createGenderChart();\n } else {\n analytics.detail.isCanShow = false;\n dt.classList.add(EL.DETAIL_BUTTON, 'hide');\n dt.classList.add(EL.DETAIL_CONTEXT_MENU, 'hide');\n }\n }\n });\n }\n };\n\n function Analytics() {}\n\n Analytics.prototype.init = function(player, sandbox) {\n listener.viewEvent();\n listener.customEvent(sandbox);\n };\n\n Analytics.prototype.chartShow = function() {\n analytics.chart.show();\n };\n\n Analytics.prototype.chartHide = function() {\n analytics.chart.hide();\n };\n\n Analytics.prototype.detailShow = function() {\n analytics.detail.show();\n };\n\n Analytics.prototype.detailHide = function() {\n analytics.detail.hide();\n };\n\n Analytics.prototype.isChartShow = function() {\n return analytics.chart.isShow;\n };\n\n Analytics.prototype.isCanShowPlayChart = function() {\n return analytics.chart.isCanShow;\n };\n\n Analytics.prototype.isCanShowDataChart = function() {\n return analytics.detail.isCanShow;\n };\n\n Analytics.prototype.reSize = function() {\n return analytics.chart.reSize();\n };\n\n return Analytics;\n })();\n\n exports.addModule('view.analytics', new Analytics());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n var state = exports.loadModule('controller.state');\n var pctTracker = exports.loadModule('pct.tracker');\n var serverSetting = exports.loadModule('view.serversetting');\n var analytics = exports.loadModule('view.analytics');\n\n var ContextMenu;\n\n ContextMenu = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n\n var ua = exports.ua;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n var constants = exports.constants;\n\n var EL = {\n PLAYER_CONTAINER: $('playerContainer'),\n VIDEO_CONTAINER: $('videoContainer'),\n PLAYER_CONTROLLER_CONTAINER: $('controllerContainer'),\n CONTEXT_MENU: $('contextMenu'),\n PIP_BUTTON: $$('.btn_pip')[0],\n COPY_URL_BUTTON: $$('.btn_urlcopy')[0],\n VERSION_TEXT: $$('.version_syntax')[0],\n VIDEO_CHART_BUTTON: $$('.btn_chart_toggle')[0],\n VIDEO_CHART_INPUT: $$('.btn_chart_toggle .inp_toggle')[0],\n VIDEO_CHART_LABEL: $$('.btn_chart_toggle .lab_toggle')[0],\n SETTING_SERVER_BUTTON: $$('.btn_setting_server')[0],\n VIDEO_DATA_BUTTON: $$('.btn_video_data')[0],\n SERVER_NAME_BOX: $$('.server_name_box')[0],\n PLAYER_SERVER_NAME: $$('.player_server_name')[0]\n };\n\n var isSupportClipBoard = window.ClipboardJS.isSupported();\n\n var menu = {\n el: EL.CONTEXT_MENU,\n show: function() {\n state.isContextMenuOpened = true;\n dt.classList.remove(this.el, 'hide');\n },\n hide: function() {\n state.isContextMenuOpened = false;\n dt.classList.add(this.el, 'hide');\n },\n toggle: function() {\n if (state.isContextMenuOpened) {\n this.hide();\n } else {\n this.show();\n }\n },\n setPosition: function(x, y) {\n var playerRect = EL.PLAYER_CONTAINER.getBoundingClientRect();\n var posX = x - playerRect.left + 'px';\n var posY = y - playerRect.top + 'px';\n var menuWidth = this.el.offsetWidth + 5;\n var menuHeight = this.el.offsetHeight + 5;\n\n if (window.innerWidth - x < menuWidth) {\n posX = window.innerWidth - playerRect.left - menuWidth + 'px';\n }\n\n if (window.innerHeight - y < menuHeight) {\n posY = window.innerHeight - playerRect.top - menuHeight + 'px';\n }\n\n this.el.style.left = posX;\n this.el.style.top = posY;\n },\n pip: {\n el: EL.PIP_BUTTON,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n },\n toggleButton: function(isPipMode) {\n if (isPipMode) {\n this.el.innerHTML = 'PIP 모드 종료';\n } else {\n this.el.innerHTML = 'PIP 모드';\n }\n },\n togglePip: function() {\n var isPipScreen = helpers.webapi.pip.isPipScreen();\n if (isPipScreen) {\n exitPictureInPicture();\n } else {\n requestPictureInPicture();\n }\n this.toggleButton(isPipScreen);\n }\n },\n share: {\n el: EL.COPY_URL_BUTTON,\n setUrl: function(url) {\n dt.dataset(this.el, 'clipboard-text', url);\n },\n show: function() {\n dt.classList.add(this.el, 'show');\n },\n hide: function() {\n dt.classList.add(this.el, 'hide');\n }\n },\n setVersion: function() {\n EL.VERSION_TEXT.innerHTML = env.playerVersion;\n debug.log('[context.menu] set version:', env.playerVersion);\n },\n server: {\n el: EL.SETTING_SERVER_BUTTON,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n }\n },\n videoChart: {\n el: EL.VIDEO_CHART_BUTTON,\n toggle: EL.VIDEO_CHART_INPUT,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n }\n },\n videoData: {\n el: EL.VIDEO_DATA_BUTTON,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n }\n },\n serverName: {\n el: EL.SERVER_NAME_BOX,\n show: function() {\n var serverName = env.playerServerName;\n\n if (this.el && EL.PLAYER_SERVER_NAME) {\n dt.classList.remove(this.el, 'hide');\n EL.PLAYER_SERVER_NAME.innerText = serverName;\n }\n }\n }\n };\n\n function getPosition(e) {\n var posX = e.pageX;\n var posY = e.pageY;\n\n return {\n x: posX,\n y: posY\n };\n }\n\n function setPositionMenu(e) {\n var pos = getPosition(e);\n menu.setPosition(pos.x, pos.y);\n }\n\n function requestPictureInPicture() {\n if (!helpers.webapi.pip.isPipScreen()) {\n helpers.webapi.pip.request(player.videoElement);\n }\n }\n\n function exitPictureInPicture() {\n if (helpers.webapi.pip.isPipScreen()) {\n helpers.webapi.pip.exit();\n }\n }\n\n function showPip(videoEl) {\n var video = videoEl || this;\n if (video.readyState === 0 || !document.pictureInPictureEnabled || video.disablePictureInPicture) {\n return;\n }\n menu.pip.show();\n }\n\n function onContextMenu(e) {\n event.preventDefault(e);\n menu.show();\n setPositionMenu(e);\n }\n\n function initContextMenu(videoEl) {\n var isSupportPiP = document.pictureInPictureEnabled;\n\n if (isSupportPiP) {\n showPip(videoEl);\n event.on(videoEl, 'loadedmetadata', showPip);\n event.on(videoEl, 'emptied', showPip);\n }\n\n if (!isSupportClipBoard || state.currentVideo.isLegacy) {\n menu.share.hide();\n } else {\n menu.share.show();\n }\n\n if (env.isPrivateIp) {\n menu.server.show();\n }\n\n if (env.playerServerName) {\n menu.serverName.show();\n }\n\n menu.setVersion();\n }\n\n function onEnterPictureInPicture(e) {\n var isPipMode = true;\n exports.queue.emit('request:pip');\n menu.pip.toggleButton(isPipMode);\n debug.log('[context.menu] enterpictureinpicture event handler - video entered picture-in-picture', e);\n }\n\n function onLeavePictureInPicture(e) {\n var isPipMode = false;\n\n exports.queue.emit('cancel:pip');\n menu.pip.toggleButton(isPipMode);\n\n pctTracker.track('pip_player', 'main_player');\n debug.log('[context.menu] leavepictureinpicture event handler - video left picture-in-picture', e);\n }\n\n function showNotification(isSuccess) {\n var relatedData = {\n message: isSuccess ? 'URL을 복사했습니다. 원하는 곳에 붙여넣기 하세요.' : 'URL 복사에 실패하였습니다.',\n callback: function() {\n exports.queue.emit('hide:modal');\n }\n };\n exports.queue.emit('show:notification', relatedData);\n }\n\n function videoChartToggle() {\n if (EL.VIDEO_CHART_INPUT) {\n EL.VIDEO_CHART_INPUT.checked = analytics.isChartShow();\n }\n }\n\n var listener = {\n viewEvent: function(videoEl) {\n event.on(document, 'contextmenu', function(e) {\n event.preventDefault(e);\n });\n event.on(EL.VIDEO_CONTAINER, 'contextmenu', onContextMenu);\n event.on(EL.PLAYER_CONTROLLER_CONTAINER, 'contextmenu', onContextMenu);\n event.on(videoEl, 'enterpictureinpicture', onEnterPictureInPicture);\n event.on(videoEl, 'leavepictureinpicture', onLeavePictureInPicture);\n\n event.on(\n window,\n 'resize',\n helpers.waiter.throttle(function() {\n menu.hide();\n }, 50)\n );\n\n event.on(EL.CONTEXT_MENU, 'click', function(e) {\n if (\n e.target === EL.VIDEO_CHART_INPUT ||\n e.target === EL.VIDEO_CHART_BUTTON ||\n e.target === EL.VIDEO_CHART_LABEL\n ) {\n exports.queue.emit('analytics:chart', analytics.isChartShow());\n videoChartToggle();\n if (e.target !== EL.VIDEO_CHART_INPUT) {\n event.preventDefault(e);\n }\n helpers.store.set(constants.STORAGE.CHART, analytics.isChartShow());\n\n if (analytics.isChartShow()) {\n pctTracker.track('chart', 'on');\n } else {\n pctTracker.track('chart', 'off');\n }\n return;\n }\n\n event.preventDefault(e);\n if (e.target === EL.PIP_BUTTON) {\n menu.pip.togglePip();\n pctTracker.track('context_menu', 'pip_player');\n }\n\n if (e.target === EL.COPY_URL_BUTTON) {\n pctTracker.track('context_menu', 'url_copy');\n }\n\n if (e.target === EL.SETTING_SERVER_BUTTON) {\n serverSetting.show();\n }\n\n if (e.target === EL.VIDEO_DATA_BUTTON) {\n analytics.detailShow();\n exports.queue.emit('hide:controller');\n exports.queue.emit('analytics:chart', true);\n pctTracker.track('detail_data');\n }\n\n menu.hide();\n });\n\n event.on(document, 'click', function(e) {\n var button = e.which || e.button;\n\n if (\n e.target === EL.VIDEO_CHART_INPUT ||\n e.target === EL.VIDEO_CHART_BUTTON ||\n e.target === EL.VIDEO_CHART_LABEL\n ) {\n return;\n }\n\n if (button === 1) {\n menu.hide();\n }\n });\n\n event.on(window, 'blur', function() {\n menu.hide();\n });\n },\n customEvent: function(player, sandbox) {\n sandbox.on('show:modal', function() {\n menu.hide();\n });\n\n sandbox.on('show:completion', function() {\n menu.hide();\n });\n\n sandbox.on('show:error', function() {\n exitPictureInPicture();\n });\n\n sandbox.on('create:contextmenu', function() {\n initContextMenu(player.videoElement);\n });\n },\n clipboardEvent: function(clipboard) {\n var isSuccess = true;\n\n clipboard.on('success', function() {\n showNotification(isSuccess);\n });\n\n clipboard.on('error', function() {\n isSuccess = false;\n showNotification(isSuccess);\n });\n }\n };\n\n function ContextMenu() {}\n\n ContextMenu.prototype.init = function(player, sandbox) {\n this.videoEl = player.videoElement;\n\n if (ua.platform === 'pc') {\n var clipboard = new window.ClipboardJS('#contextMenu .urlcopy', { container: $('playerContainer') });\n listener.viewEvent(this.videoEl);\n listener.customEvent(player, sandbox);\n listener.clipboardEvent(clipboard);\n }\n };\n\n ContextMenu.prototype.show = function() {\n menu.show();\n };\n\n ContextMenu.prototype.hide = function() {\n menu.hide();\n };\n\n ContextMenu.prototype.toggle = function() {\n menu.toggle();\n };\n\n ContextMenu.prototype.setShareUrl = function(url) {\n menu.share.setUrl(url);\n };\n\n ContextMenu.prototype.exitPictureInPicture = function() {\n exitPictureInPicture();\n };\n\n ContextMenu.prototype.showAnalyticButton = function() {\n if (analytics.isCanShowPlayChart()) {\n menu.videoChart.show();\n }\n\n if (analytics.isCanShowDataChart()) {\n menu.videoData.show();\n }\n };\n\n ContextMenu.prototype.hideAnalyticButton = function() {\n menu.videoChart.hide();\n menu.videoData.hide();\n };\n\n ContextMenu.prototype.videoChartToggle = function() {\n videoChartToggle();\n };\n\n ContextMenu.prototype.showPip = function() {\n menu.pip.show();\n };\n\n ContextMenu.prototype.hidePip = function() {\n menu.pip.hide();\n };\n\n return ContextMenu;\n })();\n\n exports.addModule('view.contextmenu', new ContextMenu());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n function Error() {}\n\n Error.prototype = (function() {\n var state = exports.loadModule('controller.state');\n var dataloader = exports.loadModule('playlist.dataloader');\n var player = exports.loadModule('player.adapter');\n var pctTracker = exports.loadModule('pct.tracker');\n var websocket = exports.loadModule('etc.websocket');\n var playerTemplate = exports.template;\n\n var $ = dt.$;\n var $$ = dt.$$;\n var ua = exports.ua;\n var event = dt.event;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n\n var ERROR = constants.ERROR;\n var ERROR_STATUS = constants.ERROR.STATUS;\n var AGE_LIMIT = constants.AGE_LIMIT;\n\n var EL = {\n ERROR: $('errorView'),\n NOTICE_INFO: $('noticeInfo'),\n PROCESS_INFO: $('processInfo'),\n THUMBNAIL_CONTAINER: $('thumbnailImageContainer'),\n THUMBNAIL_IMAGE: $('thumbnailImage'),\n ALERT_MESSAGE: $('alertMessage'),\n ALERT_LIVEAGENT: $('alertLiveAgent')\n };\n\n var errorTemplate = {\n linkInfo: playerTemplate.link_info\n };\n\n var error = {\n el: EL.ERROR,\n status: null,\n infoEl: EL.NOTICE_INFO,\n messageEl: null,\n callback: function() {},\n setOption: function(option) {\n dt.extend(this, option, true);\n },\n normalizeInfoType: function(status) {\n error.hideBackground();\n if (status.MESSAGE_TYPE === 'notice') {\n this.infoEl = EL.NOTICE_INFO;\n } else if (status.MESSAGE_TYPE === 'process') {\n this.infoEl = EL.PROCESS_INFO;\n } else if (status.MESSAGE_TYPE === 'input') {\n this.infoEl = EL.INPUT_INFO;\n }\n },\n show: function(status, info, option) {\n this.status = status;\n this.setOption(option);\n this.normalizeInfoType(status);\n setTemplate(status, info, this.infoEl);\n\n dt.classList.add(this.el, 'visible');\n dt.classList.remove(this.el, 'hidden');\n\n this.callback();\n },\n hide: function() {\n if (this.infoEl) {\n dt.classList.add(this.infoEl, 'hide');\n }\n\n if (EL.ALERT_LIVEAGENT) {\n dt.classList.add(EL.ALERT_LIVEAGENT, 'hide');\n }\n\n dt.classList.add(this.el, 'hidden');\n dt.classList.remove(this.el, 'visible');\n },\n showBackground: function() {\n if (EL.COVER_IMAGE) {\n dt.classList.remove(EL.COVER_IMAGE, 'hide');\n }\n },\n hideBackground: function() {\n if (EL.COVER_IMAGE) {\n dt.classList.add(EL.COVER_IMAGE, 'hide');\n }\n },\n showThumbnailImage: function() {\n if (EL.THUMBNAIL_CONTAINER) {\n dt.classList.remove(EL.THUMBNAIL_CONTAINER, 'hide');\n }\n },\n setThumbnailImage: function(url) {\n if (EL.THUMBNAIL_IMAGE) {\n EL.THUMBNAIL_IMAGE.style['background'] = 'url(' + url + ')';\n EL.THUMBNAIL_IMAGE.style['background-size'] = '100%';\n }\n },\n ageLimit: {\n timer: null,\n ageLimitImpressTime: 2000,\n show: function() {\n var ageLimit = state.currentVideo.ageLimit;\n var ageLimitErrorName;\n var self = this;\n\n if (ageLimit === AGE_LIMIT.AGE_18.name) {\n ageLimitErrorName = ERROR_STATUS.Age18.NAME;\n } else {\n ageLimitErrorName = ERROR_STATUS.Age19.NAME;\n }\n\n dt.StopWatch.start('ageLimit');\n showError(ageLimitErrorName, {});\n\n this.timer = setInterval(function() {\n var impressTime = dt.StopWatch.has('ageLimit');\n\n if (impressTime > self.ageLimitImpressTime) {\n exports.queue.emit('show:rating');\n hideError();\n player.play();\n clearInterval(self.timer);\n }\n }, 100);\n },\n isAgeLimit: function() {\n var errorCode = error.status && error.status.NAME;\n return errorCode === ERROR_STATUS.Age18.NAME || errorCode === ERROR_STATUS.Age19.NAME;\n }\n }\n };\n\n function showConfirmThumbnailImage() {\n exports.queue.emit('show:confirmThumbnailImage');\n }\n\n function showCoverThumbnailImage() {\n if (state.currentVideo && state.currentVideo.coverThumbnailUrl) {\n error.setThumbnailImage(state.currentVideo.coverThumbnailUrl);\n }\n error.showThumbnailImage();\n }\n\n function checkValidation(video) {\n if (!video) {\n return false;\n }\n\n if (video.playingInfo) {\n return false;\n }\n\n return true;\n }\n\n function getStatusByCode(errorCode) {\n var status = ERROR_STATUS[errorCode];\n\n if (!status) {\n status = ERROR.STATUS.UNAVAILABLE;\n }\n\n return status;\n }\n\n function setErrorMessage(info) {\n var status = getStatusByCode(info.code);\n\n if (info.message) {\n status.DESCRIPTION = helpers.string.replaceLinefeed(info.message);\n }\n }\n\n function showError(statusCode, info, option) {\n var errorStatus = getStatusByCode(statusCode);\n var confirmCode = constants.CONFIRM.STATUS[statusCode];\n\n var isNoPurchase = info.code === constants.CONFIRM.STATUS.NoPurchased.NAME;\n var isNeedPurchase = info.code === constants.CONFIRM.STATUS.NeedPurchased.NAME;\n var isEndedState = info.code === constants.ERROR.STATUS.LiveFinished.NAME;\n\n state.isShowError = true;\n\n exports.queue.emit('spinner:end');\n exports.queue.emit('hide:cover');\n exports.queue.emit('layerStatus:check');\n\n if (!isNoPurchase && !isNeedPurchase) {\n exports.queue.emit('hide:container');\n }\n\n if (confirmCode) {\n if (ua.platform === 'mobile' && (isNoPurchase || isNeedPurchase)) {\n confirmCode = constants.CONFIRM.STATUS.NoPurchasedForMobile;\n }\n\n var confirmName = confirmCode.NAME;\n // todo confirm.js와 error.js가 순환되지않도록 변경해야함 / error를 confirm, notice가 구현하는 방법으로 변경\n if (confirmName !== ERROR_STATUS.EncodingNotCompleted.NAME || ua.platform !== 'pc') {\n exports.queue.emit('show:confirm', {\n status: confirmName,\n info: info,\n option: option\n });\n return;\n }\n }\n\n if (errorStatus.MESSAGE_TYPE === 'process' && ua.platform === 'pc') {\n dataloader.getOutputProcessingInfo(env.clipId);\n }\n\n error.show(errorStatus, info, option);\n\n if (isEndedState) {\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onVideoStateChange, [\n constants.PLAYER_VIDEO_STATE.ENDED,\n state.currentVideo.id,\n player.getCurrentTimeRound()\n ]);\n return;\n }\n\n debug.info('show error type: ', errorStatus.MESSAGE_TYPE);\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onPlayError);\n }\n\n function showAgeLimit() {\n error.ageLimit.show();\n }\n\n function hideError() {\n var ageLimitImpressTime = dt.StopWatch.has('ageLimit');\n\n if (error.ageLimit.isAgeLimit() && ageLimitImpressTime < error.ageLimit.ageLimitImpressTime) {\n return;\n }\n\n exports.queue.emit('show:container');\n exports.queue.emit('hide:confirm');\n dt.StopWatch.stop('ageLimit');\n\n state.isShowError = false;\n error.hide();\n }\n\n function setTemplate(status, info, target) {\n var paragraphEl = $$('p', target)[0];\n\n if (status.NAME === ERROR_STATUS.LiveAgentNotInstalled.NAME) {\n dt.classList.remove(EL.ALERT_LIVEAGENT, 'hide');\n dt.classList.add(EL.ALERT_MESSAGE, 'hide');\n exports.queue.emit('live:updateSetupView', info.profile);\n return;\n } else {\n dt.classList.remove(EL.ALERT_MESSAGE, 'hide');\n dt.classList.add(EL.ALERT_LIVEAGENT, 'hide');\n }\n\n if (\n status.MESSAGE_TYPE !== 'process' ||\n (ua.platform !== 'pc' && status.NAME === ERROR_STATUS.EncodingNotCompleted.NAME)\n ) {\n paragraphEl.innerHTML = status.DESCRIPTION;\n }\n\n if (status.NAME === ERROR_STATUS.LegacyPlayerNotice.NAME) {\n var view = {\n infoUrl: status.LINK_URL\n };\n paragraphEl.innerHTML += errorTemplate.linkInfo.render(view);\n }\n\n var classes = status.CLASS_NAME && status.CLASS_NAME.split(' ');\n\n if (dt.classList.has(target.parentElement, constants.ERROR.CLASS.BACKGROUND_ALPHA)) {\n dt.classList.remove(target.parentElement, constants.ERROR.CLASS.BACKGROUND_ALPHA);\n }\n\n while (classes.length > 0) {\n var className = classes.pop();\n if (\n className === constants.ERROR.CLASS.BACKGROUND_ALPHA ||\n className === constants.ERROR.CLASS.BACKGROUND_DIMMED\n ) {\n dt.classList.add(target.parentElement, className);\n } else if (className === constants.ERROR.CLASS.THUMBNAIL_IMG) {\n showCoverThumbnailImage();\n } else {\n dt.classList.add(target, className);\n }\n }\n\n var linkType = status.LINK_TYPE;\n\n if (linkType) {\n var button = null;\n var link = null;\n\n var linkContainer = $$('.' + linkType, target)[0];\n\n if (linkContainer) {\n dt.classList.remove(linkContainer, 'hide');\n\n if (linkType === 'qna') {\n link = $$('a', linkContainer)[0];\n link.href = status.LINK_URL || 'http://www.kakao.com/policy/right';\n } else {\n button = $$('button', linkContainer)[0];\n }\n\n if (button && info && info.checkUrl) {\n button.setAttribute('data-url', info.checkUrl);\n }\n }\n }\n\n if (status.NAME === ERROR_STATUS.LiveFinished.NAME || status.NAME === ERROR_STATUS.LiveException.NAME) {\n dt.classList.add(target, 'finished');\n }\n\n dt.classList.remove(target, 'hide');\n }\n\n function checkAuth(url) {\n var params = {\n service: 'kakao_tv'\n };\n\n dataloader.checkAuthStatus(url, params);\n }\n\n var listener = {\n viewEvent: function() {\n event.delegate(EL.ERROR, '.link_refresh', 'click', function() {\n pctTracker.track('alert_network', 'refresh');\n location.reload();\n });\n event.delegate(EL.ERROR, '.auth button', 'click', function(e) {\n if (e.target.tagName === 'BUTTON') {\n if (dt.classList.has(e.target, 'check')) {\n var checkUrl = e.target.getAttribute('data-url');\n debug.log(checkUrl);\n checkAuth(checkUrl);\n pctTracker.track('age_limit', 'verify');\n }\n\n if (dt.classList.has(e.target, 'complete')) {\n location.reload();\n }\n }\n });\n event.delegate(EL.ERROR, '.link_redirect', 'click', function(e) {\n e.preventDefault();\n\n env.playerLegacy = false;\n error.hide();\n var profile = state.abr\n ? constants.DASH_PROFILE[state.currentVideo.profile]\n : state.currentVideo.profile;\n exports.queue.emit('loadAndPlay:videoById', state.currentVideo.id, profile);\n });\n event.delegate(EL.ERROR, '.setup_guide', 'click', function() {\n window.open(constants.URL.LIVEAGENT_SETUP_GUIDE, '_blank');\n pctTracker.track('live_install', 'guide');\n });\n\n event.delegate(EL.ERROR, '.btn_agent_setup', 'click', function() {\n var downloadUrl =\n ua.os.name === 'mac'\n ? constants.URL.LIVEAGENT_DOWNLOAD_URL_MAC\n : constants.URL.LIVEAGENT_DOWNLOAD_URL_WIN;\n var profile =\n $$('.alert_liveagent .btn_agent_setup')[0].getAttribute('data-profile') ||\n constants.PROFILE.HIGH;\n window.open(downloadUrl, '_self');\n pctTracker.track('live_install', 'liveagent');\n\n player.checkForAgentInstallation(profile);\n });\n\n event.delegate(EL.ERROR, '.a_agent_not_setup', 'click', function() {\n hideError();\n if (state.currentVideo.profile === constants.PROFILE.BASE) {\n if (state.playerClass === constants.PLAYERCLASS.KAMP) {\n player.play();\n } else {\n exports.queue.emit('load:videoById', 0, true);\n }\n pctTracker.track('live_install', 'play');\n return;\n }\n\n if (player.isPaused()) {\n state.currentVideo.profile = constants.PROFILE.BASE;\n exports.queue.emit('load:videoById', 0, true);\n }\n\n pctTracker.track('liveagent', 'install');\n });\n\n event.delegate(EL.ERROR, '.btn_close', 'click', function() {\n hideError();\n });\n },\n customEvent: function(sandbox) {\n var timer = null;\n var errorCount = 0;\n\n sandbox.on('show:error', function(data) {\n var errorInfo = data.info;\n var errorStatus = getStatusByCode(errorInfo.code);\n\n setErrorMessage(errorInfo);\n showError(errorInfo.code, errorInfo);\n\n if (\n (errorInfo.metaUrl &&\n errorStatus.CLASS_NAME.indexOf(constants.ERROR.CLASS.THUMBNAIL_IMG) > 0) ||\n errorInfo.code === constants.CONFIRM.STATUS.NoPurchased.NAME\n ) {\n exports.queue.emit('load:meta', {\n metaUrl: errorInfo.metaUrl,\n callback:\n errorInfo.code === constants.CONFIRM.STATUS.NoPurchased.NAME\n ? showConfirmThumbnailImage\n : showCoverThumbnailImage\n });\n }\n\n if (errorInfo.ws) {\n websocket.setConfig(errorInfo.ws);\n if (websocket.getConnectionTiming() === 'IMMEDIATELY') {\n websocket.open();\n }\n }\n });\n sandbox.on('hide:error', function() {\n hideError();\n });\n sandbox.on('output:processing', function(data) {\n var callDelay = 5 * 1000;\n var pState;\n\n if (data.status === 'success') {\n pState = data.result.state;\n\n if (pState === 'PROCESSING') {\n $('loadingNum').innerHTML = data.result.progress;\n } else if (pState === 'WAIT_FINISH') {\n $('loadingNum').innerHTML = 99;\n } else if (pState === 'DONE') {\n $('loadingNum').innerHTML = 100;\n location.reload();\n return;\n }\n } else {\n errorCount++;\n }\n\n if (errorCount > 5) {\n alert('인코딩 진행정보를 받아오는데 실패하였습니다.\\n잠시후에 다시 시도해주세요.');\n return;\n }\n\n timer = setTimeout(function() {\n dataloader.getOutputProcessingInfo(env.clipId);\n clearTimeout(timer);\n }, callDelay);\n });\n sandbox.on('check:auth', function(data) {\n var host = window.location.protocol + '//' + window.location.host;\n var returnUrl = host + '/embed/player/playerpopupcallback';\n var specs =\n 'fullscreen=no, width=800, height=800, menubar=no, ' +\n 'scrollbars=no, status=no, titlebar=no, resizable=yes';\n\n var url = data.result.additionalInfo && data.result.additionalInfo.url;\n\n // 인증이 안된경우 status code가 401로 내려오기때문에 임시로 error부분에서 인증관련 로직추가.\n // todo 웹에 맞는 로그인 프로세스로 수정해야함.\n if (data.status === 'success') {\n if (url !== '') {\n url = url + '&service=kakao_tv&';\n }\n } else {\n var errorCode = data.result.code;\n\n if (errorCode === 'NeedLogin') {\n debug.warn('로그인이 필요합니다.', data.result);\n\n if (url !== '') {\n url = url + '?';\n }\n } else {\n debug.warn('본인인증이 필요합니다.', data.result);\n\n if (url !== '') {\n url = url + '&service=kakao_tv&';\n }\n }\n }\n\n if (ua.platform === 'pc') {\n url = url + 'continue=' + encodeURIComponent(returnUrl);\n window.open(url, '_blank', specs);\n } else {\n url = url + 'continue=' + encodeURIComponent(env.referer);\n top.location.href = url;\n }\n });\n }\n };\n\n return {\n init: function(player, sandbox) {\n listener.viewEvent();\n listener.customEvent(sandbox);\n },\n showError: function(statusCode, info, option) {\n showError(statusCode, info, option);\n },\n hideError: function() {\n hideError();\n },\n setTemplate: function(status, info, target) {\n setTemplate(status, info, target);\n },\n addStyle: function(cname) {\n dt.classList.add(EL.NOTICE_INFO, cname);\n },\n getErrorStatus: function() {\n return error.status;\n },\n checkValidation: checkValidation,\n getStatusByCode: getStatusByCode,\n showAgeLimit: function() {\n showAgeLimit();\n }\n };\n })();\n\n exports.addModule('view.error', new Error());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var state = exports.loadModule('controller.state');\n var pctTracker = exports.loadModule('pct.tracker');\n\n var Action;\n Action = (function() {\n var $$ = dt.$$;\n var event = dt.event;\n var helpers = exports.helpers;\n var playerTemplate = exports.template;\n var ua = exports.ua;\n var actionData = null;\n\n var EL = {\n ACTION_CONTAINER: $$('.bizmeta_control')[0]\n };\n\n var action = {\n button: {\n template: playerTemplate.action_button,\n trackingUrl: '',\n set: function(action) {\n if (EL.ACTION_CONTAINER) {\n EL.ACTION_CONTAINER.innerHTML = this.template.render({\n actionUrl: action.actionButton.landingUri,\n actionText: action.actionButton.buttonText\n });\n this.trackingUrl = action.actionButton.clickTracking;\n state.hasAction = true;\n }\n actionData = action;\n },\n show: function() {\n if (EL.ACTION_CONTAINER) {\n dt.classList.remove(EL.ACTION_CONTAINER, 'hide');\n }\n },\n hide: function() {\n if (EL.ACTION_CONTAINER) {\n dt.classList.add(EL.ACTION_CONTAINER, 'hide');\n }\n }\n }\n };\n\n var listener = {\n viewEvent: function() {\n event.delegate(EL.ACTION_CONTAINER, '.link_go', 'click', function(e) {\n event.stopPropagation(e);\n event.preventDefault(e);\n\n var landingUri = actionData.actionButton.landingUri;\n\n if (ua.platform === 'pc') {\n window.open(landingUri, '_blank');\n } else {\n top.location.href = landingUri;\n }\n\n helpers.http.sendBeacon(action.button.trackingUrl);\n pctTracker.track('action_button', actionData.actionButton.buttonText);\n });\n }\n };\n\n function Action() {}\n\n Action.prototype.init = function() {\n listener.viewEvent();\n };\n\n Action.prototype.setButton = function(actionData) {\n action.button.set(actionData);\n };\n\n Action.prototype.showButton = function() {\n action.button.show();\n };\n\n Action.prototype.hideButton = function() {\n action.button.hide();\n };\n\n return Action;\n })();\n\n exports.addModule('view.action', new Action());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var shaka = exports.loadModule('player.shaka');\n var player = exports.loadModule('player.adapter');\n var queue = exports.loadModule('playlist.queue');\n var state = exports.loadModule('controller.state');\n var a11y = exports.loadModule('etc.a11y');\n var websocket = exports.loadModule('etc.websocket');\n var contextMenu = exports.loadModule('view.contextmenu');\n var vastTracker = exports.loadModule('vast.tracker');\n var pctTracker = exports.loadModule('pct.tracker');\n var qoeTracker = exports.loadModule('qoe.tracker');\n var dataLoader = exports.loadModule('playlist.dataloader');\n var analytics = exports.loadModule('view.analytics');\n var error = exports.loadModule('view.error');\n var playerTemplate = exports.template;\n\n var Inline;\n\n Inline = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n\n var PHASE = constants.PHASE[env.phase.toUpperCase()];\n var ERROR_STATUS = constants.ERROR.STATUS;\n var CONFIRM_STATUS = constants.CONFIRM.STATUS;\n var QOE_EVENTS = constants.QOE.EVENT;\n\n var orien = new dt.Orientation();\n\n var NEXT_VIDEO_SHOW_DURATION = 5;\n var nonLinearAdTimer = null;\n var nonLinearAdDuration = 0;\n var liveStatTimeout = null;\n\n var fullscreenHelper;\n\n var MUTE_STATE_KEY = constants.STORAGE.MUTE;\n var CHART_KEY = constants.STORAGE.CHART;\n\n var FULL_SCREEN_API = {\n REQUEST: 'request',\n CANCEL: 'cancel'\n };\n\n var CNAME = {\n PLAYER_PLAY: 'player_play',\n PLAYER_PAUSE: 'player_pause',\n PLAYER_REPLAY: 'player_replay',\n BUTTON_SETTING: 'btn_setup',\n BUTTON_PROFILE: 'profile',\n BUTTON_SUBTITLE: 'subtitle'\n };\n\n var EL = {\n PLAYER: $('player'),\n PLAYER_FRAME: $('playerFrame'),\n PLAYER_CONTAINER: $('playerContainer'),\n VIDEO_CONTAINER: $('videoContainer'),\n PLAYER_CONTROLLER_TOGGLE_BUTTON: $$('#videoContainer button')[0],\n VIDEO_OVERLAY: $('videoOverlay'),\n AD_CONTROLLER: $('adController'),\n AD_COUNT: $('adCount'),\n AD_TIME: $('adTime'),\n AD_TEXT: $('adSkipOffsetText'),\n AD_PLAY_PAUSE_BUTTON_WRAP: $('adPlayPauseBtnWrap'),\n AD_PLAY: $('adPlayBtn'),\n AD_PAUSE: $('adPauseBtn'),\n AD_LINK: $('adLinkBtn'),\n AD_SKIP: $('adSkipBtn'),\n AD_ADVERTISER: $('advertiser'),\n AD_PLAY_PROGRESS: $('adProgress'),\n AD_LINEAR_CONTAINER: $('linear'),\n AD_LINEAR_BANNER: $('linearBanner'),\n AD_LINEAR_BANNER_TEXT: $$('#linearBanner .banner_text')[0],\n AD_NONLINEAR_CONTAINER: $('nonLinear'),\n AD_NONLINEAR_TEXT_BANNER_INFO: $$('#nonLinear .link_adinfo')[0],\n AD_NONLINEAR_TEXT_BANNER_CLOSE: $$('#nonLinear .close_textad')[0],\n AD_NONLINEAR_TEXT_BANNER_BOX: $$('#nonLinear .text_adbox')[0],\n AD_NONLINEAR_TEXT_BANNER: $$('#nonLinear .link_textad')[0],\n AD_NONLINEAR_TEXT_BANNER_TITLE: $$('#nonLinear .link_textad strong')[0],\n AD_NONLINEAR_IMAGE_BANNER_BOX: $$('#nonLinear .section_banner')[0],\n AD_NONLINEAR_IMAGE_BANNER_CLOSE: $$('#nonLinear .close_imagead')[0],\n AD_NONLINEAR_IMAGE_BANNER: $$('#nonLinear .link_imagead')[0],\n AD_NONLINEAR_IMAGE_BANNER_IMG: $$('#nonLinear .thumb_img')[0],\n AD_NONLINEAR_POINT: $('nonLinearPoint'),\n AD_MUTE_BUTTON: $$('#adController .btn_mute')[0],\n AD_UNMUTE_BUTTON: $$('#adController .btn_muteoff')[0],\n AD_MUTE_BUTTON_WRAP: $('adMuteBtnWrap'),\n AD_NOTI: $('adNoti'),\n MUTE_BUTTON: $$('#controller .btn_mute')[0],\n UNMUTE_BUTTON: $$('#controller .btn_muteoff')[0],\n MUTE_BUTTON_WRAP: $('muteBtnWrap'),\n PLAYER_CONTROLLER_CONTAINER: $('controllerContainer'),\n PLAYER_CONTROLLER: $('controller'),\n PLAYER_CONTROLLER_HEAD: $$('#controller .player_head')[0],\n PLAYER_CONTROLLER_BODY: $$('#controller .player_body')[0],\n PLAYER_CONTROLLER_FOOT: $$('#controller .player_foot')[0],\n PLAYER_FUNCTION: $$('.player_function')[0],\n PLAYER_TITLE: $$('#controller .tit_player')[0],\n TITLE_LINK: $$('#controller .link_title')[0],\n LIVE_REPLAY: $$('#controller .live_re')[0],\n LIVE_FULL: $$('#controller .live_full')[0],\n AGE_LIMIT_ICON_HEAD: $('headTough'),\n AGE_LIMIT_ICON_VIEWER: $('viewerTough'),\n SECRET_ICON_VIEWER: $('viewerSecret'),\n LIVE_ICON: $$('#controller .ico_live')[0],\n COVER_LIVE_ICON: $$('#customCover .ico_live')[0],\n COVER_TITLE: $$('#customCover .tit_player')[0],\n COVER_PLAY_BUTTON_WRAP: $('coverPlayBtnWrap'),\n VIEWER_BOX: $$('#controller .box_viewer')[0],\n VIEWER_COUNT: $('viewerCount'),\n PLAYER_BLIND: $('playerBlind'),\n PLAYER_NOTIFICATION: $('notification'),\n PLAY_BUTTON: $$('.' + CNAME.PLAYER_PLAY)[0],\n PAUSE_BUTTON: $$('.' + CNAME.PLAYER_PAUSE)[0],\n REPLAY_BUTTON: $$('.' + CNAME.PLAYER_REPLAY)[0],\n PLAY_PAUSE_BUTTON_WRAP: $('playPauseBtnWrap'),\n SEEKING_BUTTON_WRAP: $('seekingBtnWrap'),\n SOUND_CONTROL: $$('.sound_control')[0],\n VOLUME_PANEL: $$('.vol_panel')[0],\n SETTING_BUTTON: $$('.btn_setup')[0],\n SETUP_BUTTON: $$('.' + CNAME.BUTTON_SETTING)[0],\n TIME_SEEK: $('timeSeek'),\n FULLSCREEN_BUTTON: $('fullscreenBtn'),\n PROGRESSBAR: $('progress'),\n PROGRESSBAR_TOTALBAR: $$('#progress .total_bar')[0],\n PROGRESS_POINT: $('pointProgress'),\n LOAD_PROGRESS: $('loadProgress'),\n PLAY_PROGRESS: $('playProgress'),\n TIME_POINT: $$('.check_time')[0],\n DURATION: $('duration'),\n CURRENT_TIME: $('currentTime'),\n SPINNER_CONTAINER: $('spinnerContainer'),\n ERROR_CONTAINER: $('errorView'),\n ERROR_MESSAGE: $('errorMessage'),\n PROFILE_BUTTON: $$('.profile')[0],\n APPLINK_BUTTON: $$('#controller .btn_liveHD')[0],\n STILL_CONTAINER: $$('.thumb_section')[0],\n STILL_VIDEO: $('stillVideo'),\n STILL_VIDEO_TIME: $$('.txt_time')[0],\n SEEK_BAR: $$('.thumb_bar')[0],\n EXTENSTION_CONTAINER: $$('#controller .extensions')[0],\n DIMMED_LAYER: $$('#controller .dimmed_layer')[0],\n PLAY_TIME_CONTAINER: $$('.play_time')[0],\n CHART_BUTTON: $$('.btn_chart')[0],\n ACTION_CONTAINER: $$('.bizmeta_control')[0],\n NUM_VIEWER: $$('.num_viewer')[0],\n RATING_CONTAINER: $('ratingContainer'),\n TVOD_CONTAINER: $$('.tvod_container')[0],\n TVOD_MESSAGE: $$('.tvod_message')[0],\n TVOD_LINK: $$('.tvod_link')[0]\n };\n\n var VOLUME_STATE_KEY = constants.STORAGE.VOLUME;\n var VOLUME_DEFUALT = 0.5;\n\n var profileTemplate = {\n profile_text: playerTemplate.mobile_profile_text,\n supHD: playerTemplate.superscript_hd,\n sup4K: playerTemplate.superscript_4k\n };\n\n var adTemplate = {\n notiText: playerTemplate.ad_noti_text\n };\n\n var defaultUI = {\n control: {\n el: EL.VIDEO_CONTAINER,\n show: function() {\n dt.classList.remove(this.el, 'hide_default_control');\n dt.classList.add(EL.PLAYER_CONTROLLER_CONTAINER, 'hide');\n },\n hide: function() {\n dt.classList.add(this.el, 'hide_default_control');\n dt.classList.remove(EL.PLAYER_CONTROLLER_CONTAINER, 'hide');\n }\n },\n video: {\n hideCursor: function() {\n dt.classList.add(player.videoElement, 'hide_cursor');\n },\n showCursor: function() {\n dt.classList.remove(player.videoElement, 'hide_cursor');\n }\n }\n };\n\n var customUI = {\n setSize: function() {\n var body = document.documentElement || document.body;\n EL.PLAYER_CONTAINER.style.width = body.clientWidth + 'px';\n EL.PLAYER_CONTAINER.style.height = body.clientHeight + 'px';\n },\n reSize: function() {\n var videoHeight = player.videoElement.videoHeight;\n var videoWidth = player.videoElement.videoWidth;\n var videoRatio = videoWidth / videoHeight;\n var body = document.documentElement || document.body;\n var width = body.clientWidth;\n var height = body.clientHeight;\n var ratio = width / height;\n\n if (ratio < 1.77) {\n height = (width * 9) / 16;\n } else {\n width = (height * 16) / 9;\n }\n\n if (videoRatio <= 1) {\n EL.PLAYER_CONTAINER.style.width = '100%';\n EL.PLAYER_CONTAINER.style.height = '100%';\n EL.PLAYER_CONTAINER.style.top = '';\n EL.PLAYER_CONTAINER.style.left = '';\n } else {\n EL.PLAYER_CONTAINER.style.width = width + 'px';\n EL.PLAYER_CONTAINER.style.height = height + 'px';\n\n this.relocate(width, height);\n }\n\n if (env.isPrivateIp) {\n analytics.reSize();\n }\n },\n relocate: function(width, height) {\n EL.PLAYER_CONTAINER.style.top = 'calc(50% - ' + height / 2 + 'px)';\n EL.PLAYER_CONTAINER.style.left = 'calc(50% - ' + width / 2 + 'px)';\n },\n blind: {\n el: EL.PLAYER_BLIND,\n show: function() {\n dt.classList.remove(this.el, 'hide');\n },\n hide: function() {\n dt.classList.add(this.el, 'hide');\n }\n },\n notification: {\n el: EL.PLAYER_NOTIFICATION,\n timer: null,\n show: function(message, callback) {\n var self = this;\n\n dt.classList.remove(this.el, 'hide');\n this.el.innerHTML = message;\n\n if (this.timer) {\n clearTimeout(this.timer);\n }\n\n this.timer = setTimeout(function() {\n self.hide();\n self.timer = null;\n\n if (callback && typeof callback === 'function') {\n callback();\n }\n }, 1500);\n },\n hide: function() {\n this.el.innerHTML = '';\n dt.classList.add(this.el, 'hide');\n }\n },\n overlay: {\n el: EL.VIDEO_OVERLAY,\n show: function() {\n dt.classList.remove(this.el, 'hidden');\n dt.classList.add(this.el, 'visible');\n },\n hide: function() {\n if (dt.classList.has(this.el, 'visible')) {\n dt.classList.remove(this.el, 'visible');\n dt.classList.add(this.el, 'hidden');\n }\n }\n },\n control: {\n el: EL.PLAYER_CONTROLLER,\n controlTimer: null,\n showStatus: false,\n clearTimer: function() {\n if (this.controlTimer) {\n clearTimeout(this.controlTimer);\n }\n },\n show: function(isfreeze) {\n var self = this;\n\n if (state.isShowError || !env.controls) {\n return;\n }\n\n if (ua.platform !== 'pc') {\n exports.queue.emit('hide:rating');\n }\n\n this.showStatus = true;\n state.customControlActivated = true;\n\n if (dt.classList.has(this.el, 'hide')) {\n dt.classList.remove(this.el, 'hide');\n }\n\n dt.classList.remove(EL.PLAYER, 'hide-custom-control');\n dt.classList.add(EL.PLAYER, 'show-custom-control');\n\n this.clearTimer();\n\n if (isfreeze) {\n return;\n }\n\n this.controlTimer = setTimeout(function() {\n if (!state.isSettingMenuOpened && !env.keepShowControl) {\n self.hide();\n self.hideSeekTime();\n }\n self.controlTimer = null;\n }, 1500);\n },\n hide: function() {\n this.showStatus = false;\n state.customControlActivated = false;\n\n dt.classList.remove(EL.PLAYER, 'show-custom-control');\n dt.classList.add(EL.PLAYER, 'hide-custom-control');\n\n exports.queue.emit('hide:customUI');\n\n if (ua.platform !== 'pc' && player.getCurrentTime() > 0 && state.isFirstPlay) {\n exports.queue.emit('show:rating');\n }\n },\n toggleUI: function() {\n if (this.showStatus) {\n this.hide();\n } else {\n this.show(true);\n }\n },\n showPlayPause: function() {\n if (EL.PLAY_PAUSE_BUTTON_WRAP) {\n dt.classList.remove(EL.PLAY_PAUSE_BUTTON_WRAP, 'hide');\n }\n },\n hidePlayPause: function() {\n if (EL.PLAY_PAUSE_BUTTON_WRAP) {\n dt.classList.add(EL.PLAY_PAUSE_BUTTON_WRAP, 'hide');\n }\n },\n showSeeking: function() {\n if (EL.SEEKING_BUTTON_WRAP) {\n dt.classList.remove(EL.SEEKING_BUTTON_WRAP, 'hide');\n }\n },\n hideSeeking: function() {\n if (EL.SEEKING_BUTTON_WRAP) {\n dt.classList.add(EL.SEEKING_BUTTON_WRAP, 'hide');\n }\n },\n hideAdPlayPause: function() {\n if (EL.AD_PLAY_PAUSE_BUTTON_WRAP) {\n dt.classList.add(EL.AD_PLAY_PAUSE_BUTTON_WRAP, 'hide');\n }\n },\n hideCoverPlay: function() {\n if (EL.COVER_PLAY_BUTTON_WRAP) {\n dt.classList.add(EL.COVER_PLAY_BUTTON_WRAP, 'hide');\n }\n },\n showSeekTime: function() {\n if (EL.TIME_SEEK) {\n dt.classList.remove(EL.TIME_SEEK, 'hide');\n }\n },\n hideSeekTime: function() {\n if (EL.TIME_SEEK) {\n dt.classList.add(EL.TIME_SEEK, 'hide');\n }\n },\n setDuration: function(duration) {\n if (EL.DURATION) {\n EL.DURATION.innerHTML = helpers.string.delimitTimes(duration);\n }\n },\n setTitle: function(data) {\n if (data.title) {\n EL.TITLE_LINK.innerHTML = helpers.string.escapeHtml(data.title);\n }\n },\n showTitle: function() {\n if (EL.PLAYER_TITLE) {\n dt.classList.remove(EL.PLAYER_TITLE, 'hide');\n }\n },\n hideTitle: function() {\n if (EL.PLAYER_TITLE) {\n dt.classList.add(EL.PLAYER_TITLE, 'hide');\n }\n },\n showReplay: function() {\n if (EL.LIVE_REPLAY) {\n dt.classList.remove(EL.LIVE_REPLAY, 'hide');\n }\n },\n hideReplay: function() {\n if (EL.LIVE_REPLAY) {\n dt.classList.add(EL.LIVE_REPLAY, 'hide');\n }\n },\n showFull: function() {\n if (EL.LIVE_FULL) {\n dt.classList.remove(EL.LIVE_FULL, 'hide');\n }\n },\n hideFull: function() {\n if (EL.LIVE_FULL) {\n dt.classList.add(EL.LIVE_FULL, 'hide');\n }\n },\n setViewerCount: function(count) {\n if (!EL.VIEWER_COUNT) {\n return;\n }\n\n if (!count) {\n this.hideViewerBox();\n return;\n }\n\n if (!isNaN(count)) {\n count = helpers.string.delimitNumbers(count);\n }\n\n this.showViewerBox();\n EL.VIEWER_COUNT.innerHTML = count;\n },\n setAgeLimit: function(age) {\n var isShownTitle = env.popup || (!env.isInternal && env.showInfo);\n if (age === 'AGE_19') {\n dt.classList.remove(isShownTitle ? EL.AGE_LIMIT_ICON_HEAD : EL.AGE_LIMIT_ICON_VIEWER, 'hide');\n }\n },\n setSecret: function(needPassword) {\n if (EL.SECRET_ICON_VIEWER) {\n if (needPassword) {\n dt.classList.remove(EL.SECRET_ICON_VIEWER, 'hide');\n } else {\n dt.classList.add(EL.SECRET_ICON_VIEWER, 'hide');\n }\n }\n },\n setCurrentTime: function(currentTime, duration) {\n var rate = Math.floor((currentTime / duration) * 100);\n\n if (rate > 100 || rate < 0 || isNaN(currentTime)) {\n return;\n }\n\n if (EL.CURRENT_TIME) {\n EL.CURRENT_TIME.innerHTML = helpers.string.delimitTimes(currentTime);\n }\n\n if (EL.TIME_SEEK) {\n EL.TIME_SEEK.innerHTML = helpers.string.delimitTimes(currentTime);\n }\n },\n showAppLinkButton: function() {\n if (EL.APPLINK_BUTTON) {\n dt.classList.remove(EL.APPLINK_BUTTON, 'hide');\n }\n },\n hideAppLinkButton: function() {\n if (EL.APPLINK_BUTTON) {\n dt.classList.add(EL.APPLINK_BUTTON, 'hide');\n }\n },\n hideProfile: function() {\n if (EL.PROFILE_BUTTON && EL.PROFILE_BUTTON.parentElement) {\n dt.classList.add(EL.PROFILE_BUTTON.parentElement, 'hide');\n }\n },\n showProfile: function() {\n if (EL.PROFILE_BUTTON && EL.PROFILE_BUTTON.parentElement) {\n dt.classList.remove(EL.PROFILE_BUTTON.parentElement, 'hide');\n }\n },\n toggleMute: function(muteOn) {\n var muteButton = EL.MUTE_BUTTON;\n var unMuteButton = EL.UNMUTE_BUTTON;\n\n if (muteOn) {\n dt.classList.remove(muteButton, 'hide');\n dt.classList.add(unMuteButton, 'hide');\n } else {\n dt.classList.add(muteButton, 'hide');\n dt.classList.remove(unMuteButton, 'hide');\n }\n },\n toggleAdMute: function(muteOn) {\n var muteButton = EL.AD_MUTE_BUTTON;\n var unMuteButton = EL.AD_UNMUTE_BUTTON;\n\n if (muteOn) {\n dt.classList.remove(muteButton, 'hide');\n dt.classList.add(unMuteButton, 'hide');\n } else {\n dt.classList.add(muteButton, 'hide');\n dt.classList.remove(unMuteButton, 'hide');\n }\n },\n showExtension: function() {\n if (EL.EXTENSTION_CONTAINER) {\n dt.classList.remove(EL.EXTENSTION_CONTAINER, 'hide');\n }\n },\n hideExtension: function() {\n if (EL.EXTENSTION_CONTAINER) {\n dt.classList.add(EL.EXTENSTION_CONTAINER, 'hide');\n }\n },\n showDimmedLayer: function() {\n if (EL.DIMMED_LAYER) {\n dt.classList.remove(EL.DIMMED_LAYER, 'hide');\n }\n },\n hideDimmedLayer: function() {\n if (EL.DIMMED_LAYER) {\n dt.classList.add(EL.DIMMED_LAYER, 'hide');\n }\n },\n hideMute: function() {\n if (EL.MUTE_BUTTON_WRAP) {\n dt.classList.add(EL.MUTE_BUTTON_WRAP, 'hide');\n }\n },\n hideAdMute: function() {\n if (EL.AD_MUTE_BUTTON_WRAP) {\n dt.classList.add(EL.AD_MUTE_BUTTON_WRAP, 'hide');\n }\n },\n hideLiveIcon: function() {\n if (EL.LIVE_ICON) {\n dt.classList.add(EL.LIVE_ICON, 'hide');\n }\n },\n hideCoverLiveIcon: function() {\n if (EL.COVER_LIVE_ICON) {\n dt.classList.add(EL.COVER_LIVE_ICON, 'hide');\n }\n },\n hideCoverTitle: function() {\n if (EL.COVER_TITLE) {\n dt.classList.add(EL.COVER_TITLE, 'hide');\n }\n },\n showViewerBox: function() {\n if (!env.showViewer) {\n return;\n }\n\n if (EL.VIEWER_BOX) {\n dt.classList.remove(EL.VIEWER_BOX, 'hide');\n }\n\n if (EL.NUM_VIEWER) {\n dt.classList.remove(EL.NUM_VIEWER, 'info_none');\n }\n },\n hideViewerBox: function() {\n if (EL.VIEWER_BOX) {\n dt.classList.add(EL.VIEWER_BOX, 'hide');\n }\n\n if (EL.NUM_VIEWER) {\n dt.classList.add(EL.NUM_VIEWER, 'info_none');\n }\n },\n hideViewerBackground: function() {\n if (EL.VIEWER_BOX) {\n dt.classList.add(EL.VIEWER_BOX, 'hide_liveicon');\n }\n },\n showChartButton: function() {\n if (EL.CHART_BUTTON) {\n dt.classList.remove(EL.CHART_BUTTON, 'hide');\n }\n },\n hideChartButton: function() {\n if (EL.CHART_BUTTON) {\n dt.classList.add(EL.CHART_BUTTON, 'hide');\n }\n }\n },\n fullscreen: {\n el: EL.FULLSCREEN_BUTTON,\n show: function() {\n dt.classList.remove(EL.FULLSCREEN_BUTTON, 'hide');\n },\n hide: function() {\n dt.classList.add(EL.FULLSCREEN_BUTTON, 'hide');\n },\n toggle: function(isFullScreen) {\n var nextElement = this.el.nextElementSibling;\n\n if (isFullScreen) {\n dt.classList.add(EL.PLAYER, 'fullscreen');\n this.el.setAttribute('aria-label', '기본화면');\n\n if (nextElement && nextElement.className === 'box_tooltip') {\n nextElement.innerHTML = '기본화면';\n }\n } else {\n dt.classList.remove(EL.PLAYER, 'fullscreen');\n this.el.setAttribute('aria-label', '전체화면');\n\n if (nextElement && nextElement.className === 'box_tooltip') {\n nextElement.innerHTML = '전체화면';\n }\n }\n }\n },\n progress: {\n el: EL.PROGRESSBAR,\n show: function() {\n if (EL.PROGRESSBAR) {\n dt.classList.remove(EL.PROGRESSBAR, 'hide');\n }\n },\n hide: function() {\n if (EL.PROGRESSBAR) {\n dt.classList.add(EL.PROGRESSBAR, 'hide');\n }\n },\n on: function() {\n if (EL.PROGRESSBAR) {\n dt.classList.add(EL.PROGRESSBAR, 'on');\n }\n },\n off: function() {\n if (EL.PROGRESSBAR) {\n dt.classList.remove(EL.PROGRESSBAR, 'on');\n }\n },\n updateLoad: function(loadEndPercentage) {\n var transform = helpers.polyfill.getProps('transform');\n var sx = 0;\n if (EL.LOAD_PROGRESS && loadEndPercentage > 0) {\n sx = loadEndPercentage.toFixed(3);\n EL.LOAD_PROGRESS.style[transform] = 'scaleX(' + sx + ')';\n }\n },\n updatePlay: function(percentage) {\n if (percentage > 100) {\n return;\n }\n\n if (EL.PLAY_PROGRESS) {\n EL.PLAY_PROGRESS.style.width = percentage + '%';\n }\n }\n },\n ad: {\n el: EL.AD_CONTROLLER,\n timer: null,\n show: function() {\n dt.classList.remove(this.el, 'hide');\n },\n hide: function() {\n dt.classList.add(this.el, 'hide');\n },\n setup: function() {\n var video = queue.front;\n var staticResource = null;\n var adnotiText = '';\n var sourceText = '';\n var optouthide = true;\n var optoutImageUrl = '';\n var optoutClickUrl = '';\n\n if (EL.AD_LINK) {\n if (video.clickThrough && video.clickThrough['@_uri']) {\n EL.AD_LINK.href = video.clickThrough['@_uri'];\n } else {\n this.hideLink();\n }\n }\n\n if (video.timeOffset === 'end') {\n if (video.extension && video.extension.length > 0) {\n var textAd = video.extension[0].customObject && video.extension[0].customObject.TextAd;\n if (textAd) {\n this.setLinearBanner(textAd.Click, textAd.Title);\n }\n }\n }\n\n if (video.icon) {\n video.icon.forEach(function(v) {\n staticResource = v.staticResource;\n\n if (v['@_program'] === 'source') {\n if (staticResource) {\n sourceText = staticResource[0]['@_uri'] || '';\n adnotiText = helpers.string.replaceLinefeed(sourceText);\n }\n } else if (v['@_program'] === 'optout') {\n var clickUrl = v.iconClicks && v.iconClicks.iconClickThrough;\n if (staticResource && clickUrl) {\n optoutImageUrl = staticResource[0]['@_uri'] || '';\n optoutClickUrl = clickUrl['@_uri'] || '';\n optouthide = false;\n }\n }\n });\n }\n\n if (EL.AD_NOTI) {\n EL.AD_NOTI.innerHTML = adnotiText\n ? adTemplate.notiText.render({\n txt_single: adnotiText.indexOf('
    ') === -1,\n notiText: adnotiText,\n optouthide: optouthide,\n optoutImage: optoutImageUrl,\n optoutClickUrl: optoutClickUrl\n })\n : '';\n }\n },\n setupMidTextAd: function(click, title) {\n this.hideCount();\n this.hideLink();\n this.hideSkip();\n this.setNonLinearTextBanner(click, title);\n this.hideNonLinearContainer();\n },\n setupMidImageAd: function(click, banner) {\n this.setNonLinearImageBanner(click, banner);\n },\n end: function() {\n this.hideCount();\n this.hideSkip();\n this.hideLinearBanner();\n },\n reset: function() {\n var video = queue.front;\n var duration = player.getDurationRound();\n var skipOffset = video.skipOffset && video.skipOffset < duration ? video.skipOffset : duration;\n var skipCheck = skipOffset - duration !== 0;\n\n this.updateTime(skipOffset, skipCheck);\n\n if (video.timeOffset === 'end') {\n this.hideCount();\n this.hideLink();\n this.hideSkip();\n\n var creativeExtension = video.extension;\n if (creativeExtension && creativeExtension.length > 0) {\n if (creativeExtension[0].customObject && creativeExtension[0].customObject.TextAd) {\n this.showLinearBanner();\n }\n }\n } else {\n this.showCount();\n this.showLink();\n this.hideSkip();\n this.hideLinearBanner();\n }\n },\n showSkip: function() {\n if (EL.AD_SKIP) {\n dt.classList.remove(EL.AD_SKIP, 'hide');\n }\n },\n hideSkip: function() {\n if (EL.AD_SKIP) {\n dt.classList.add(EL.AD_SKIP, 'hide');\n }\n },\n showLink: function() {\n if (EL.AD_LINK) {\n dt.classList.remove(EL.AD_LINK, 'hide');\n }\n },\n hideLink: function() {\n if (EL.AD_LINK) {\n dt.classList.add(EL.AD_LINK, 'hide');\n }\n },\n showCount: function() {\n if (EL.AD_COUNT) {\n dt.classList.remove(EL.AD_COUNT, 'hide');\n }\n },\n hideCount: function() {\n if (EL.AD_COUNT) {\n dt.classList.add(EL.AD_COUNT, 'hide');\n }\n },\n setLinearBanner: function(url, title) {\n if (EL.AD_LINEAR_BANNER && url) {\n EL.AD_LINEAR_BANNER.href = url;\n }\n\n if (EL.AD_LINEAR_BANNER_TEXT && title && title !== '') {\n EL.AD_LINEAR_BANNER_TEXT.innerHTML = title;\n }\n },\n showLinearBanner: function() {\n if (EL.AD_LINEAR_BANNER) {\n dt.classList.remove(EL.AD_LINEAR_BANNER, 'hide');\n }\n },\n hideLinearBanner: function() {\n if (EL.AD_LINEAR_BANNER) {\n dt.classList.add(EL.AD_LINEAR_BANNER, 'hide');\n }\n },\n showLinearContainer: function() {\n if (EL.AD_LINEAR_CONTAINER) {\n dt.classList.remove(EL.AD_LINEAR_CONTAINER, 'hide');\n }\n },\n hideLinearContainer: function() {\n if (EL.AD_LINEAR_CONTAINER) {\n dt.classList.add(EL.AD_LINEAR_CONTAINER, 'hide');\n }\n },\n showNonLinearContainer: function() {\n if (EL.AD_NONLINEAR_CONTAINER) {\n dt.classList.remove(EL.AD_NONLINEAR_CONTAINER, 'hide');\n }\n },\n hideNonLinearContainer: function() {\n if (EL.AD_NONLINEAR_CONTAINER) {\n dt.classList.add(EL.AD_NONLINEAR_CONTAINER, 'hide');\n }\n },\n setNonLinearContainerStyle: function(adType) {\n if (EL.AD_NONLINEAR_CONTAINER) {\n EL.AD_NONLINEAR_CONTAINER.className = adType;\n }\n },\n setNonLinearTextBanner: function(url, title) {\n this.setNonLinearContainerStyle('text');\n\n if (EL.AD_NONLINEAR_TEXT_BANNER && EL.AD_NONLINEAR_TEXT_BANNER !== '') {\n EL.AD_NONLINEAR_TEXT_BANNER.href = url;\n }\n\n if (EL.AD_NONLINEAR_TEXT_BANNER_TITLE) {\n EL.AD_NONLINEAR_TEXT_BANNER_TITLE.innerHTML = title;\n }\n },\n setNonLinearImageBanner: function(url, imgSrc) {\n this.setNonLinearContainerStyle('image');\n\n if (EL.AD_NONLINEAR_IMAGE_BANNER && EL.AD_NONLINEAR_IMAGE_BANNER !== '') {\n EL.AD_NONLINEAR_IMAGE_BANNER.href = url;\n }\n\n if (EL.AD_NONLINEAR_IMAGE_BANNER_IMG) {\n EL.AD_NONLINEAR_IMAGE_BANNER_IMG.src = imgSrc;\n }\n },\n setNonLinearProgressPoint: function(duration, displayPer) {\n if (env.debugMode) {\n var midAdDuration = duration > -1 ? duration : 5;\n var pointWidth = (midAdDuration * 100) / player.getDurationRound();\n\n if (EL.AD_NONLINEAR_POINT) {\n EL.AD_NONLINEAR_POINT.style.width = pointWidth.toFixed(2) + '%';\n if (!isNaN(displayPer) && displayPer > 0) {\n EL.AD_NONLINEAR_POINT.style.left = displayPer + '%';\n }\n }\n }\n },\n setMidrollPoint: function(index, isStarted, timeOffset) {\n var pointLeft = (timeOffset * 100) / player.getDurationRound();\n var midrollPointNode = document.getElementById('midrollPoint' + index);\n\n if (EL.PROGRESSBAR_TOTALBAR) {\n if (!isStarted) {\n if (!midrollPointNode) {\n midrollPointNode = document.createElement('div');\n midrollPointNode.id = 'midrollPoint' + index;\n dt.classList.add(midrollPointNode, 'midroll_point');\n EL.PROGRESSBAR_TOTALBAR.appendChild(midrollPointNode);\n }\n midrollPointNode.style.left = pointLeft + '%';\n dt.classList.remove(midrollPointNode, 'hide');\n if (env.debugMode) {\n dt.classList.remove(midrollPointNode, 'started');\n }\n } else if (isStarted) {\n midrollPointNode = document.getElementById('midrollPoint' + index);\n\n if (env.debugMode) {\n dt.classList.add(midrollPointNode, 'started');\n } else {\n dt.classList.add(midrollPointNode, 'hide');\n }\n }\n }\n },\n removeMidrollPoint: function() {\n var maxMidrollIndex = 30;\n var midrollPointNode = null;\n for (var i = 0; i < maxMidrollIndex; i++) {\n midrollPointNode = document.getElementById('midrollPoint' + i);\n if (EL.PROGRESSBAR_TOTALBAR && midrollPointNode) {\n EL.PROGRESSBAR_TOTALBAR.removeChild(midrollPointNode);\n } else {\n break;\n }\n }\n },\n showNonLinearAdTextBox: function() {\n if (EL.AD_NONLINEAR_TEXT_BANNER_BOX) {\n dt.classList.remove(EL.AD_NONLINEAR_TEXT_BANNER_BOX, 'hide');\n }\n },\n hideNonLinearAdText: function() {\n if (EL.AD_NONLINEAR_TEXT_BANNER_BOX) {\n dt.classList.add(EL.AD_NONLINEAR_TEXT_BANNER_BOX, 'hide');\n }\n },\n showNonLinearAdTextInfo: function() {\n if (EL.AD_NONLINEAR_TEXT_BANNER_INFO) {\n dt.classList.remove(EL.AD_NONLINEAR_TEXT_BANNER_INFO, 'hide');\n }\n },\n hideNonLinearAdTextInfo: function() {\n if (EL.AD_NONLINEAR_TEXT_BANNER_INFO) {\n dt.classList.add(EL.AD_NONLINEAR_TEXT_BANNER_INFO, 'hide');\n }\n },\n showNonLinearAdImageBox: function() {\n if (EL.AD_NONLINEAR_IMAGE_BANNER_BOX) {\n dt.classList.remove(EL.AD_NONLINEAR_IMAGE_BANNER_BOX, 'hide');\n }\n },\n hideNonLinearAdImage: function() {\n if (EL.AD_NONLINEAR_IMAGE_BANNER_BOX) {\n dt.classList.add(EL.AD_NONLINEAR_IMAGE_BANNER_BOX, 'hide');\n }\n },\n showButton: function() {\n if (EL.AD_PLAY_PAUSE_BUTTON_WRAP) {\n dt.classList.remove(EL.AD_PLAY_PAUSE_BUTTON_WRAP, 'hidden');\n dt.classList.add(EL.AD_PLAY_PAUSE_BUTTON_WRAP, 'visible');\n }\n\n if (this.timer) {\n clearTimeout(this.timer);\n }\n\n if (ua.platform !== 'pc' && isFullScreen()) {\n customUI.control.show(false);\n }\n\n if (player.isPaused() && !state.ended) {\n return;\n }\n\n var self = this;\n this.timer = setTimeout(function() {\n self.hideButton();\n self.timer = null;\n }, 1500);\n },\n hideButton: function() {\n if (EL.AD_PLAY_PAUSE_BUTTON_WRAP) {\n dt.classList.add(EL.AD_PLAY_PAUSE_BUTTON_WRAP, 'hidden');\n dt.classList.remove(EL.AD_PLAY_PAUSE_BUTTON_WRAP, 'visible');\n }\n\n if (ua.platform !== 'pc' && isFullScreen()) {\n customUI.control.hide();\n }\n },\n updateTime: function(time, skip) {\n if (EL.AD_TIME) {\n EL.AD_TIME.innerHTML = time;\n EL.AD_TEXT.innerHTML = skip ? ' 초 후 SKIP' : ' 초 후 재생';\n }\n },\n updatePlay: function(percentage) {\n if (percentage > 100) {\n return;\n }\n\n if (EL.AD_PLAY_PROGRESS) {\n EL.AD_PLAY_PROGRESS.style.width = percentage + '%';\n }\n }\n },\n stillVideo: {\n videoElement: null,\n isFirstPlay: true,\n set: function(url) {\n if (!this.videoElement) {\n this.create();\n }\n this.videoElement.src = url;\n this.load();\n state.hasStillVideo = true;\n },\n create: function() {\n var self = this;\n\n this.videoElement = document.createElement('video');\n this.videoElement.setAttribute('id', 'stillVideo');\n this.videoElement.setAttribute('playsinline', '');\n this.videoElement.setAttribute('muted', '');\n\n event.on(this.videoElement, 'canplay', function() {\n if (self.isFirstPlay) {\n self.setSize();\n }\n });\n\n event.on(this.videoElement, 'play', function() {\n self.isFirstPlay = false;\n this.pause();\n });\n\n event.on(this.videoElement, 'error', function() {\n if (this.crossOrigin) {\n state.hasStillVideo = false;\n hideStillVideo();\n if (EL.TIME_POINT) {\n dt.classList.add(EL.TIME_POINT, 'hide');\n }\n\n customUI.control.setCurrentTime(player.getCurrentTimeRound(), player.getDurationRound());\n player.seekTo(player.getCurrentTimeRound());\n } else {\n this.setAttribute('crossorigin', 'use-credentials');\n this.load();\n }\n });\n\n EL.STILL_CONTAINER.appendChild(this.videoElement);\n },\n load: function() {\n this.videoElement.load();\n },\n show: function() {\n var video = this.videoElement;\n var self = this;\n\n if (self.isFirstPlay) {\n video.play();\n }\n dt.classList.remove(EL.STILL_CONTAINER, 'hide');\n },\n hide: function() {\n if (state.hasStillVideo && !this.videoElement.paused) {\n this.videoElement.pause();\n }\n dt.classList.add(EL.STILL_CONTAINER, 'hide');\n },\n seekTo: function(time) {\n if (!isNaN(time)) {\n if (this.videoElement.readyState > 3) {\n this.videoElement.currentTime = Math.round(time);\n }\n }\n },\n move: function(pageX) {\n var rect = EL.PROGRESSBAR.getBoundingClientRect();\n if (isFullScreen()) {\n rect = checkRectSize(rect);\n }\n var offsetLeft = Math.floor(rect.left);\n var offsetX = pageX && pageX - offsetLeft;\n var videoWidthHalf = this.videoElement.clientWidth / 2;\n var leftLimit = videoWidthHalf;\n var rightLimit = rect.width - videoWidthHalf;\n\n if (videoWidthHalf === 0) {\n return;\n }\n\n if (offsetX < leftLimit) {\n offsetX = leftLimit;\n } else if (offsetX > rightLimit) {\n offsetX = rightLimit;\n }\n\n this.setPosition(offsetX);\n },\n setSize: function() {\n var video = {\n width: this.videoElement.videoWidth,\n height: this.videoElement.videoHeight\n };\n\n var viewport = {\n width: document.documentElement.clientWidth,\n height: document.documentElement.clientHeight\n };\n\n var videoWidthForPC = 156;\n var videoWidthForMobile = 200;\n\n var ratio = 9 / 16;\n var width = ua.platform === 'pc' ? videoWidthForPC : videoWidthForMobile;\n\n if (video.height >= video.width) {\n if (ua.platform !== 'pc' && !isFullScreen() && viewport.width > viewport.height) {\n EL.STILL_CONTAINER.style['height'] = null;\n } else {\n width = ua.platform === 'pc' ? videoWidthForPC * ratio : videoWidthForMobile * ratio;\n EL.STILL_CONTAINER.style['height'] = 'auto';\n }\n } else {\n if (ua.platform !== 'pc' && !isFullScreen()) {\n width = videoWidthForMobile;\n }\n EL.STILL_CONTAINER.style['height'] = null;\n }\n\n EL.STILL_CONTAINER.style.width = width + 'px';\n EL.STILL_CONTAINER.style.marginLeft = -(width / 2) + 'px';\n },\n setPosition: function(offsetX) {\n EL.STILL_CONTAINER.style['left'] = ua.platform === 'pc' ? offsetX + 'px' : offsetX + 50 + 'px';\n EL.TIME_POINT.style['left'] = ua.platform === 'pc' ? offsetX + 'px' : offsetX + 50 + 'px';\n\n if (EL.STILL_VIDEO_TIME) {\n EL.STILL_VIDEO_TIME.style['left'] = isFullScreen() ? offsetX + 50 + 'px' : '50%';\n }\n },\n resetPosition: function() {\n if (EL.STILL_CONTAINER) {\n EL.STILL_CONTAINER.style['left'] = null;\n }\n if (EL.STILL_VIDEO_TIME) {\n EL.STILL_VIDEO_TIME.style['left'] = null;\n }\n }\n },\n tvod: {\n el: {\n container: EL.TVOD_CONTAINER,\n message: EL.TVOD_MESSAGE,\n link: EL.TVOD_LINK\n },\n show: function() {\n if (this.el.container) {\n dt.classList.remove(this.el.container, 'hide');\n }\n },\n hide: function() {\n if (this.el.container) {\n dt.classList.add(this.el.container, 'hide');\n }\n },\n setMessage: function(message) {\n if (this.el.message) {\n this.el.message.innerHTML = message;\n }\n },\n setTvodData: function(data) {\n this.setMessage(data.guideMessage);\n }\n },\n container: {\n el: EL.VIDEO_CONTAINER,\n show: function() {\n dt.classList.remove(this.el, 'hidden');\n },\n hide: function() {\n dt.classList.add(this.el, 'hidden');\n }\n },\n rating: {\n el: EL.RATING_CONTAINER,\n timer: null,\n minImpressionTime: 4000,\n show: function() {\n var impressTime = dt.StopWatch.has('rating');\n var self = this;\n\n if (!impressTime) {\n dt.StopWatch.start('rating');\n } else {\n if (impressTime > this.minImpressionTime) {\n return;\n } else {\n dt.StopWatch.resume('rating');\n }\n }\n\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n\n this.timer = setInterval(function() {\n var impressTime = dt.StopWatch.has('rating');\n\n if (impressTime > self.minImpressionTime) {\n self.hide();\n dt.StopWatch.stop('rating');\n clearInterval(self.timer);\n }\n }, 200);\n },\n showWithReset: function() {\n var impressTime = dt.StopWatch.has('rating');\n\n if (impressTime < this.minImpressionTime) {\n dt.StopWatch.stop('rating');\n this.show();\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n dt.StopWatch.pause('rating');\n }\n }\n }\n };\n\n function checkRectSize(rect) {\n if (rect.height < 1) {\n var resizeRect = {};\n for (var o in rect) {\n if (rect.hasOwnProperty(o)) {\n resizeRect[o] = rect[o] * 100;\n }\n }\n return resizeRect;\n }\n return rect;\n }\n\n function sendReport() {\n var video = state.currentVideo;\n var type, id;\n\n if (video.type === 'VOD') {\n id = video.id;\n type = constants.VIDEO_TYPE.VOD;\n } else if (video.type === 'LIVE') {\n id = video.id;\n type = constants.VIDEO_TYPE.LIVE;\n }\n\n var width = 440;\n var height = 620;\n\n openReportWindow(type, id, width, height);\n }\n\n function openReportWindow(type, id, width, height) {\n var currentUrl = window.location.href;\n var reportUrl = helpers.serverHost.create(env.klimtServer, PHASE);\n var param;\n\n if (currentUrl.indexOf('kakao.com') > -1) {\n if (type === constants.VIDEO_TYPE.VOD) {\n param = 'type=clipLink&id=' + id;\n } else {\n param = 'type=liveLink&id=' + id;\n }\n reportUrl = reportUrl.replace('play-tv', 'tv');\n reportUrl += '/report?' + param;\n } else {\n if (type === constants.VIDEO_TYPE.VOD) {\n param = 'serviceCode=70' + '&contentType=' + type + '&articleId=' + id;\n } else {\n param = 'serviceCode=123' + '&contentType=' + type + '&articleId=' + id;\n }\n\n if (PHASE === constants.PHASE.PROD) {\n reportUrl =\n 'http://' +\n (ua.platform !== 'pc' ? 'm.' : '') +\n 'spam119.daum.net/form?platformCode=KAKAOTV&' +\n param;\n } else {\n reportUrl =\n 'http://' +\n (ua.platform !== 'pc' ? 'm.' : '') +\n 'spam119.dev.daum.net/form?platformCode=KAKAOTV&' +\n param;\n }\n }\n\n var features =\n 'fullscreen=no, width=' +\n width +\n ', height=' +\n height +\n ', menubar=no, scrollbars=no, status=no, titlebar=no, resizable=yes';\n\n if (ua.platform === 'pc') {\n openPopup(reportUrl, 'reportWindow', features);\n } else {\n if (env.referer) {\n reportUrl += '&continue=' + encodeURIComponent(env.referer);\n }\n\n top.location.href = reportUrl;\n }\n }\n\n function openPopup(url, name, features) {\n if (isFullScreen()) {\n if (ua.platform === 'pc') {\n cancelFullscreen();\n }\n }\n helpers.window.openPopup(url, name, features);\n }\n\n function toggleCustomUI() {\n if (state.customControlActivated) {\n activateCustomUI(false);\n } else {\n activateCustomUI(true);\n }\n }\n\n function hideControl() {\n customUI.control.hide();\n }\n\n function showControlHead() {\n dt.classList.remove(EL.PLAYER_CONTROLLER_HEAD, 'hide');\n }\n\n function hideControlHead() {\n dt.classList.add(EL.PLAYER_CONTROLLER_HEAD, 'hide');\n }\n\n function showControlFoot() {\n if (env.controls) {\n dt.classList.remove(EL.PLAYER_CONTROLLER_FOOT, 'hide');\n }\n }\n\n function hideControlFoot() {\n dt.classList.add(EL.PLAYER_CONTROLLER_FOOT, 'hide');\n }\n\n function activateAdPlayPause(isPaused) {\n if (!EL.AD_PLAY_PAUSE_BUTTON_WRAP) {\n return;\n }\n\n if (dt.classList.has(EL.AD_PLAY_PAUSE_BUTTON_WRAP, 'hidden')) {\n customUI.ad.showButton();\n } else {\n customUI.ad.hideButton();\n }\n\n toggleAdPlayPause(isPaused);\n }\n\n function toggleAdPlayPause(isPaused) {\n var playButton = EL.AD_PLAY;\n var pauseButton = EL.AD_PAUSE;\n\n if (isPaused) {\n dt.classList.remove(playButton, 'hidden');\n dt.classList.add(pauseButton, 'hidden');\n } else {\n dt.classList.add(playButton, 'hidden');\n dt.classList.remove(pauseButton, 'hidden');\n }\n }\n\n function activateCustomUI(activated, isfreeze) {\n var video = queue.front;\n\n if (activated) {\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n if (ua.platform !== 'pc' && !isFullScreen()) {\n customUI.control.hide();\n } else {\n if (video.timeOffset !== 'end') {\n customUI.control.show(isfreeze);\n return;\n }\n }\n customUI.ad.show();\n } else {\n customUI.control.show(isfreeze);\n }\n } else {\n if (ua.platform === 'mobile' && player.isPaused() && !state.isShowError && !state.ended) {\n return;\n }\n customUI.control.hide();\n customUI.control.hideSeekTime();\n }\n }\n\n function updateProgress(currentTime, duration) {\n var percentage = (100 * currentTime) / duration;\n var video = queue.front;\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n customUI.ad.updatePlay(percentage);\n customUI.progress.updatePlay(percentage);\n } else if (video && video.type === constants.VIDEO_TYPE.VOD) {\n customUI.progress.updatePlay(percentage);\n }\n }\n\n function updateTime(currentTime, duration) {\n if (duration > 0) {\n customUI.control.setCurrentTime(currentTime, duration);\n updateProgress(currentTime, duration);\n }\n }\n\n function updateLoad(loadEndPercentage) {\n customUI.progress.updateLoad(loadEndPercentage);\n }\n\n function updateAdSkipTime() {\n var skipOffset, remainTime, skipCheck;\n\n if (!state.adControlActivated) {\n return;\n }\n\n var currentTime = player.getCurrentTimeRound();\n var duration = player.getDurationRound();\n\n var video = queue.front;\n\n if (duration > 0) {\n if (state.skipAdEnabled) {\n return;\n }\n\n skipOffset = video.skipOffset && video.skipOffset < duration ? video.skipOffset : duration;\n remainTime = skipOffset - currentTime;\n skipCheck = skipOffset - duration !== 0;\n\n if (remainTime < 1 && skipCheck) {\n state.skipAdEnabled = true;\n customUI.ad.hideCount();\n customUI.ad.showSkip();\n } else if (remainTime > 0) {\n customUI.ad.updateTime(remainTime, skipCheck);\n }\n }\n }\n\n function checkNextVideo(currentTime, duration) {\n var remainTime = Math.round(duration - currentTime);\n\n if (remainTime <= NEXT_VIDEO_SHOW_DURATION) {\n if (state.autoplay || state.continuousPlay) {\n if (!state.isCheckNextVideo) {\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onCheckNextVideo, [\n state.currentVideo.id\n ]);\n state.isCheckNextVideo = true;\n }\n }\n }\n }\n\n function showBlind() {\n customUI.control.hide();\n customUI.blind.show();\n }\n\n function hideBlind() {\n customUI.blind.hide();\n }\n\n function showNotification(message, callback) {\n showBlind();\n customUI.notification.show(message, callback);\n }\n\n function startSpinner() {\n customUI.overlay.show();\n }\n\n function endSpinner() {\n setTimeout(function() {\n customUI.overlay.hide();\n }, 250);\n }\n\n function showDefaultControl() {\n player.videoElement.setAttribute('controls', 'true');\n defaultUI.control.show();\n }\n\n function hideDefaultControl() {\n player.videoElement.removeAttribute('controls');\n defaultUI.control.hide();\n }\n\n function getProgressRate(e) {\n var rect = EL.PROGRESSBAR.getBoundingClientRect();\n if (isFullScreen()) {\n rect = checkRectSize(rect);\n }\n\n var pageX = e.changedTouches ? e.changedTouches[0].pageX : e.pageX;\n var offsetLeft = Math.floor(rect.left);\n\n var offsetX = pageX && pageX - offsetLeft;\n var offsetWidth = rect.width;\n var rate = 0;\n\n if (offsetX > offsetWidth) {\n rate = 100;\n }\n\n if (offsetX >= 0 && offsetX <= offsetWidth) {\n rate = (offsetX / offsetWidth) * 100;\n }\n\n return rate;\n }\n\n function isFullScreen() {\n return fullscreenHelper.isFullScreen();\n }\n\n function isFullScreenSupport() {\n return fullscreenHelper.isSupport();\n }\n\n function requestFullscreen() {\n var options = {\n navigationUI: 'hide'\n };\n\n if (fullscreenHelper.isSupport()) {\n fullscreenHelper.request(options);\n } else if (fullscreenHelper.isSupportOnlyIOS()) {\n fullscreenHelper.setFullscreen(true);\n } else {\n alert('현재 환경에서는 전체화면을 지원하지 않습니다');\n }\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onFullScreenChange, [\n FULL_SCREEN_API.REQUEST,\n state.currentVideo.id\n ]);\n }\n\n function cancelFullscreen() {\n var video = queue.front;\n\n if (fullscreenHelper.isSupport()) {\n fullscreenHelper.exit();\n } else if (fullscreenHelper.isSupportOnlyIOS()) {\n fullscreenHelper.setFullscreen(false);\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onFullScreenChange, [\n FULL_SCREEN_API.CANCEL,\n video && video.id\n ]);\n }\n\n function lockScreenInLandscape() {\n if (!('orientation' in screen)) {\n return;\n }\n\n screen.orientation\n .lock('landscape')\n .then(function() {\n listenToDeviceOrientationChanges();\n })\n .catch(function(error) {\n debug.tooltip(error.name + ': ' + error.message);\n });\n }\n\n function listenToDeviceOrientationChanges() {\n if (!('DeviceOrientationEvent' in window)) {\n return;\n }\n\n var previousDeviceOrientation, currentDeviceOrientation;\n event.on(window, 'deviceorientation', function onDeviceOrientationChange(event) {\n if (Math.abs(event.gamma) > 10 || Math.abs(event.beta) < 10) {\n previousDeviceOrientation = currentDeviceOrientation;\n currentDeviceOrientation = 'landscape';\n return;\n }\n if (Math.abs(event.gamma) < 10 || Math.abs(event.beta) > 10) {\n previousDeviceOrientation = currentDeviceOrientation;\n if (previousDeviceOrientation === 'landscape') {\n if (!isFullScreen()) {\n screen.orientation.unlock();\n customUI.stillVideo.resetPosition();\n }\n window.removeEventListener('deviceorientation', onDeviceOrientationChange);\n }\n }\n });\n }\n\n function applyParameters() {\n if (!env.showProfile) {\n customUI.control.hideProfile();\n }\n\n if (!env.showProgress) {\n customUI.progress.hide();\n }\n\n if (!env.showMute) {\n customUI.control.hideMute();\n customUI.control.hideAdMute();\n }\n\n if (!env.showPlayback) {\n customUI.control.hidePlayPause();\n customUI.control.hideSeeking();\n customUI.control.hideAdPlayPause();\n customUI.control.hideCoverPlay();\n }\n\n if (!env.showLiveIcon) {\n customUI.control.hideLiveIcon();\n customUI.control.hideCoverLiveIcon();\n customUI.control.hideCoverTitle();\n customUI.control.hideViewerBackground();\n customUI.control.hideTitle();\n }\n\n if (!env.showViewer) {\n customUI.control.hideViewerBox();\n customUI.control.hideTitle();\n }\n }\n\n function isEnabledFullscreen() {\n var fullscreenEnabled =\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n fullscreenHelper.isSupportOnlyIOS() ||\n document.msFullscreenEnabled ||\n document.mozFullScreenEnabled;\n\n return env.fs && fullscreenEnabled;\n }\n\n function updateStat() {\n if (state.currentVideo.type === 'LIVE') {\n dataLoader.getLiveStat(state.currentVideo.id);\n }\n }\n\n function statCallback(data) {\n var video = state.currentVideo;\n var nextInterval = data.nextInterval || 60;\n var count = data.playCount || video.playCount;\n video.title = data.displayTitle || '';\n video.ccuCount = data.ccuCount || '';\n\n customUI.control.setTitle({\n title: video.title\n });\n customUI.control.setAgeLimit(video.ageLimit);\n customUI.control.setSecret(video.needPassword);\n customUI.control.setViewerCount(count);\n\n liveStatTimeout = setTimeout(function() {\n updateStat();\n }, nextInterval * 1000);\n }\n\n function getClipLocation(profile, callback) {\n var tid = state.currentVideo && state.currentVideo.tid;\n var isHLSContentType =\n state.currentVideo && state.currentVideo.videoUrl && state.currentVideo.videoUrl.indexOf('m3u8') > -1;\n\n if (profile === 'AUTO' && !isHLSContentType) {\n profile = constants.PROFILE.MAIN;\n }\n\n var options = {\n service: env.service,\n section: env.section,\n tid: tid,\n profile: profile,\n dteType: helpers.device.getDteType(ua),\n contentType: isHLSContentType ? constants.CONTENT_TYPE.HLS : constants.CONTENT_TYPE.MP4\n };\n\n if (env.section2) {\n options.section2 = env.section2;\n }\n\n if (env.ptoken) {\n options.ptoken = env.ptoken;\n }\n\n qoeTracker.track(QOE_EVENTS.RESOLUTION_CHANGE, {\n l1: constants.PROFILE_RESOULTION[state.currentVideo.profile],\n l2: 'manual',\n rslu: constants.PROFILE_RESOULTION[profile]\n });\n\n dataLoader.getClipLocation(state.currentVideo, options, callback);\n }\n\n function getLiveLocation(profile, callback) {\n var currentVideo = state.currentVideo;\n var tid = currentVideo && currentVideo.tid;\n var contentType = currentVideo && currentVideo.contentType;\n\n var options = {\n service: env.service,\n section: env.section,\n tid: tid,\n profile: profile,\n dteType: helpers.device.getDteType(ua),\n contentType: contentType\n };\n\n if (currentVideo.password) {\n options.password = currentVideo.password;\n }\n\n if (env.ptoken) {\n options.ptoken = env.ptoken;\n }\n\n qoeTracker.track(QOE_EVENTS.RESOLUTION_CHANGE, {\n l1: constants.PROFILE_RESOULTION[state.currentVideo.profile],\n l2: 'manual',\n rslu: constants.PROFILE_RESOULTION[profile]\n });\n\n dataLoader.getLiveLocation(state.currentVideo, options, callback);\n }\n\n function onSeeked() {\n var currentTime = player.getCurrentTimeRound();\n var duration = player.getDurationRound();\n\n state.preventTogglePlayPause = false;\n\n if (currentTime >= player.getDurationRound()) {\n state.ended = true;\n return;\n }\n\n updateTime(currentTime, duration);\n state.ended = false;\n resizeControl();\n\n if (player.isPaused() && state.isSettingMenuOpened) {\n exports.queue.emit('close:menubox');\n }\n }\n\n function onPlay() {\n if (window.WebSocket) {\n if (websocket.getConnectionTiming() === 'PLAYING') {\n websocket.open();\n }\n }\n }\n\n function setupNonLinearAd(ad) {\n var displayPer = ad.DisplayPer > 0 ? ad.DisplayPer : 1;\n nonLinearAdDuration = (ad.Duration || 5) * 1000;\n\n if (ad.Title) {\n customUI.ad.setupMidTextAd(ad.Click, ad.Title);\n } else if (ad.BannerUrl) {\n customUI.ad.setupMidImageAd(ad.Click, ad.BannerUrl);\n }\n customUI.ad.setNonLinearProgressPoint(ad.Duration, displayPer);\n debug.info('setupNonLinearAd', ad.Duration, displayPer);\n }\n\n function setupMidrollAd(index, isStarted, timeOffset) {\n customUI.ad.setMidrollPoint(index, isStarted, timeOffset);\n }\n\n function removeMidrollPoint() {\n customUI.ad.removeMidrollPoint();\n }\n\n function showLinearAdContainer() {\n customUI.ad.showLinearContainer();\n }\n\n function hideLinearAdContainer() {\n customUI.ad.hideLinearContainer();\n }\n\n function showNonLinearAdContainer() {\n var video = queue.front;\n if (video && video.type !== constants.VIDEO_TYPE.AD) {\n hideLinearAdContainer();\n customUI.ad.showNonLinearContainer();\n }\n }\n\n function hideNonLinearAdContainer() {\n customUI.ad.hideNonLinearContainer();\n }\n\n function showNonLinearAd(isStarted, adType) {\n showNonLinearAdContainer();\n if (adType === 'text') {\n showMidTextAd(isStarted);\n } else if (adType === 'image') {\n showMidImageAd(isStarted);\n }\n }\n\n function hideNonLinearAd() {\n closeMidTextAd();\n closeMidImageAd();\n }\n\n function showMidTextAd(isStarted) {\n customUI.ad.hideNonLinearAdImage();\n customUI.ad.hideNonLinearAdTextInfo();\n customUI.ad.showNonLinearAdTextBox();\n customUI.ad.show();\n\n if (isStarted) {\n nonLinearAdTimer = new dt.Timer(closeMidTextAd, nonLinearAdDuration);\n nonLinearAdTimer.start();\n }\n vastTracker.midTextAdTracker.load();\n }\n\n function closeNonLinearAd() {\n if (nonLinearAdTimer) {\n nonLinearAdTimer.clear();\n nonLinearAdTimer = null;\n debug.info('Nonlinear Image Ad - Finish!!', player.getCurrentTimeRound());\n }\n if (state.isNonLinearAdShown) {\n customUI.ad.setNonLinearProgressPoint(0);\n }\n }\n\n function closeMidTextAd() {\n closeNonLinearAd();\n customUI.ad.showNonLinearAdTextInfo();\n customUI.ad.hideNonLinearAdText();\n }\n\n function closeMidImageAd() {\n hideNonLinearAdContainer();\n closeNonLinearAd();\n customUI.ad.hideNonLinearAdImage();\n }\n\n function showMidImageAd(isStarted) {\n customUI.ad.hideNonLinearAdText();\n customUI.ad.showNonLinearAdImageBox();\n customUI.ad.show();\n\n if (isStarted) {\n nonLinearAdTimer = new dt.Timer(closeMidImageAd, nonLinearAdDuration);\n nonLinearAdTimer.start();\n debug.info('Nonlinear Image Ad - Start!', player.getCurrentTimeRound());\n }\n vastTracker.midImageAdTracker.load();\n }\n\n function pauseNonLinearAd() {\n if (nonLinearAdTimer) {\n nonLinearAdTimer.pause();\n }\n hideNonLinearAdContainer();\n }\n\n function resumeNonLinearAd() {\n if (nonLinearAdTimer) {\n nonLinearAdTimer.resume();\n }\n showNonLinearAdContainer();\n }\n\n function removeText(text) {\n var re = / |P|HD|4K/g;\n return text.replace(re, '');\n }\n\n function setProfile(profile) {\n var profileTextTemplate = profileTemplate.profile_text;\n var profileList = state.currentVideo.outputList;\n var profileLabel = '';\n var profileText = '';\n var templateData = {\n profileAuto: profile === constants.PROFILE.AUTO,\n profile: '',\n profileHD: false,\n profile4K: false\n };\n\n if (state.abr) {\n profileLabel = shaka.getCurrentProfile();\n profileText = removeText(shaka.getCurrentProfile());\n } else {\n if (profile === constants.PROFILE.AUTO) {\n profileList.filter(function(val) {\n if (\n val.height === player.videoElement.videoWidth ||\n val.height === player.videoElement.videoHeight\n ) {\n profileLabel = val.label;\n profileText = removeText(profileLabel);\n return true;\n }\n return false;\n });\n } else {\n for (var i in profileList) {\n if (profileList.hasOwnProperty(i) && profileList[i].profile === profile) {\n profileLabel = profileList[i].label;\n profileText = removeText(profileLabel);\n break;\n }\n }\n }\n }\n\n templateData.profile = profileText;\n templateData.profileHD = profileLabel.indexOf('HD') > 0;\n templateData.profile4K = profileLabel.indexOf('4K') > 0;\n\n dt.classList.remove(EL.SETUP_BUTTON, 'btn_hd');\n dt.classList.remove(EL.SETUP_BUTTON, 'btn_4k');\n\n if (templateData.profileHD) {\n dt.classList.add(EL.SETUP_BUTTON, 'btn_hd');\n } else if (templateData.profile4K) {\n dt.classList.add(EL.SETUP_BUTTON, 'btn_4k');\n }\n\n if (EL.PROFILE_BUTTON) {\n EL.PROFILE_BUTTON.innerHTML = profileTextTemplate.render(templateData);\n }\n }\n\n function toggleMuteUI(muteOn) {\n if (helpers.device.isSupportMutedControl(ua)) {\n customUI.control.toggleAdMute(muteOn);\n customUI.control.toggleMute(muteOn);\n }\n }\n\n function initVolumeControl() {\n var muteOn = getRecentMute();\n var volume = muteOn ? 0 : getRecentVolume();\n setVolume(volume, muteOn);\n toggleMuteUI(muteOn);\n }\n\n function setVolume(volume, muteOn) {\n var vol = isNaN(volume) || volume > 1 || volume < 0 ? VOLUME_DEFUALT : volume;\n\n if (ua.platform === 'pc') {\n player.setVolume(vol);\n }\n player.setMute(muteOn);\n }\n\n function getRecentMute() {\n return (\n state.initialState.startMuted ||\n helpers.store.get(MUTE_STATE_KEY) === true ||\n helpers.store.get(MUTE_STATE_KEY) === 'true'\n );\n }\n\n function getRecentVolume() {\n var storedVolume = helpers.store.get(VOLUME_STATE_KEY);\n if (!storedVolume) {\n storedVolume = VOLUME_DEFUALT;\n }\n return storedVolume;\n }\n\n function setRecentVolume(volume) {\n if (!isNaN(volume)) {\n helpers.store.set(VOLUME_STATE_KEY, volume.toFixed(2));\n }\n }\n\n function saveRecentMute(muteOn) {\n helpers.store.set(MUTE_STATE_KEY, muteOn);\n }\n\n function setStillVideo(seekUrl, callback) {\n if (seekUrl && seekUrl !== '' && helpers.device.isSupportThumbnailVideo(ua)) {\n customUI.stillVideo.set(seekUrl);\n\n if (callback && typeof callback === 'function') {\n callback();\n }\n }\n }\n\n function setStillVideoCurrentTime(currentTime) {\n EL.STILL_VIDEO_TIME.innerHTML = helpers.string.delimitTimes(currentTime);\n }\n\n function showStillVideo() {\n customUI.stillVideo.show();\n if (EL.TIME_POINT) {\n dt.classList.remove(EL.TIME_POINT, 'hide');\n }\n }\n\n function hideStillVideo() {\n customUI.stillVideo.hide();\n if (EL.TIME_POINT) {\n dt.classList.add(EL.TIME_POINT, 'hide');\n }\n }\n\n function toggleProfile() {\n if (!state.hls || !state.drm) {\n customUI.control.showProfile();\n } else {\n customUI.control.hideProfile();\n }\n }\n\n function toggleAppLink() {\n var video = state.currentVideo;\n\n if (env.appLink && video.shouldShowHDLabel) {\n customUI.control.showAppLinkButton();\n } else {\n customUI.control.hideAppLinkButton();\n }\n }\n\n function setSeekThumbnail() {\n var video = state.currentVideo;\n var seekUrl = video.seekUrl;\n\n if (seekUrl) {\n setStillVideo(seekUrl);\n }\n }\n\n function getShowTitle() {\n var video = state.currentVideo;\n var showTitle = true;\n\n if (!env.isInternal && env.showInfo) {\n if (video.type === 'LIVE' && !(env.showLiveIcon && env.showViewer)) {\n showTitle = false;\n }\n } else {\n showTitle = false;\n }\n\n return showTitle;\n }\n\n function setShowTitle() {\n var showTitle = getShowTitle();\n if (env.popup || showTitle) {\n customUI.control.showTitle();\n }\n }\n\n function setKakaoTVLink() {\n var video = state.currentVideo;\n var link = '/channel/#{channelId}/cliplink/#{linkId}';\n\n if (video.type === 'LIVE') {\n link = '/channel/#{channelId}/livelink/#{linkId}';\n }\n\n link = helpers.string.format(helpers.serverHost.link(PHASE) + link, {\n channelId: video.channelId,\n linkId: video.id\n });\n\n customUI.control.setTitle({\n title: video.title,\n url: link\n });\n }\n\n function setRatingLevel() {\n var RATING_TYPE = constants.RATING;\n var video = state.currentVideo;\n var rating = video.rating;\n\n if (!rating) {\n return;\n }\n\n var template = playerTemplate.rating_level;\n var isMobile = ua.platform === 'mobile';\n var ratingList = [];\n var ageLimit = getAgeLimit(rating.ageLimit);\n var ratingValues = rating && rating.values;\n var companyName = rating.companyName;\n var serialNumber = rating.serialNumber;\n\n ratingValues.forEach(function(value) {\n if (RATING_TYPE[value]) {\n ratingList.push(RATING_TYPE[value]);\n }\n });\n\n EL.RATING_CONTAINER.innerHTML = template.render({\n ratingList: ratingList,\n ageLimit: ageLimit,\n isMobile: isMobile,\n companyName: companyName,\n serialNumber: serialNumber\n });\n }\n\n function getAgeLimit(ageLimit) {\n var AGE_LIMIT = constants.AGE_LIMIT;\n var ageLimitTemplateData = {};\n\n if (ageLimit && AGE_LIMIT[ageLimit]) {\n ageLimitTemplateData = AGE_LIMIT[ageLimit];\n }\n\n return ageLimitTemplateData;\n }\n\n function runClickHandler(target, selector, callback) {\n var closest = target.closest(selector);\n if (closest) {\n callback(closest);\n }\n }\n\n function resizeControl() {\n if (state.ended) {\n dt.classList.add(EL.PLAYER, 'ended');\n } else {\n dt.classList.remove(EL.PLAYER, 'ended');\n customUI.progress.off();\n }\n }\n\n function checkFullscreenEnabled() {\n if (!isEnabledFullscreen()) {\n customUI.fullscreen.hide();\n }\n }\n\n var handler = {\n onTouchStartProgress: function(e) {\n var video = queue.front;\n var currentTime = 0;\n\n if (\n !state.seekEnabled ||\n (video && video.type === constants.VIDEO_TYPE.AD) ||\n (video && video.type === constants.VIDEO_TYPE.LIVE)\n ) {\n return;\n }\n\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n state.mutedBeforeSeek = player.getMute();\n var orientation = helpers.orientation.getOrientation();\n var pageX = e.changedTouches ? e.changedTouches[0].pageX : e.pageX;\n var rate = getProgressRate(e);\n\n if (rate >= 0 && rate <= 100) {\n currentTime = (player.getDurationRound() * rate) / 100;\n if (!state.hasStillVideo) {\n player.seekTo(currentTime);\n player.setMute(true);\n customUI.control.setCurrentTime(currentTime, player.getDurationRound());\n customUI.control.showSeekTime();\n } else {\n if (ua.platform !== 'pc') {\n showStillVideo();\n setStillVideoCurrentTime(currentTime);\n customUI.control.hideTitle();\n customUI.control.hideExtension();\n customUI.control.showDimmedLayer();\n\n if (isFullScreen() && orientation === 'landscape') {\n customUI.stillVideo.move(pageX);\n }\n }\n }\n customUI.progress.updatePlay(rate);\n }\n\n customUI.progress.on();\n customUI.control.hidePlayPause();\n customUI.control.hideSeeking();\n customUI.control.clearTimer();\n\n state.seeking = true;\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onTouchEventStart);\n },\n onTouchEndProgress: function(e) {\n var rate = getProgressRate(e);\n var currentTime = 0;\n var showTitle = getShowTitle();\n var video = queue.front;\n\n if (\n video === null ||\n video.type === constants.VIDEO_TYPE.AD ||\n video.type === constants.VIDEO_TYPE.LIVE\n ) {\n return;\n }\n\n if (dt.StopWatch.has('rebuffering')) {\n dt.StopWatch.stop('rebuffering');\n }\n dt.StopWatch.start('seek');\n\n if (state.seekEnabled) {\n customUI.control.hideSeekTime();\n customUI.control.showSeeking();\n customUI.control.showPlayPause();\n customUI.progress.off();\n\n state.seeking = false;\n player.setMute(state.mutedBeforeSeek);\n\n if (ua.platform !== 'pc') {\n var isFreeze = state.pausedBeforeSeek;\n customUI.control.show(isFreeze);\n\n if (state.hasStillVideo) {\n hideStillVideo();\n }\n\n customUI.control.showExtension();\n customUI.control.hideDimmedLayer();\n\n if (showTitle) {\n customUI.control.showTitle();\n }\n }\n\n if (rate >= 0 && rate <= 100) {\n startSpinner();\n currentTime = (player.getDurationRound() * rate) / 100;\n player.seekTo(currentTime);\n }\n\n pctTracker.track('progress', player.getCurrentTimeRound());\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onTouchEventEnd);\n }\n },\n onTouchMoveProgressPoint: function(e) {\n var video = queue.front;\n\n if (!state.seeking) {\n return false;\n }\n\n if (video.type === constants.VIDEO_TYPE.AD || video.type === constants.VIDEO_TYPE.LIVE) {\n return;\n }\n\n var orientation = helpers.orientation.getOrientation();\n var pageX = e.changedTouches ? e.changedTouches[0].pageX : e.pageX;\n var rate = getProgressRate(e);\n var currentTime = 0;\n\n customUI.progress.updatePlay(rate);\n customUI.progress.on();\n\n if (rate > 0 && rate <= 100) {\n currentTime = (player.getDurationRound() * rate) / 100;\n\n if (state.hasStillVideo) {\n if (ua.platform !== 'pc') {\n showStillVideo();\n if (EL.TIME_POINT) {\n dt.classList.remove(EL.TIME_POINT, 'hide');\n }\n\n setStillVideoCurrentTime(currentTime);\n customUI.stillVideo.seekTo(currentTime);\n\n if (isFullScreen() && orientation === 'landscape') {\n customUI.stillVideo.move(pageX);\n }\n }\n } else {\n hideStillVideo();\n customUI.control.setCurrentTime(currentTime, player.getDurationRound());\n player.seekTo(currentTime);\n }\n }\n },\n onClickMenu: function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n customUI.control.hide();\n exports.queue.emit('show:modal', { target: 'setting' });\n },\n onClickProfile: function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n customUI.control.hide();\n exports.queue.emit('show:modal', { target: 'profile' });\n },\n onClickSubtitle: function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n customUI.control.hide();\n exports.queue.emit('show:modal', { target: 'subtitle' });\n },\n onShowNotification: function(data) {\n var message = data.message;\n var callback = data.callback;\n\n if (!message || typeof message !== 'string') {\n debug.log('message does not exsist');\n return;\n }\n\n showNotification(message, callback);\n },\n onFullScreenChange: function(e) {\n var video = queue.front;\n\n if (!fullscreenHelper.isFullScreenChangeEvent(e)) {\n endSpinner();\n return;\n }\n\n if (!helpers.device.isSupportCustomController(ua)) {\n endSpinner();\n return;\n }\n\n if (!state.ended && !player.isPaused()) {\n player.play();\n }\n\n if (isFullScreen()) {\n customUI.fullscreen.toggle(true);\n customUI.rating.showWithReset();\n exports.queue.emit('request:fullscreen');\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onFullScreenChange, [\n FULL_SCREEN_API.REQUEST,\n video && video.id\n ]);\n } else {\n customUI.fullscreen.toggle(false);\n customUI.stillVideo.resetPosition();\n\n exports.queue.emit('cancel:fullscreen');\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onFullScreenChange, [\n FULL_SCREEN_API.CANCEL,\n video && video.id\n ]);\n\n hideDefaultControl();\n endSpinner();\n }\n },\n onOrientationChange: function() {\n if (ua.platform === 'pc') {\n customUI.reSize();\n }\n },\n onClickAdController: function(e) {\n var target = e.target;\n\n runClickHandler(target, '.link_skip', function() {\n event.stopPropagation(e);\n\n if (state.skipAdEnabled) {\n dt.StopWatch.start(queue.front.breakId !== 'midroll' ? 'startPlay' : 'rebuffering');\n exports.queue.emit('skip:ad');\n vastTracker.skip();\n if (queue.front.breakId === 'preroll') {\n pctTracker.track('linear_pre', 'skip');\n } else if (queue.front.breakId === 'midroll') {\n pctTracker.track('linear_mid', 'skip');\n }\n }\n });\n\n runClickHandler(target, '.link_more', function(closest) {\n event.stopPropagation(e);\n\n if (ua.platform === 'pc') {\n customUI.control.show(true);\n }\n\n if (closest.href) {\n player.pause();\n vastTracker.click();\n if (queue.front.breakId === 'preroll') {\n pctTracker.track('linear_pre', 'link');\n } else if (queue.front.breakId === 'midroll') {\n pctTracker.track('linear_mid', 'link');\n }\n }\n });\n\n runClickHandler(target, '.link_smrad', function(closest) {\n event.stopPropagation(e);\n\n if (closest.href) {\n player.pause();\n vastTracker.extension.click();\n pctTracker.track('linear_post_text', 'link');\n }\n });\n\n runClickHandler(target, '.link_textad', function(closest) {\n event.stopPropagation(e);\n pauseNonLinearAd();\n\n if (closest.href) {\n player.pause();\n vastTracker.midTextAdTracker.click();\n pctTracker.track('nonlinear_text', 'link');\n }\n });\n\n runClickHandler(target, '.close_textad', function() {\n event.stopPropagation(e);\n\n closeMidTextAd();\n pctTracker.track('nonlinear_text', 'close');\n });\n\n runClickHandler(target, '.link_nonlinear_text', function() {\n event.stopPropagation(e);\n\n showNonLinearAd(false, 'text');\n pctTracker.track('nonlinear_text', 'info');\n });\n\n runClickHandler(target, '.link_imagead', function(closest) {\n event.stopPropagation(e);\n pauseNonLinearAd();\n\n if (closest.href) {\n player.pause();\n vastTracker.midImageAdTracker.click();\n pctTracker.track('nonlinear_image', 'link');\n }\n });\n\n runClickHandler(target, '.close_imagead', function() {\n event.stopPropagation(e);\n\n closeMidImageAd();\n pctTracker.track('nonlinear_image', 'close');\n });\n\n runClickHandler(target, '.link_optout', function() {\n pctTracker.track('ad_optout');\n });\n },\n onClickPlayerController: function(e) {\n var target = e.target;\n\n runClickHandler(target, '.btn_liveHD', function() {\n event.stopPropagation(e);\n hideControl();\n\n exports.queue.emit('play:live', 'HIGH');\n pctTracker.track('liveapp', 'open');\n });\n\n runClickHandler(target, '.btn_mute', function() {\n event.stopPropagation(e);\n\n player.setMute(false);\n saveRecentMute(false);\n exports.queue.emit('reset:env:mute');\n pctTracker.track('mute', 'false');\n });\n\n runClickHandler(target, '.btn_muteoff', function() {\n event.stopPropagation(e);\n\n player.setMute(true);\n saveRecentMute(true);\n pctTracker.track('mute', 'true');\n });\n\n runClickHandler(target, '.player_play', function() {\n event.stopPropagation(e);\n\n if (state.needMidrollRequest) {\n state.needMidrollRequest = false;\n exports.queue.emit('ad:checkMidrollAd');\n }\n\n player.play();\n activateCustomUI(true);\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onClickEventStart, [\n constants.PLAYER_CLICK_ACTION.PLAY,\n state.currentVideo.id\n ]);\n pctTracker.track('play_pause');\n });\n\n runClickHandler(target, '.player_pause', function() {\n event.stopPropagation(e);\n\n player.pause();\n activateCustomUI(true);\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onClickEventStart, [\n constants.PLAYER_CLICK_ACTION.PAUSE,\n state.currentVideo.id\n ]);\n pctTracker.track('play_pause');\n });\n\n runClickHandler(target, '.player_replay', function() {\n event.stopPropagation(e);\n\n activateCustomUI(false);\n startSpinner();\n\n exports.queue.emit('hide:completion');\n\n var preserveState = {\n autoplay: state.autoplay\n };\n\n if (state.abr) {\n shaka.unload();\n }\n\n exports.queue.emit(\n 'loadAndPlay:videoById:replay',\n state.currentVideo.id,\n state.abr ? constants.DASH_PROFILE[state.currentVideo.profile] : state.currentVideo.profile,\n 0,\n preserveState\n );\n pctTracker.track('replay');\n });\n\n runClickHandler(target, '.btn_back10s', function() {\n event.stopPropagation(e);\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n\n var currentTime = player.getCurrentTimeRound() - 10;\n if (currentTime < 0) {\n return;\n }\n\n state.preventTogglePlayPause = true;\n player.seekTo(currentTime);\n activateCustomUI(true);\n pctTracker.track('10s_seeking', 'forward');\n });\n\n runClickHandler(target, '.btn_front10s', function() {\n event.stopPropagation(e);\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n\n var currentTime = player.getCurrentTimeRound() + 10;\n if (currentTime > player.getDurationRound()) {\n return;\n }\n\n state.preventTogglePlayPause = true;\n player.seekTo(currentTime);\n activateCustomUI(true);\n pctTracker.track('10s_seeking', 'backward');\n });\n\n runClickHandler(target, '#fullscreenBtn', function() {\n event.stopPropagation(e);\n\n if (isFullScreen()) {\n cancelFullscreen();\n } else {\n requestFullscreen();\n if (ua.platform === 'pc') {\n contextMenu.exitPictureInPicture();\n } else {\n var video = player.videoElement;\n if (video.videoWidth >= video.videoHeight) {\n lockScreenInLandscape();\n }\n }\n }\n pctTracker.track('fullscreen');\n });\n }\n };\n\n var listener = {\n viewEvent: function() {\n var thread;\n var prefix = helpers.polyfill.getPrefix(document, 'visibilityState');\n var visibilityChange = prefix + 'visibilitychange';\n\n event.on(EL.AD_CONTROLLER, 'click', handler.onClickAdController);\n\n event.on(EL.PLAYER_CONTROLLER, 'click', handler.onClickPlayerController);\n\n event.on(document, visibilityChange, function() {\n if (document.visibilityState === 'hidden') {\n pauseNonLinearAd();\n\n if (ua.platform === 'mobile') {\n player.pause();\n state.pausedBeforeSeek = player.isPaused();\n }\n } else if (document.visibilityState === 'visible') {\n var video = queue.front;\n\n if (state.pausedBeforeSeek && player.isPaused()) {\n player.pause();\n\n if (video && video.type === constants.VIDEO_TYPE.VOD) {\n customUI.control.show(player.isPaused());\n } else if (video && video.type === constants.VIDEO_TYPE.AD) {\n customUI.ad.showButton();\n }\n } else {\n if (video && video.type === constants.VIDEO_TYPE.VOD && !state.ended) {\n customUI.control.hide();\n } else if (video && video.type === constants.VIDEO_TYPE.AD) {\n customUI.ad.hideButton();\n }\n }\n\n if (state.hasStillVideo && helpers.device.isPCWithSafari(ua)) {\n customUI.stillVideo.load();\n }\n }\n });\n\n event.delegate(EL.PLAYER, '.report', 'click', function(e) {\n event.stopPropagation(e);\n event.preventDefault(e);\n\n sendReport();\n exports.queue.emit('close:settingbox');\n\n pctTracker.track('report');\n });\n\n if (ua.platform === 'pc') {\n orien.onOrientationChange(\n helpers.waiter.throttle(function(e) {\n handler.onOrientationChange(e);\n }, 250)\n );\n\n event.delegate(EL.PLAYER_CONTROLLER, '.progress_bar', 'mousemove', function(e) {\n var video = queue.front;\n\n if (\n env.isAdType ||\n !env.controls ||\n (video && video.type === constants.VIDEO_TYPE.AD) ||\n (video && video.type === constants.VIDEO_TYPE.LIVE)\n ) {\n return;\n }\n\n var timePlay = $$('.time_play')[0];\n var rate = getProgressRate(e);\n\n if (rate > 0) {\n var currentTime = (player.getDurationRound() * rate) / 100;\n\n if (!isNaN(currentTime)) {\n var rect = EL.PROGRESSBAR.getBoundingClientRect();\n if (isFullScreen()) {\n rect = checkRectSize(rect);\n }\n\n var pageX = e.pageX;\n var offsetLeft = Math.floor(rect.left);\n var offsetX = pageX && pageX - offsetLeft;\n var seekBarWidth = (offsetX / EL.PROGRESSBAR.offsetWidth) * 100;\n\n EL.SEEK_BAR.style['width'] = seekBarWidth + '%';\n\n timePlay.innerHTML = helpers.string.delimitTimes(currentTime);\n\n if (state.hasStillVideo) {\n showStillVideo();\n customUI.stillVideo.seekTo(currentTime);\n customUI.stillVideo.move(pageX);\n } else {\n EL.TIME_POINT.style['left'] = offsetX + 'px';\n }\n }\n }\n });\n\n event.delegate(EL.PLAYER_CONTROLLER, '.progress_bar', 'mouseover', function() {\n if (env.isAdType || !env.controls) {\n return;\n }\n\n if (EL.TIME_POINT) {\n dt.classList.remove(EL.TIME_POINT, 'hide');\n }\n });\n\n event.on(document, 'mouseout', function(e) {\n var from = e.relatedTarget || e.toElement;\n if (!from || from.nodeName === 'HTML') {\n if (!env.controls || state.ended) {\n return;\n }\n\n if (\n player.videoElement.readyState > 3 &&\n !state.ended &&\n !env.isAdType &&\n !state.seeking &&\n !player.isPaused() &&\n !env.keepShowControl\n ) {\n customUI.control.hide();\n }\n }\n });\n\n event.on(EL.PLAYER_CONTROLLER_CONTAINER, 'mousemove', function() {\n var onmousestop = function() {\n if (\n !env.controls ||\n state.seeking ||\n state.ended ||\n player.isPaused() ||\n state.isSettingMenuOpened ||\n env.keepShowControl\n ) {\n return;\n }\n customUI.control.hide();\n };\n\n if (player.isReady() && !state.ended && !env.isAdType) {\n customUI.control.show(player.isPaused());\n }\n\n if (thread) {\n clearTimeout(thread);\n }\n\n thread = setTimeout(onmousestop, 1500);\n });\n } else {\n orien.onOrientationChange(function(e) {\n if (isFullScreen()) {\n customUI.stillVideo.resetPosition();\n }\n handler.onOrientationChange(e);\n });\n\n event.on(EL.PLAYER_CONTROLLER_CONTAINER, 'click', function() {\n var video = queue.front;\n\n if (player.videoElement.readyState === 4) {\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n return;\n }\n\n if (!player.isPaused()) {\n toggleCustomUI();\n } else {\n customUI.control.toggleUI();\n }\n }\n });\n\n if (EL.TVOD_LINK) {\n event.on(EL.TVOD_LINK, 'click', function() {\n var currentVideo = state.currentVideo;\n\n var purchase = currentVideo.purchase;\n\n if (ua.platform !== 'pc' && purchase) {\n helpers.web2app.launchTalk(purchase.purchaseLink);\n }\n\n pctTracker.track('original_tvod', 'purchase', 'playing');\n });\n }\n\n event.on(EL.AD_CONTROLLER, 'click', function(e) {\n var video = queue.front;\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n if (\n dt.classList.has(e.target, 'link_skip') ||\n dt.classList.has(e.target, 'img_player') ||\n dt.classList.has(e.target, 'link_play') ||\n dt.classList.has(e.target, 'link_pause')\n ) {\n customUI.ad.showButton();\n return;\n }\n activateAdPlayPause(player.isPaused());\n }\n });\n\n event.on(EL.AD_PLAY, 'click', function() {\n player.play();\n pctTracker.track('play_pause');\n });\n\n event.on(EL.AD_PAUSE, 'click', function() {\n player.pause();\n pctTracker.track('play_pause');\n });\n\n event.on(EL.AD_MUTE_BUTTON, 'click', function() {\n player.setMute(false);\n saveRecentMute(false);\n\n pctTracker.track('mute', 'false');\n });\n\n event.on(EL.AD_UNMUTE_BUTTON, 'click', function() {\n player.setMute(true);\n saveRecentMute(true);\n\n pctTracker.track('mute', 'true');\n });\n\n event.on(EL.PLAYER_CONTROLLER_TOGGLE_BUTTON, 'click', function() {\n customUI.control.show(true);\n if (player.isPaused()) {\n EL.PLAY_BUTTON.focus();\n } else {\n EL.PAUSE_BUTTON.focus();\n }\n });\n\n event.delegate(EL.PLAYER_FUNCTION, '.' + CNAME.BUTTON_SETTING, 'click', handler.onClickMenu);\n event.delegate(EL.PLAYER, '.' + CNAME.BUTTON_PROFILE, 'click', handler.onClickProfile);\n event.delegate(EL.PLAYER, '.' + CNAME.BUTTON_SUBTITLE, 'click', handler.onClickSubtitle);\n }\n\n event.on(\n window,\n 'resize',\n helpers.waiter.debounce(function() {\n var body = document.documentElement || document.body;\n qoeTracker.track(QOE_EVENTS.DISPLAY_SIZE_CHANGE, {\n n1: body.clientWidth,\n n2: body.clientHeight\n });\n }, 300)\n );\n\n function addEventFullScreenChange() {\n var fullscreenEvents = [\n 'fullscreenchange',\n 'MSFullscreenChange',\n 'mozfullscreenchange',\n 'webkitfullscreenchange',\n 'webkitbeginfullscreen',\n 'webkitendfullscreen'\n ];\n\n var webkitFullscreenEvents = ['webkitbeginfullscreen', 'webkitendfullscreen'];\n\n fullscreenEvents.forEach(function(item) {\n event.on(document, item, function(e) {\n handler.onFullScreenChange(e);\n });\n });\n\n webkitFullscreenEvents.forEach(function(item) {\n event.on(player.videoElement, item, function(e) {\n handler.onFullScreenChange(e);\n });\n });\n\n event.on(player.videoElement, 'webkitendfullscreen', function() {\n var isAutoPlay = false;\n var startTime = 0;\n\n if (state.ended && helpers.device.isiOSOver14(ua)) {\n exports.queue.emit('load:videoById:withPlayerUnload', startTime, isAutoPlay);\n }\n });\n }\n\n addEventFullScreenChange();\n },\n customEvent: function(sandbox) {\n sandbox.on('complete:play', function() {\n if (!env.controls) {\n hideControlFoot();\n }\n\n if (env.menu) {\n if (EL.SETTING_BUTTON) {\n dt.classList.remove(EL.SETTING_BUTTON, 'hide');\n }\n }\n });\n\n sandbox.on('show:notification', function(data) {\n handler.onShowNotification(data);\n });\n\n sandbox.on('complete:stat', function(data) {\n statCallback(data);\n });\n\n sandbox.on('change:orientation', function(data) {\n debug.info('change:orientation', data.body.type);\n\n if (data.body.type === 'landscape') {\n requestFullscreen();\n } else {\n cancelFullscreen();\n }\n // customUI.fullscreen.toggle(data.body.fullscreen);\n });\n\n sandbox.on('request:pip', function() {\n cancelFullscreen();\n });\n\n sandbox.on('hide:controller', function() {\n activateCustomUI(false);\n });\n\n sandbox.on('show:container', function() {\n customUI.container.show();\n });\n\n sandbox.on('hide:container', function() {\n customUI.container.hide();\n });\n\n sandbox.on('show:rating', function() {\n customUI.rating.show();\n });\n\n sandbox.on('hide:rating', function() {\n customUI.rating.hide();\n });\n },\n gestureEvent: function() {\n var progressbar, doc;\n\n if (!EL.PROGRESSBAR) {\n return;\n }\n\n progressbar = window.gesture.GestureListener(EL.PROGRESSBAR);\n doc = window.gesture.GestureListener(document);\n\n progressbar.onGestureStart(function(session) {\n if (!env.isAdType && env.controls) {\n handler.onTouchStartProgress(session.targetEvent);\n }\n });\n\n progressbar.onGestureMove(function(session) {\n if (!env.isAdType && env.controls) {\n handler.onTouchMoveProgressPoint(session.targetEvent);\n }\n });\n\n progressbar.onGestureEnd(function(session) {\n if (!env.isAdType && env.controls) {\n handler.onTouchEndProgress(session.targetEvent);\n }\n });\n\n doc.onGestureMove(function(session) {\n handler.onTouchMoveProgressPoint(session.targetEvent);\n });\n\n doc.onGestureEnd(function(session) {\n if (state.seeking) {\n handler.onTouchEndProgress(session.targetEvent);\n }\n });\n }\n };\n\n function Inline() {}\n\n Inline.prototype.init = function(player, sandbox) {\n var isSupportCustomController = helpers.device.isSupportCustomController(ua);\n var connection = helpers.webapi.network.getConnection();\n fullscreenHelper = helpers.fullscreen(EL.PLAYER_CONTAINER, player.videoElement);\n\n debug.tooltip('Support custom ui: ', isSupportCustomController);\n debug.tooltip('browser info : ', ua.browser.name + ' / ' + ua.browser.version.info);\n debug.tooltip('ua platform : ', ua.platform + ', ' + ua.os.name);\n debug.tooltip('network type : ', connection && connection.type);\n debug.tooltip('isAllowContentAcessTalkWebView : ', helpers.device.isAllowContentAcessTalkWebView());\n debug.log('[view:inline] initialized');\n\n if (isSupportCustomController) {\n applyParameters();\n hideDefaultControl();\n\n listener.viewEvent();\n } else {\n showDefaultControl();\n }\n\n if (!helpers.device.isSupportMutedControl(ua)) {\n dt.classList.add(EL.AD_MUTE_BUTTON, 'hide');\n dt.classList.add(EL.AD_UNMUTE_BUTTON, 'hide');\n dt.classList.add(EL.MUTE_BUTTON, 'hide');\n dt.classList.add(EL.UNMUTE_BUTTON, 'hide');\n }\n\n listener.customEvent(sandbox);\n listener.gestureEvent();\n };\n\n Inline.prototype.setSize = function() {\n customUI.setSize();\n };\n\n Inline.prototype.reSize = function() {\n customUI.reSize();\n };\n\n Inline.prototype.showBlind = function() {\n showBlind();\n };\n\n Inline.prototype.hideBlind = function() {\n hideBlind();\n };\n\n Inline.prototype.showNotification = function(message, callback) {\n showNotification(message, callback);\n };\n\n Inline.prototype.startSpinner = function() {\n startSpinner();\n };\n\n Inline.prototype.endSpinner = function() {\n endSpinner();\n };\n\n Inline.prototype.showAd = function() {\n customUI.ad.show();\n };\n\n Inline.prototype.hideAd = function() {\n customUI.ad.hide();\n };\n\n Inline.prototype.setupAd = function() {\n state.skipAdEnabled = false;\n customUI.ad.reset();\n customUI.ad.setup();\n };\n\n Inline.prototype.setupVideoControl = function() {\n var video = state.currentVideo;\n var storeChart = helpers.store.get(CHART_KEY);\n\n if (video.wasLive) {\n customUI.control.showReplay();\n } else {\n customUI.control.hideReplay();\n }\n\n if (video.isFullVod) {\n customUI.control.showFull();\n } else {\n customUI.control.hideFull();\n }\n\n var duration = player.getDurationRound();\n\n dt.classList.remove(EL.PLAYER_CONTROLLER, 'ad_type');\n\n if (env.isAdType || env.miniProgress) {\n dt.classList.add(EL.PLAYER_CONTROLLER, 'mini_progress');\n } else {\n customUI.control.setDuration(duration);\n customUI.control.setCurrentTime(0, duration);\n customUI.progress.updatePlay(0);\n\n if (state.allAdsCompleted) {\n customUI.control.setCurrentTime(duration, duration);\n customUI.progress.updatePlay(100);\n }\n\n dt.classList.remove(EL.PLAYER_CONTROLLER, 'mini_progress');\n\n if (ua.platform === 'pc' && env.isPrivateIp && !env.popup && !ua.browser.msie) {\n contextMenu.showAnalyticButton();\n customUI.control.showChartButton();\n\n if (!state.isPostrollEnded && storeChart !== 'false') {\n exports.queue.emit('analytics:chart', false);\n }\n }\n }\n };\n\n Inline.prototype.setupAdControl = function() {\n var duration = player.getDurationRound();\n\n customUI.control.setDuration(duration);\n customUI.control.setCurrentTime(0, player.getDurationRound());\n customUI.progress.updatePlay(0);\n\n dt.classList.add(EL.PLAYER_CONTROLLER, 'ad_type');\n\n if (ua.platform !== 'pc' && !isFullScreen()) {\n customUI.control.hide();\n } else {\n contextMenu.hideAnalyticButton();\n customUI.control.hideChartButton();\n }\n };\n\n Inline.prototype.setupLiveControl = function() {\n dt.classList.remove(EL.PLAYER_CONTROLLER, 'ad_type');\n if (EL.PLAY_TIME_CONTAINER) {\n dt.classList.add(EL.PLAY_TIME_CONTAINER, 'hide');\n }\n if (EL.PLAY_PROGRESS) {\n dt.classList.add(EL.PLAY_PROGRESS, 'hide');\n }\n\n if (!liveStatTimeout) {\n updateStat();\n }\n };\n\n Inline.prototype.showControl = function(isfreeze) {\n activateCustomUI(true, isfreeze);\n };\n\n Inline.prototype.showAdControl = function(isPaused) {\n activateAdPlayPause(isPaused);\n };\n\n Inline.prototype.hideActivatedControl = function() {\n activateCustomUI(false);\n };\n\n Inline.prototype.hideControl = function() {\n hideControl();\n };\n\n Inline.prototype.clearTimer = function() {\n customUI.control.clearTimer();\n };\n\n Inline.prototype.resizeControl = function() {\n resizeControl();\n };\n\n Inline.prototype.showControlHead = function() {\n showControlHead();\n };\n\n Inline.prototype.hideControlHead = function() {\n hideControlHead();\n };\n\n Inline.prototype.showControlFooter = function() {\n showControlFoot();\n };\n\n Inline.prototype.onTimeUpdate = function(currentTime, duration) {\n var video = queue.front;\n\n if (state.seeking) {\n customUI.control.setCurrentTime(currentTime, duration);\n return;\n }\n\n updateTime(currentTime, duration);\n\n if (video && video.type === constants.VIDEO_TYPE.VOD) {\n checkNextVideo(currentTime, duration);\n } else if (video && video.type === constants.VIDEO_TYPE.AD) {\n if (video.timeOffset !== 'end') {\n updateAdSkipTime();\n }\n }\n };\n\n Inline.prototype.updateProgressTime = function(currentTime, duration) {\n updateTime(currentTime, duration);\n };\n\n Inline.prototype.onProgress = function(loadEndPercentage) {\n updateLoad(loadEndPercentage);\n };\n\n Inline.prototype.onEndVideo = function() {\n var video = state.currentVideo;\n\n if (ua.platform !== 'pc' && state.hasStillVideo) {\n hideStillVideo();\n customUI.control.showExtension();\n customUI.control.hideDimmedLayer();\n customUI.tvod.hide();\n if (env.controls) {\n customUI.control.showSeeking();\n customUI.control.showPlayPause();\n }\n\n if (EL.TIME_POINT) {\n dt.classList.add(EL.TIME_POINT, 'hide');\n }\n }\n\n if (video.purchase) {\n var info = {\n checkUrl: video.purchase.purchaseLink,\n message: video.purchase.guideMessage,\n code: 'NeedPurchased',\n type: 'onError',\n preview: true\n };\n error.showError(CONFIRM_STATUS.NeedPurchased.NAME, info);\n } else if (env.rel && state.hasRelated) {\n exports.queue.emit('show:completion');\n exports.queue.emit('hide:modal');\n\n if (video.type === 'LIVE') {\n if (isFullScreen()) {\n cancelFullscreen();\n }\n\n error.showError(ERROR_STATUS.LiveFinished.NAME, {});\n } else {\n activateCustomUI(false);\n }\n } else {\n var isAutoPlay = false;\n var startTime = 0;\n var isiOSOver14 = helpers.device.isiOSOver14(ua);\n\n if (state.abr) {\n shaka.unload();\n }\n\n if (!isiOSOver14 || (isiOSOver14 && !isFullScreen())) {\n exports.queue.emit('load:videoById:withPlayerUnload', startTime, isAutoPlay);\n }\n }\n };\n\n Inline.prototype.onSeeked = function() {\n onSeeked();\n };\n\n Inline.prototype.requestFullscreen = function() {\n requestFullscreen();\n };\n\n Inline.prototype.cancelFullscreen = function() {\n cancelFullscreen();\n };\n\n Inline.prototype.isFullScreen = function() {\n return isFullScreen();\n };\n\n Inline.prototype.isFullScreenSupport = function() {\n return isFullScreenSupport();\n };\n\n Inline.prototype.togglePlayPause = function(isPaused) {\n if (state.preventTogglePlayPause) {\n return;\n }\n\n if (isPaused) {\n if (state.ended) {\n dt.classList.add(EL.PAUSE_BUTTON, 'hidden');\n dt.classList.remove(EL.PLAY_BUTTON, 'hidden');\n } else {\n dt.classList.remove(EL.PLAY_BUTTON, 'hidden');\n dt.classList.add(EL.PAUSE_BUTTON, 'hidden');\n }\n } else {\n dt.classList.add(EL.PLAY_BUTTON, 'hidden');\n dt.classList.remove(EL.PAUSE_BUTTON, 'hidden');\n }\n };\n\n Inline.prototype.toggleAdPlayPause = function(isPaused) {\n if (player.getCurrentTime() > 0) {\n customUI.ad.showButton();\n }\n\n toggleAdPlayPause(isPaused);\n };\n\n Inline.prototype.getClipLocation = function(profile, callback) {\n getClipLocation(profile, callback);\n };\n\n Inline.prototype.getLiveLocation = function(profile, callback) {\n getLiveLocation(profile, callback);\n };\n\n Inline.prototype.setupNonLinearAd = function(ad) {\n setupNonLinearAd(ad);\n };\n\n Inline.prototype.setupMidrollAd = function(index, isStarted, timeOffset) {\n setupMidrollAd(index, isStarted, timeOffset);\n };\n\n Inline.prototype.removeMidrollPoint = function() {\n removeMidrollPoint();\n };\n\n Inline.prototype.showNonLinearAd = function(isStarted, adType) {\n showNonLinearAd(isStarted, adType);\n };\n\n Inline.prototype.hideNonLinearAd = function() {\n hideNonLinearAd();\n };\n\n Inline.prototype.pauseNonLinearAd = function() {\n pauseNonLinearAd();\n };\n\n Inline.prototype.resumeNonLinearAd = function() {\n resumeNonLinearAd();\n };\n\n Inline.prototype.showLinearAdContainer = function() {\n showLinearAdContainer();\n };\n\n Inline.prototype.hideLinearAdContainer = function() {\n hideLinearAdContainer();\n };\n\n Inline.prototype.showNonLinearAdContainer = function() {\n showNonLinearAdContainer();\n };\n\n Inline.prototype.hideNonLinearAdContainer = function() {\n hideNonLinearAdContainer();\n };\n\n Inline.prototype.setProfile = function(profile) {\n setProfile(profile);\n };\n\n Inline.prototype.setStillVideo = function(seekUrl, callback) {\n setStillVideo(seekUrl, callback);\n };\n\n Inline.prototype.showStillVideo = function() {\n showStillVideo();\n };\n\n Inline.prototype.hideStillVideo = function() {\n hideStillVideo();\n };\n\n Inline.prototype.onLoadStart = function() {\n var video = queue.front;\n if (video.type === constants.VIDEO_TYPE.VOD) {\n setSeekThumbnail();\n }\n };\n\n Inline.prototype.toggleMuteUI = function(muteOn) {\n toggleMuteUI(muteOn);\n };\n\n Inline.prototype.getRecentMute = function() {\n return getRecentMute();\n };\n\n Inline.prototype.getRecentVolume = function() {\n return getRecentVolume();\n };\n\n Inline.prototype.setRecentVolume = function(volume) {\n setRecentVolume(volume);\n };\n\n Inline.prototype.saveRecentMute = function(muteOn) {\n saveRecentMute(muteOn);\n };\n\n Inline.prototype.onCompleteMeta = function() {\n setShowTitle();\n setKakaoTVLink();\n setRatingLevel();\n toggleProfile();\n toggleAppLink();\n };\n\n Inline.prototype.setKakaoTVLink = function() {\n setKakaoTVLink();\n };\n\n Inline.prototype.setRatingLevel = function() {\n setRatingLevel();\n };\n\n Inline.prototype.setVolume = function(volume, muteOn) {\n setVolume(volume, muteOn);\n };\n\n Inline.prototype.hideDefaultControl = function() {\n hideDefaultControl();\n };\n\n Inline.prototype.setAriaAttr = function() {\n if (EL.PLAYER_CONTROLLER_TOGGLE_BUTTON) {\n a11y.removeAria(EL.PLAYER_CONTROLLER_TOGGLE_BUTTON, 'hidden');\n }\n a11y.removeAria(player.videoElement, 'hidden');\n a11y.setAria(player.videoElement, 'describedby', 'videoDesc');\n };\n\n Inline.prototype.resetAriaAttr = function() {\n if (EL.PLAYER_CONTROLLER_TOGGLE_BUTTON) {\n a11y.setAria(EL.PLAYER_CONTROLLER_TOGGLE_BUTTON, 'hidden', 'true');\n }\n a11y.setAria(player.videoElement, 'hidden', 'true');\n a11y.removeAria(player.videoElement, 'describedby');\n };\n\n Inline.prototype.hideVideoCursor = function() {\n defaultUI.video.hideCursor();\n };\n\n Inline.prototype.showVideoCursor = function() {\n defaultUI.video.showCursor();\n };\n\n Inline.prototype.openPopup = function(url, name, features) {\n openPopup(url, name, features);\n };\n\n Inline.prototype.setShowTitle = function() {\n setShowTitle();\n };\n\n Inline.prototype.setDuration = function(duration) {\n customUI.control.setDuration(duration);\n };\n\n Inline.prototype.setTvod = function(data) {\n customUI.tvod.setTvodData(data);\n };\n\n Inline.prototype.showTvod = function() {\n customUI.tvod.show();\n };\n\n Inline.prototype.hideTvod = function() {\n customUI.tvod.hide();\n };\n\n Inline.prototype.hideProfile = function() {\n customUI.control.hideProfile();\n };\n\n Inline.prototype.showRating = function() {\n customUI.rating.show();\n };\n\n Inline.prototype.showWithResetRating = function() {\n customUI.rating.showWithReset();\n };\n\n Inline.prototype.hideRating = function() {\n customUI.rating.hide();\n };\n\n Inline.prototype.initVolumeControl = function() {\n initVolumeControl();\n };\n\n Inline.prototype.checkFullscreenEnabled = function() {\n checkFullscreenEnabled();\n };\n\n Inline.prototype.onPlay = function() {\n onPlay();\n };\n\n return Inline;\n })();\n\n exports.addModule('view.inline', new Inline());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var InlinePC;\n\n InlinePC = (function() {\n var state = exports.loadModule('controller.state');\n var dataLoader = exports.loadModule('playlist.dataloader');\n var shaka = exports.loadModule('player.shaka');\n var player = exports.loadModule('player.adapter');\n var queue = exports.loadModule('playlist.queue');\n var contextMenu = exports.loadModule('view.contextmenu');\n var inline = exports.loadModule('view.inline');\n var pctTracker = exports.loadModule('pct.tracker');\n var pvtTracker = exports.loadModule('pvt.tracker');\n var keyboardAddOn = exports.loadModule('addon.keyboard');\n var analytics = exports.loadModule('view.analytics');\n var playerTemplate = exports.template;\n\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n\n var ID = {\n CLIP_INFO_MODIFY: 'clipInfoModify',\n CLIP_INFO_PANEL: 'clipInfoPanel',\n CLIP_COVER_PANEL: 'clipCoverImagePanel'\n };\n\n var KEYBOARD_TYPE = {\n FRONT_5S: 'ico_front5s',\n BACK_5S: 'ico_back5s',\n FRONT_60S: 'ico_front60s',\n BACK_60S: 'ico_back60s',\n VOLUME_MUTE: 'ico_volumeno',\n VOLUME_DOWN: 'ico_volumedown',\n VOLUME_UP: 'ico_volumeup',\n SPEED_DOWN: 'ico_speeddown',\n SPEED_UP: 'ico_speedup'\n };\n\n var DEFAULT_SPEED = 1.0;\n\n var EL = {\n PLAYER_CONTAINER: $('playerContainer'),\n CONTROLLER: $('controller'),\n CONTROLLER_BODY: $$('#controller .player_body')[0],\n CONTROLLER_PLAY_BUTTON: $$('.player_body button')[0],\n CONTROLLER_PLAY_BUTTON_TEXT: $$('.player_body .img_player')[0],\n PLAY_BUTTON: $$('.player_play')[0],\n REPLAY_BUTTON: $$('.player_replay')[0] || null,\n PROGRESSBAR: $('progress'),\n SOUND_CONTROL: $$('.sound_control')[0],\n VOLUME: $('volume'),\n MUTE_BUTTON: $('volumeBtn'),\n VOLUMEBAR: $('volumeBar'),\n VOLUMEBAR_BG: $('volumeBarBg'),\n VOLUME_POINT: $('pointVolume'),\n SETTING_BUTTON: $('settingBtn'),\n CHART_BUTTON: $('chartBtn'),\n WIDE_SCREEN_BUTTON: $('widescreebBtn'),\n POPUP_BUTTON: $('popupBtn'),\n SETUP_BOX: $$('.box_setup')[0],\n CHART_BOX: $$('.box_chart')[0],\n SETTING_BOX: $$('.box_setting')[0],\n MODIFY_BUTTON: $$('.box_setting .clip_modify')[0],\n AUTOPLAY_CHECK: $$('.box_setting .clip_autoplay')[0],\n STILL_IMAGE: $('stillImage'),\n AUTO_PLAY: $('autoPlay'),\n STILL_IMAGE_LIST: $$('#stillImage .list_section')[0],\n PUBLIC_MODE: $('publicMode'),\n CLIP_INFO_MODIFY: $(ID.CLIP_INFO_MODIFY) || null,\n CLIP_INFO_PANEL: $(ID.CLIP_INFO_PANEL) || null,\n CLIP_COVER_PANEL: $(ID.CLIP_COVER_PANEL) || null,\n PLAYER_FUNCTION: $$('.player_function')[0],\n AD_CONTROLLER: $('adController'),\n QUALITY_BOX: $$('.box_quality')[0],\n QUALITY_BUTTON: $$('.box_setting .btn_quality')[0],\n QUALITY_LIST: $$('.list_quality')[0],\n QUALITY_TEXT: $$('.txt_quality')[0],\n QUALITY_TITLE: $$('.box_quality .tit_quality')[0],\n SPEED_BOX: $$('.box_setup .box_playspeed')[0],\n MENU_SPEED_BUTTON: $$('.box_setting .clip_speed')[0],\n SUBTITLE_BOX: $$('.box_setup .box_subtitles')[0],\n SUBTITLE_TEXT: $('current_subtitle'),\n SUBTITLE_LIST: $$('.list_subtitles')[0],\n MENU_SUBTITLE_BUTTON: $$('.box_setting .lang_subtitles')[0],\n SUBTITLE_BUTTON: $$('.box_setting .btn_langsubtitles')[0],\n MENU_QUALITY_BUTTON: $$('.box_setting .dp_quality')[0],\n SPEED_TITLE: $$('.box_playspeed .tit_playspeed')[0],\n SPEED_LIST: $$('.list_playspeed')[0],\n SPEED_TEXT: $('current_speed'),\n KEYBOARD_EFFECT: $$('.player_body .ico_keyboard')[0],\n MIRRORING_TEXT: $$('.txt_mirroring')[0],\n ALERT_LIVEAGENT: $('alertLiveAgent')\n };\n\n var PROFILE_KEY = constants.STORAGE.PROFILE;\n var SUBTITLE_KEY = constants.STORAGE.SUBTITLE;\n var MINI_PLAYER_MAX_WIDTH = 500;\n\n var customUI = {\n control: {\n playback: {\n el: EL.CONTROLLER_PLAY_BUTTON,\n timer: null,\n show: function() {\n var self = this;\n dt.classList.remove(this.el, 'hide');\n\n this.timer = setTimeout(function() {\n self.hide();\n self.timer = null;\n }, 500);\n },\n hide: function() {\n dt.classList.add(this.el, 'hide');\n }\n },\n volume: {\n el: EL.MUTE_BUTTON,\n timer: null,\n show: function() {\n dt.classList.add(EL.SOUND_CONTROL, 'open');\n },\n hide: function() {\n dt.classList.remove(EL.SOUND_CONTROL, 'open');\n },\n mute: function(muted) {\n if (muted) {\n dt.classList.remove(this.el, 'btn_sound');\n dt.classList.add(this.el, 'btn_soundoff');\n this.el.setAttribute('aria-label', '음소거 해제');\n this.el.nextElementSibling.innerHTML = '음소거 해제';\n } else {\n dt.classList.remove(this.el, 'btn_soundoff');\n dt.classList.add(this.el, 'btn_sound');\n this.el.setAttribute('aria-label', '음소거');\n this.el.nextElementSibling.innerHTML = '음소거';\n }\n },\n update: function(volume) {\n var volumeRate = (volume * 100).toFixed(2) + '%';\n\n EL.VOLUMEBAR.style['width'] = volumeRate;\n EL.SOUND_CONTROL.setAttribute('aria-valuetext', volumeRate);\n }\n },\n profile: {\n el: EL.QUALITY_LIST,\n timer: null,\n template: {\n profileList: playerTemplate.pc_profile_list,\n supHD: playerTemplate.superscript_hd,\n sup4K: playerTemplate.superscript_4k,\n profileText: playerTemplate.profile_text\n },\n create: function(outputs) {\n var supHDTemplate = this.template.supHD;\n var sup4KTemplate = this.template.sup4K;\n\n var view = {\n outputs: []\n };\n\n var profile, profileLabel;\n\n for (var i = outputs.length - 1; i >= 0; i--) {\n profile = outputs[i].profile.toString();\n profileLabel = outputs[i].label;\n\n if (profile === state.currentVideo.profile) {\n this.updateLabel(profileLabel);\n }\n\n if (profile !== 'AUDIO') {\n view.outputs.push({\n profileOn: profile === state.currentVideo.profile ? 'on' : '',\n profileName: profile,\n profileLabel: this.removeText(profileLabel),\n supHD: (function() {\n if (profileLabel.indexOf('HD') >= 0) {\n return supHDTemplate.render();\n } else {\n return '';\n }\n })(),\n sup4K: (function() {\n if (profileLabel.indexOf('4K') >= 0) {\n return sup4KTemplate.render();\n } else {\n return '';\n }\n })()\n });\n }\n }\n\n var fragment = this.createTemplate(view);\n this.render(fragment);\n },\n createTemplate: function(view) {\n var template = this.template.profileList;\n return template.render(view);\n },\n render: function(htmlStr) {\n EL.QUALITY_LIST.innerHTML = htmlStr;\n },\n showList: function() {\n dt.classList.add(EL.QUALITY_BOX, 'open');\n },\n hideList: function() {\n dt.classList.remove(EL.QUALITY_BOX, 'open');\n },\n removeText: function(text) {\n var re = / |P|HD|4K/g;\n return text.replace(re, '');\n },\n updateLabel: function(label) {\n var profileAuto = state.currentVideo.profile === constants.PROFILE.AUTO;\n var labelString = profileAuto\n ? this.removeText(shaka.getCurrentProfile())\n : this.removeText(label);\n var supHD = profileAuto\n ? shaka.getCurrentProfile().indexOf('HD') !== -1\n : label.indexOf('HD') !== -1;\n var sup4K = label && label.indexOf('4K') !== -1;\n var view = {\n profileText: labelString,\n profileAuto: profileAuto,\n profileHD: supHD,\n profile4K: sup4K\n };\n var labelHTML = this.template.profileText.render(view);\n\n dt.classList.remove(EL.SETTING_BUTTON, 'btn_hd');\n dt.classList.remove(EL.SETTING_BUTTON, 'btn_4k');\n\n if (supHD) {\n dt.classList.add(EL.SETTING_BUTTON, 'btn_hd');\n } else if (sup4K) {\n dt.classList.add(EL.SETTING_BUTTON, 'btn_4k');\n }\n\n EL.QUALITY_TEXT.innerHTML = labelHTML;\n }\n },\n setting: {\n el: EL.SETUP_BOX,\n show: function() {\n dt.classList.add(this.el, 'open');\n },\n hide: function() {\n dt.classList.remove(this.el, 'open');\n },\n showAutoPlay: function() {\n if (EL.AUTOPLAY_CHECK) {\n dt.classList.remove(EL.AUTOPLAY_CHECK, 'hide');\n }\n },\n hideAutoPlay: function() {\n if (EL.AUTOPLAY_CHECK) {\n dt.classList.add(EL.AUTOPLAY_CHECK, 'hide');\n }\n },\n showDpQualityButton: function() {\n if (EL.MENU_QUALITY_BUTTON) {\n dt.classList.remove(EL.MENU_QUALITY_BUTTON, 'hide');\n }\n },\n hideDpQualityButton: function() {\n if (EL.MENU_QUALITY_BUTTON) {\n dt.classList.add(EL.MENU_QUALITY_BUTTON, 'hide');\n }\n },\n showSubtitleButton: function() {\n if (EL.MENU_SUBTITLE_BUTTON) {\n dt.classList.remove(EL.MENU_SUBTITLE_BUTTON, 'hide');\n }\n },\n hideSubtitleButton: function() {\n if (EL.MENU_SUBTITLE_BUTTON) {\n dt.classList.add(EL.MENU_SUBTITLE_BUTTON, 'hide');\n }\n },\n showSpeedButton: function() {\n if (EL.MENU_SPEED_BUTTON) {\n dt.classList.remove(EL.MENU_SPEED_BUTTON, 'hide');\n }\n },\n hideSpeedButton: function() {\n if (EL.MENU_SPEED_BUTTON) {\n dt.classList.add(EL.MENU_SPEED_BUTTON, 'hide');\n }\n }\n },\n stillImage: {\n el: EL.STILL_IMAGE,\n template: playerTemplate.still_image,\n create: function(thumbnails) {\n var image = '';\n var seconds = 0;\n var maxLength = thumbnails.length > 6 ? 6 : thumbnails.length;\n\n var view = {\n thumbnails: []\n };\n\n for (var i = 0; i < maxLength; i++) {\n seconds = thumbnails[i].timeInSec;\n\n if (thumbnails[i].thumbnailUrl) {\n image =\n '//t1.daumcdn.net/thumb/C180x100/?fname=' +\n encodeURIComponent(thumbnails[i].thumbnailUrl);\n }\n\n view.thumbnails.push({\n seconds: seconds,\n imageSrc: image,\n time: helpers.string.delimitTimes(seconds)\n });\n }\n\n var fragment = this.createTemplate(view);\n this.render(fragment);\n },\n createTemplate: function(view) {\n return this.template.render(view);\n },\n render: function(htmlStr) {\n EL.STILL_IMAGE_LIST.innerHTML = htmlStr;\n },\n show: function() {\n dt.classList.remove(this.el, 'hide');\n },\n hide: function() {\n dt.classList.add(this.el, 'hide');\n },\n on: function() {\n dt.classList.add(this.el, 'on');\n },\n off: function() {\n dt.classList.remove(this.el, 'on');\n }\n },\n menu: {\n template: playerTemplate.clip_cover_image,\n activateTab: $$('#clipInfoModify .on a')[0] || null,\n showClipInfo: function() {\n dt.classList.remove(EL.CLIP_INFO_PANEL, 'hide');\n dt.classList.add(EL.CLIP_COVER_PANEL, 'hide');\n },\n showClipCover: function() {\n dt.classList.remove(EL.CLIP_COVER_PANEL, 'hide');\n dt.classList.add(EL.CLIP_INFO_PANEL, 'hide');\n },\n setClipInfo: function() {\n var lblName = $('lblName');\n var scrapChecked = $$('input[name=\"scrapAllow\"]');\n var openedChecked = $$('input[name=\"isOpen\"]');\n\n var video = state.currentVideo;\n\n if (video.canScrap) {\n scrapChecked[0].checked = true;\n }\n\n if (video.isLegacy) {\n dt.classList.add(EL.PUBLIC_MODE, 'hide');\n\n for (var i = 0, len = openedChecked.length; i < len; i++) {\n var r = openedChecked[i];\n r.checked = false;\n r.disabled = true;\n }\n } else {\n dt.classList.remove(EL.PUBLIC_MODE, 'hide');\n\n if (video.isOpen) {\n openedChecked[0].checked = true;\n }\n }\n\n lblName.value = video.title;\n },\n setClipCover: function(thumbnails) {\n var image = '';\n var maxLength = thumbnails.length > 6 ? 6 : thumbnails.length;\n\n if (thumbnails.length < 1) {\n return;\n }\n\n var view = {\n thumbnails: []\n };\n\n for (var i = 0; i < maxLength; i++) {\n if (thumbnails[i].thumbnailUrl) {\n image =\n '//t1.daumcdn.net/thumb/C180x100/?fname=' +\n encodeURIComponent(thumbnails[i].thumbnailUrl);\n }\n\n view.thumbnails.push({\n className: thumbnails[i].isDefault ? 'on' : '',\n imageIndex: i,\n imageSrc: image\n });\n }\n\n var target = $$('.list_cover', EL.CLIP_COVER_PANEL)[0];\n var fragment = this.createTemplate(view);\n\n this.render(target, fragment);\n },\n createTemplate: function(view) {\n return this.template.render(view);\n },\n render: function(target, htmlStr) {\n target.innerHTML = htmlStr;\n },\n submitClipInfo: function() {\n var scrapCheck = $$('input[name=\"scrapAllow\"]');\n var openedCheck = $$('input[name=\"isOpen\"]');\n var title = $('lblName').value;\n var clipId = state.currentVideo.clipId;\n var isOpen = openedCheck[0].checked;\n var canScrap = scrapCheck[0].checked;\n\n var options = {\n title: title,\n id: clipId,\n canScrap: canScrap,\n isOpen: isOpen\n };\n dataLoader.updateClipInfo(clipId, options);\n },\n submitClipCover: function(index) {\n var clipId = state.currentVideo.clipId;\n\n var options = {\n isDefault: true\n };\n dataLoader.updateClipCover(clipId, options, index);\n },\n selectTab: function(targetId) {\n if (targetId) {\n dt.classList.remove(this.activateTab.parentNode, 'on');\n\n var selectedTab = $$('a[href=\"#' + targetId + '\"]')[0];\n dt.classList.add(selectedTab.parentNode, 'on');\n\n this.activateTab = selectedTab;\n }\n },\n togglePanel: function(target) {\n if ($(target) === EL.CLIP_INFO_PANEL) {\n this.showClipInfo();\n }\n\n if ($(target) === EL.CLIP_COVER_PANEL) {\n this.showClipCover();\n }\n }\n },\n screen: {\n showWide: function() {\n if (EL.WIDE_SCREEN_BUTTON) {\n dt.classList.remove(EL.WIDE_SCREEN_BUTTON, 'hide');\n }\n },\n hideWide: function() {\n if (EL.WIDE_SCREEN_BUTTON) {\n dt.classList.add(EL.WIDE_SCREEN_BUTTON, 'hide');\n }\n }\n },\n popup: {\n el: EL.POPUP_BUTTON,\n show: function() {\n dt.classList.remove(EL.POPUP_BUTTON, 'hide');\n },\n hide: function() {\n dt.classList.add(EL.POPUP_BUTTON, 'hide');\n }\n },\n subtitle: {\n el: EL.SUBTITLE_BOX,\n template: playerTemplate.pc_subtitle_list,\n create: function(textTracks) {\n var view = {\n textTracks: []\n };\n\n textTracks.forEach(function(v) {\n var isoCode = v.language.substr(0, 2);\n if (window.ISO6391.getNativeName(isoCode)) {\n view.textTracks.push({\n subtitle: v.language,\n subtitleText: window.ISO6391.getNativeName(isoCode)\n });\n }\n });\n\n if (view.textTracks.length > 0) {\n EL.SUBTITLE_LIST.innerHTML = this.template.render(view);\n customUI.control.setting.showSubtitleButton();\n }\n },\n showList: function() {\n if (this.el) {\n dt.classList.add(this.el, 'open');\n }\n },\n hideList: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'open');\n }\n },\n setSubtitleText: function(subtitle) {\n var preSubtitleElement = $$('.list_subtitles .on', this.el)[0];\n var el = $$('[data-subtitle=\"' + subtitle + '\"]', this.el)[0];\n\n if (preSubtitleElement) {\n dt.classList.remove(preSubtitleElement, 'on');\n }\n\n if (el) {\n dt.classList.add(el.parentElement, 'on');\n }\n\n if (EL.SUBTITLE_TEXT) {\n EL.SUBTITLE_TEXT.innerText =\n subtitle === constants.SUBTITLE.STATUS.OFF\n ? '사용안함'\n : window.ISO6391.getNativeName(subtitle);\n }\n }\n },\n speed: {\n el: EL.SPEED_BOX,\n showList: function() {\n if (this.el) {\n dt.classList.add(this.el, 'open');\n }\n },\n hideList: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'open');\n }\n },\n setSpeedText: function(speed) {\n if (this.el) {\n var preSpeedElement = $$('.list_playspeed .on', this.el)[0];\n var el = $$('[data-speed=\"' + speed + '\"]', this.el)[0];\n\n if (preSpeedElement) {\n dt.classList.remove(preSpeedElement, 'on');\n }\n\n if (el) {\n dt.classList.add(el.parentElement, 'on');\n }\n }\n\n if (EL.SPEED_TEXT) {\n if (parseFloat(speed) === DEFAULT_SPEED) {\n speed = '보통';\n }\n EL.SPEED_TEXT.innerText = speed;\n }\n }\n },\n keyboard: {\n el: EL.KEYBOARD_EFFECT,\n timer: null,\n type: null,\n template: playerTemplate.keyboard_effect_text,\n setup: function(type, text) {\n dt.classList.remove(this.el, this.type);\n dt.classList.add(this.el, type);\n\n if (text) {\n if (type === KEYBOARD_TYPE.SPEED_UP || type === KEYBOARD_TYPE.SPEED_DOWN) {\n this.el.innerHTML = this.template.render({ className: 'speed_txt', effectText: text });\n } else if (type === KEYBOARD_TYPE.VOLUME_UP || type === KEYBOARD_TYPE.VOLUME_DOWN) {\n this.el.innerHTML = this.template.render({ className: 'volume_txt', effectText: text });\n } else {\n this.el.innerHTML = text;\n }\n } else {\n this.el.innerHTML = '';\n }\n\n this.type = type;\n },\n show: function() {\n var self = this;\n if (!this.timer) {\n dt.classList.remove(this.el, 'hide');\n\n this.timer = setTimeout(function() {\n self.timer = null;\n self.hide();\n }, 500);\n }\n },\n hide: function() {\n dt.classList.add(this.el, 'hide');\n }\n },\n tv: {\n showMirroringText: function() {\n if (EL.MIRRORING_TEXT) {\n dt.classList.remove(EL.MIRRORING_TEXT, 'hide');\n }\n },\n hideMirroringText: function() {\n if (EL.MIRRORING_TEXT) {\n dt.classList.add(EL.MIRRORING_TEXT, 'hide');\n }\n }\n },\n install: {\n template: playerTemplate.install_agent,\n setupView: function(profile) {\n if (EL.ALERT_LIVEAGENT) {\n EL.ALERT_LIVEAGENT.innerHTML = this.template.render({\n installExt: player.isInstalledExtension(),\n profile: profile,\n isChromePC: ua.platform === 'pc' && ua.browser.chrome\n });\n }\n }\n }\n }\n };\n\n var control = customUI.control;\n var existRelatedTimer = null;\n\n function setVolume(volume, muteOn) {\n inline.setVolume(volume, muteOn);\n updateVolumeUI(volume);\n }\n\n function toggleMuteUI(volume, muteOn) {\n muteVolumeUI(muteOn);\n updateVolumeUI(muteOn ? 0 : volume);\n }\n\n function muteVolumeUI(muteOn) {\n control.volume.mute(muteOn);\n }\n\n function updateVolumeUI(volume) {\n control.volume.update(volume);\n }\n\n function updateVolume(rate) {\n var volume = (rate / 100).toFixed(2);\n var muteOn = checkMuteRange(rate);\n\n debug.info('updateVolume', volume, muteOn);\n setVolume(volume, muteOn);\n }\n\n function initVolumeControl() {\n var muteOn = inline.getRecentMute();\n var volume = muteOn ? 0 : getRecentVolume();\n setVolume(volume, muteOn);\n }\n\n function getRecentVolume() {\n return inline.getRecentVolume();\n }\n\n function setRecentVolume(volume) {\n inline.setRecentVolume(volume);\n }\n\n function initModifyButton() {\n var isOwner = state.currentVideo.owner;\n var isLive = state.currentVideo.type === constants.VIDEO_TYPE.LIVE;\n\n if (isOwner && !isLive) {\n dt.classList.remove(EL.MODIFY_BUTTON, 'hide');\n } else {\n dt.classList.add(EL.MODIFY_BUTTON, 'hide');\n }\n }\n\n function createProfileList() {\n var outputList = state.currentVideo.outputList;\n\n if (outputList && outputList.length > 0) {\n control.profile.create(outputList);\n }\n }\n\n function createSubtitle() {\n var textTracks = player.getTextTracks();\n\n if (textTracks.length > 0) {\n control.subtitle.create(textTracks);\n }\n }\n\n function setClipInfoAndCover() {\n var thumbnailList = state.currentVideo.thumbnailList;\n if (thumbnailList && thumbnailList.length > 0) {\n control.menu.setClipCover(thumbnailList);\n }\n control.menu.setClipInfo();\n }\n\n function setProfileLabel(label) {\n EL.QUALITY_BUTTON.setAttribute('data-label-temp', label);\n }\n\n function checkRectSize(rect) {\n if (rect.height < 1) {\n var resizeRect = {};\n for (var o in rect) {\n if (rect.hasOwnProperty(o)) {\n resizeRect[o] = rect[o] * 100;\n }\n }\n return resizeRect;\n }\n return rect;\n }\n\n function getVolumeRate(e) {\n var rect = EL.VOLUMEBAR_BG.getBoundingClientRect();\n if (inline.isFullScreen()) {\n rect = checkRectSize(rect);\n }\n\n var pageX = e.pageX;\n var offsetLeft = Math.floor(rect.left);\n var offsetX = pageX && pageX - offsetLeft;\n var offsetWidth = rect.width;\n var rate = 0;\n\n if (offsetX > offsetWidth) {\n rate = 100;\n }\n\n if (offsetX >= 0 && offsetX <= offsetWidth) {\n rate = (offsetX / offsetWidth) * 100;\n }\n\n return rate;\n }\n\n function checkMuteRange(rate) {\n return rate < 10;\n }\n\n function onTouchMoveVolume(e) {\n var rate = getVolumeRate(e);\n updateVolume(rate);\n\n state.volumeChanging = true;\n inline.clearTimer();\n }\n\n function onTouchEndVolume(e) {\n var rate = getVolumeRate(e);\n var muteOn = checkMuteRange(rate);\n\n updateVolume(rate);\n setRecentVolume(player.getVolume());\n inline.saveRecentMute(muteOn);\n\n state.volumeChanging = false;\n\n pctTracker.track('volume', parseInt(rate));\n }\n\n function applyParameters() {\n if (!env.isInternal || env.popup) {\n control.setting.hideAutoPlay();\n control.screen.hideWide();\n }\n\n if (env.popup) {\n control.popup.hide();\n control.screen.hideWide();\n }\n }\n\n function existRelatedClip() {\n existRelatedTimer = setTimeout(function() {\n var isfreeze = true;\n inline.showControl(isfreeze);\n inline.resizeControl();\n showCompletion();\n }, 300);\n }\n\n function showCompletion() {\n exports.queue.emit('show:completion');\n }\n\n function openSettingBox() {\n control.setting.show();\n state.isSettingMenuOpened = true;\n dt.classList.add(EL.SETTING_BUTTON, 'open');\n }\n\n function closeSettingBox() {\n control.setting.hide();\n control.speed.hideList();\n control.subtitle.hideList();\n state.isSettingMenuOpened = false;\n dt.classList.remove(EL.SETTING_BUTTON, 'open');\n }\n\n function openChartBox() {\n analytics.chartShow();\n if (EL.CHART_BOX) {\n dt.classList.add(EL.CHART_BOX, 'open');\n }\n }\n\n function closeChartBox() {\n analytics.chartHide();\n if (EL.CHART_BOX) {\n dt.classList.remove(EL.CHART_BOX, 'open');\n }\n }\n\n function closeMenuBox() {\n control.profile.hideList();\n closeSettingBox();\n }\n\n function togglePlayback() {\n var isPaused = player.isPaused();\n if (!state.isContextMenuOpened && !state.isSettingMenuOpened) {\n if (isPaused) {\n if (state.needMidrollRequest) {\n state.needMidrollRequest = false;\n exports.queue.emit('ad:checkMidrollAd');\n }\n\n player.play();\n } else {\n player.pause();\n }\n\n togglePlayPause(isPaused);\n control.playback.show();\n pctTracker.track('play_pause');\n }\n\n if (state.isContextMenuOpened) {\n contextMenu.hide();\n }\n\n if (state.isSettingMenuOpened) {\n closeMenuBox();\n }\n }\n\n function togglePlayPause(isPaused) {\n if (isPaused) {\n if (!state.ended) {\n EL.CONTROLLER_PLAY_BUTTON_TEXT.innerHTML = '일시정지';\n dt.classList.remove(EL.CONTROLLER_PLAY_BUTTON, 'link_play');\n dt.classList.add(EL.CONTROLLER_PLAY_BUTTON, 'link_pause');\n dt.classList.add(EL.REPLAY_BUTTON, 'hidden');\n } else {\n dt.classList.add(EL.PLAY_BUTTON, 'hidden');\n dt.classList.remove(EL.REPLAY_BUTTON, 'hidden');\n }\n } else {\n EL.CONTROLLER_PLAY_BUTTON_TEXT.innerHTML = '재생하기';\n dt.classList.add(EL.CONTROLLER_PLAY_BUTTON, 'link_play');\n dt.classList.remove(EL.CONTROLLER_PLAY_BUTTON, 'link_pause');\n dt.classList.add(EL.REPLAY_BUTTON, 'hidden');\n }\n }\n\n function toggleFullScreen() {\n if (inline.isFullScreen()) {\n inline.cancelFullscreen();\n } else {\n inline.requestFullscreen();\n }\n }\n\n function setStillImage() {\n var thumbnailList = state.currentVideo.thumbnailList;\n if (thumbnailList && thumbnailList.length > 0) {\n control.stillImage.create(thumbnailList);\n }\n showStillImage();\n }\n\n function showStillImage() {\n control.stillImage.show();\n }\n\n function hideStillImage() {\n control.stillImage.hide();\n }\n\n function setStillVideo(seekUrl) {\n inline.setStillVideo(seekUrl, function() {\n showStillVideo();\n });\n }\n\n function showStillVideo() {\n inline.showStillVideo();\n }\n\n function hideStillVideo() {\n inline.hideStillVideo();\n }\n\n function setSeekThumbnail() {\n var video = state.currentVideo;\n var seekUrl = video.seekUrl;\n if (seekUrl) {\n hideStillImage();\n setStillVideo(seekUrl);\n } else {\n hideStillVideo();\n setStillImage(seekUrl);\n }\n }\n\n function getWidthOutOfRange(boxElement) {\n if (!boxElement) {\n return;\n }\n\n var buttonRect = EL.SETTING_BUTTON.getBoundingClientRect();\n var playerRect = EL.PLAYER_CONTAINER.getBoundingClientRect();\n var boxRect = boxElement.getBoundingClientRect();\n var playerMarginRight = 15;\n\n var buttonCenter = buttonRect.right - buttonRect.width / 2;\n var maxWidth = playerRect.width - playerMarginRight;\n\n return maxWidth - buttonCenter - boxRect.width / 2;\n }\n\n function moveSettingBox() {\n var settingBoxMarginLeft = -86;\n var qualityBoxMarginLeft = -43;\n var speedBoxMarginLeft = -43;\n var overOuterHalfWidth = (window.outerWidth - player.videoElement.clientWidth) / 2;\n var settingBoxOverWidth = getWidthOutOfRange(EL.SETTING_BOX) + overOuterHalfWidth;\n var qualityBoxOverWidth = getWidthOutOfRange(EL.QUALITY_BOX) + overOuterHalfWidth;\n var speedBoxOverWidth = getWidthOutOfRange(EL.SPEED_BOX) + overOuterHalfWidth;\n var isOutOfRange = settingBoxOverWidth < 0;\n\n if (isOutOfRange) {\n EL.SETTING_BOX.style.marginLeft = settingBoxMarginLeft + settingBoxOverWidth + 'px';\n EL.QUALITY_BOX.style.marginLeft = qualityBoxMarginLeft + qualityBoxOverWidth + 'px';\n EL.SPEED_BOX.style.marginLeft = speedBoxMarginLeft + speedBoxOverWidth + 'px';\n } else {\n EL.SETTING_BOX.style.marginLeft = settingBoxMarginLeft + 'px';\n EL.QUALITY_BOX.style.marginLeft = qualityBoxMarginLeft + 'px';\n EL.SPEED_BOX.style.marginLeft = speedBoxMarginLeft + 'px';\n }\n }\n\n function setSpeed(speed) {\n state.playbackRate = player.setPlaybackRate(parseFloat(speed));\n control.speed.setSpeedText(speed);\n }\n\n function resetSpeed() {\n setSpeed(DEFAULT_SPEED);\n }\n\n function setSubtitle(subtitle) {\n var selectTrack = null;\n player.getTextTracks().forEach(function(v) {\n if (v.language === subtitle) {\n selectTrack = v;\n }\n });\n\n if (selectTrack || subtitle === 'off') {\n player.setTextTrack(subtitle);\n control.subtitle.setSubtitleText(subtitle);\n }\n }\n\n function isMiniPlayer() {\n var playerWidth = document.documentElement.clientWidth;\n\n return playerWidth <= MINI_PLAYER_MAX_WIDTH;\n }\n\n function isSeekable() {\n return queue.front.type === constants.VIDEO_TYPE.VOD && !state.modalContentActivated;\n }\n\n var listener = {\n viewEvent: function() {\n var menu = control.menu;\n\n if (ua.platform === 'pc') {\n event.on(\n window,\n 'resize',\n helpers.waiter.throttle(function() {\n if (isMiniPlayer()) {\n exports.queue.emit('hide:modal');\n inline.showWithResetRating();\n\n if (env.isPrivateIp) {\n closeChartBox();\n contextMenu.videoChartToggle();\n }\n }\n }, 100)\n );\n\n event.on(EL.CONTROLLER_BODY, 'click', function() {\n togglePlayback();\n });\n\n event.on(EL.SOUND_CONTROL, 'mouseover', function() {\n if (!state.seeking) {\n control.volume.show();\n }\n });\n\n event.on(EL.SOUND_CONTROL, 'mouseout', function() {\n if (!state.volumeChanging) {\n control.volume.hide();\n }\n });\n\n event.on(EL.MUTE_BUTTON, 'click', function() {\n var muteOn = player.getMute();\n var volume = !muteOn ? 0 : getRecentVolume();\n\n if (muteOn) {\n player.setVolume(volume);\n exports.queue.emit('reset:env:mute');\n }\n\n if (state.initialState.startMuted) {\n state.initialState.startMuted = false;\n }\n\n toggleMuteUI(volume, !muteOn);\n player.setMute(!muteOn);\n inline.saveRecentMute(!muteOn);\n\n inline.clearTimer();\n pctTracker.track('mute', (!muteOn).toString());\n });\n\n event.delegate(EL.QUALITY_LIST, 'button', 'click', function(e) {\n var buttonEl, profile, label, preQualityElement;\n var isOnTv = helpers.tv.isOnTv(player.videoElement);\n\n closeMenuBox();\n\n buttonEl = e.target.tagName !== 'SUP' ? e.target : e.target.parentElement;\n profile = buttonEl.getAttribute('data-profile');\n preQualityElement = $$('.list_quality .on')[0];\n label = buttonEl.innerText;\n\n if (profile === state.currentVideo.profile) {\n return;\n }\n\n setProfileLabel(label);\n if (state.abr && !isOnTv) {\n state.currentVideo.profile = profile;\n shaka.setTrack(profile);\n control.profile.updateLabel(label);\n if (state.ended) {\n player.seekTo(0);\n }\n } else {\n if (state.ended) {\n exports.queue.emit('loadAndPlay:videoById', state.currentVideo.id, profile);\n } else {\n if (queue.front.type === constants.VIDEO_TYPE.VOD) {\n inline.pauseNonLinearAd();\n inline.getClipLocation(profile);\n } else {\n state.currentVideo.contentType = constants.CONTENT_TYPE.HLS;\n\n if (profile !== constants.PROFILE.BASE && profile !== constants.PROFILE.LOW) {\n if (player.isInstalledLiveAgent() && (env.useNPP || !ua.os.mac)) {\n state.currentVideo.contentType = constants.CONTENT_TYPE.NPP;\n } else if (env.useNPP || !ua.os.mac) {\n exports.queue.emit('show:error', {\n info: {\n code: constants.ERROR.STATUS.LiveAgentNotInstalled.NAME,\n profile: profile\n }\n });\n return;\n }\n }\n\n player.pause();\n inline.startSpinner();\n inline.getLiveLocation(profile);\n }\n }\n }\n\n if (profile !== constants.PROFILE.AUTO) {\n helpers.store.set(PROFILE_KEY, state.abr ? constants.DASH_PROFILE[profile] : profile);\n }\n\n if (preQualityElement) {\n dt.classList.remove(preQualityElement, 'on');\n }\n dt.classList.add(buttonEl.parentElement, 'on');\n\n pvtTracker.pause();\n pctTracker.track('profile', state.abr ? constants.DASH_PROFILE[profile] : profile);\n });\n\n event.on(EL.SETTING_BUTTON, 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n moveSettingBox();\n\n var isOpened = dt.classList.has(EL.SETUP_BOX, 'open') || dt.classList.has(EL.SPEED_BOX, 'open');\n\n if (isOpened) {\n closeSettingBox();\n } else {\n control.profile.hideList();\n openSettingBox();\n }\n\n pctTracker.track('setting');\n });\n\n event.on(EL.CONTROLLER_BODY, 'dblclick', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n if (inline.isFullScreenSupport()) {\n toggleFullScreen();\n }\n });\n\n event.delegate(EL.PLAYER_FUNCTION, '.btn_chart', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n var isOpened = dt.classList.has(EL.CHART_BOX, 'open') || dt.classList.has(EL.CHART_BOX, 'open');\n\n if (isOpened) {\n closeChartBox();\n } else {\n openChartBox();\n }\n\n helpers.store.set(constants.STORAGE.CHART, !isOpened);\n\n contextMenu.videoChartToggle();\n pctTracker.track('chart', isOpened ? 'off' : 'on');\n });\n\n event.delegate(EL.PLAYER_FUNCTION, '.btn_wide', 'click', function() {\n debug.log('click wide screen button');\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onWideScreenChange);\n pctTracker.track('wide_screen');\n });\n\n event.delegate(EL.PLAYER_FUNCTION, '.btn_popup', 'click', function() {\n var pathname = window.location.pathname;\n var search = window.location.search;\n\n search = helpers.url.setParameter(search, 'popup', '1');\n search = helpers.url.setParameter(search, 'autoplay', '1');\n\n var url = pathname + search;\n var features =\n 'width=720, height=427, left=0, top=0,' +\n 'location=no, toolbar=no, menubar=no, scrollbars=no, status=no, resizable=yes';\n\n inline.openPopup(url, 'popupModePlayerWindow', features);\n player.pause();\n pctTracker.track('popup_player');\n });\n\n event.delegate(EL.SETTING_BOX, '.clip_modify', 'click', function() {\n var callback = null;\n var isfreeze = false;\n\n exports.queue.emit('hide:completion');\n\n if (state.ended) {\n isfreeze = true;\n inline.showControl(isfreeze);\n\n callback = function() {\n showCompletion();\n inline.showControl(isfreeze);\n };\n } else {\n inline.hideActivatedControl();\n }\n\n control.menu.setClipInfo();\n control.menu.setClipCover(state.currentVideo.thumbnailList);\n\n exports.queue.emit('show:modal', {\n target: 'clipInfoModify',\n callback: callback\n });\n\n closeSettingBox();\n });\n\n event.delegate(EL.SETUP_BOX, '.btn_quality', 'click', function() {\n control.setting.hide();\n control.profile.showList();\n\n pctTracker.track('profile');\n });\n\n event.delegate(EL.QUALITY_BOX, '.tit_quality', 'click', function() {\n control.profile.hideList();\n openSettingBox();\n });\n\n event.delegate(EL.SETUP_BOX, '.btn_langsubtitles', 'click', function() {\n control.setting.hide();\n control.subtitle.showList();\n\n pctTracker.track('subtitles');\n });\n\n event.delegate(EL.SETUP_BOX, '.tit_subtitles', 'click', function() {\n control.subtitle.hideList();\n openSettingBox();\n });\n\n event.delegate(EL.SETUP_BOX, '.list_subtitles', 'click', function(e) {\n var buttonEl = e.target;\n var subtitle = buttonEl.getAttribute('data-subtitle');\n var subtitleText = subtitle === constants.SUBTITLE.STATUS.OFF ? subtitle : buttonEl.innerText;\n\n helpers.store.set(SUBTITLE_KEY, subtitle);\n\n if (!dt.classList.has(buttonEl.parentElement, 'on')) {\n setSubtitle(subtitle);\n }\n\n control.subtitle.hideList();\n\n openSettingBox();\n\n pctTracker.track('subtitles', subtitleText);\n });\n\n event.delegate(EL.SETUP_BOX, '.btn_playspeed', 'click', function() {\n control.setting.hide();\n control.speed.showList();\n\n pctTracker.track('speed');\n });\n\n event.delegate(EL.SETUP_BOX, '.tit_playspeed', 'click', function() {\n control.speed.hideList();\n openSettingBox();\n });\n\n event.delegate(EL.SETUP_BOX, '.list_playspeed', 'click', function(e) {\n var buttonEl = e.target;\n var speed = buttonEl.getAttribute('data-speed');\n\n setSpeed(speed);\n control.speed.hideList();\n\n openSettingBox();\n\n pctTracker.track('speed', speed);\n });\n\n event.delegate(EL.CONTROLLER, '#stillImage', 'mouseover', function() {\n var video = queue.front;\n\n if (\n state.ended ||\n state.seeking ||\n player.isPaused() ||\n state.hasStillVideo ||\n (video && video.type !== constants.VIDEO_TYPE.VOD)\n ) {\n return;\n }\n control.stillImage.on();\n });\n\n event.delegate(EL.CONTROLLER, '#stillImage', 'mouseout', function() {\n if (!state.ended) {\n control.stillImage.off();\n }\n });\n\n event.delegate(EL.CONTROLLER, '.link_section', 'click', function(e) {\n if (!state.ended) {\n var target = e.target;\n\n if (target.tagName === 'A' || target.tagName === 'IMG' || target.tagName === 'SPAN') {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n if (target.parentNode && target.parentNode.tagName === 'A') {\n target = target.parentNode;\n }\n\n var sec = target.getAttribute('data-time');\n player.seekTo(parseInt(sec, 10));\n pctTracker.track('still_image');\n }\n control.stillImage.off();\n }\n });\n\n event.delegate(EL.CLIP_INFO_MODIFY, '.link_share', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n var current = e.target;\n var target = current.href.split('#')[1];\n\n menu.selectTab(target);\n menu.togglePanel(target);\n });\n\n event.delegate(EL.CLIP_INFO_MODIFY, '.link_cover', 'click', function(e) {\n var target = e.target;\n\n if (target.tagName === 'A' || target.tagName === 'IMG') {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n if (target.parentNode && target.parentNode.tagName === 'A') {\n target = target.parentNode;\n }\n\n dt.classListAll.remove($$('li', EL.CLIP_COVER_PANEL), 'on');\n dt.classList.add(target.parentNode, 'on');\n\n $('thumnailIndex').value = target.getAttribute('data-thumbnail-index');\n }\n });\n\n event.delegate(EL.CLIP_INFO_PANEL, '.btn_edit', 'click', function() {\n var lblName = $('lblName');\n\n if (lblName.value === '') {\n alert('동영상 제목을 입력해 주세요.');\n lblName.focus();\n return;\n }\n\n if (lblName.length >= 30) {\n alert('동영상 제목은 20자내에서 입력해 주세요.');\n lblName.focus();\n return;\n }\n\n menu.submitClipInfo();\n });\n\n event.delegate(EL.CLIP_COVER_PANEL, '.btn_edit', 'click', function() {\n var index = $('thumnailIndex').value;\n menu.submitClipCover(index);\n });\n\n event.delegate(EL.CONTROLLER, 'autoPlay', 'click', function(e) {\n var isAutoPlay = e.target.checked;\n state.autoplay = isAutoPlay;\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onChangeAutoPlayMode, [\n isAutoPlay\n ]);\n });\n }\n },\n customEvent: function(sandbox) {\n sandbox.on('hide:customUI', function() {\n closeSettingBox();\n control.profile.hideList();\n if (control.stillImage.el) {\n control.stillImage.off();\n }\n control.volume.hide();\n dt.classList.remove(EL.SETTING_BUTTON, 'open');\n });\n\n sandbox.on('update:clipinfo', function(data) {\n var message = '';\n\n if (data.status === 'success') {\n message = '동영상의 정보 수정이 완료되었습니다.';\n\n state.currentVideo.title = data.result.title;\n state.currentVideo.canScrap = data.result.canScrap;\n state.currentVideo.isOpen = data.result.isOpen;\n } else {\n message = '동영상의 정보 수정 중 오류가 발생하였습니다.';\n }\n\n exports.queue.emit('hide:modal', {\n callback: function() {\n var callback = function() {\n inline.hideBlind();\n\n if (state.ended) {\n showCompletion();\n inline.showControl(true);\n }\n };\n inline.showNotification(message, callback);\n }\n });\n });\n\n sandbox.on('update:clipcover', function(data) {\n var message = '';\n\n if (data.status === 'success') {\n message = '동영상의 대표이미지 수정이 완료되었습니다.';\n\n var index = data.index;\n var thumbnailList = state.currentVideo.thumbnailList;\n\n for (var i = 0; i < thumbnailList.length; i++) {\n thumbnailList[i].isDefault = false;\n }\n thumbnailList[index] = data.result;\n\n state.currentVideo.thumbnailList = thumbnailList;\n } else {\n message = '동영상의 대표이미지 수정 중 오류가 발생하였습니다.';\n }\n\n exports.queue.emit('hide:modal', {\n callback: function() {\n var callback = function() {\n inline.hideBlind();\n\n if (state.ended) {\n showCompletion();\n inline.showControl(true);\n }\n };\n inline.showNotification(message, callback);\n }\n });\n });\n\n sandbox.on('close:menubox', function() {\n closeMenuBox();\n });\n\n sandbox.on('close:settingbox', function() {\n closeSettingBox();\n });\n\n sandbox.on('analytics:chart', function(isShow) {\n if (!isShow) {\n openChartBox();\n } else {\n closeChartBox();\n }\n contextMenu.videoChartToggle();\n });\n },\n gestureEvent: function() {\n var volumeListener = window.gesture.GestureListener(EL.VOLUME);\n\n volumeListener.onGestureMove(function(session) {\n onTouchMoveVolume(session.targetEvent);\n });\n\n volumeListener.onGestureEnd(function(session) {\n onTouchEndVolume(session.targetEvent);\n });\n }\n };\n\n function InlinePC() {}\n\n InlinePC.prototype.init = function(initPlayer, sandbox) {\n if (ua.platform === 'pc') {\n applyParameters();\n\n listener.viewEvent();\n listener.customEvent(sandbox);\n listener.gestureEvent();\n\n keyboardAddOn.initWithConfig({\n keydownCallback: {\n up: function() {\n if (!queue.front) {\n return;\n }\n\n if (!state.seeking) {\n inline.showControl(player.isPaused());\n control.volume.show();\n }\n var volume = parseFloat(getRecentVolume()) + 0.1;\n var newVolume = volume > 1.0 ? 1.0 : volume;\n var newVolumePercentage = newVolume * 100;\n var muteOn = checkMuteRange(newVolumePercentage);\n\n updateVolume(newVolumePercentage);\n setRecentVolume(newVolume);\n inline.saveRecentMute(muteOn);\n\n control.keyboard.setup(KEYBOARD_TYPE.VOLUME_UP, newVolumePercentage.toFixed(0) + '%');\n control.keyboard.show();\n },\n down: function() {\n if (!queue.front) {\n return;\n }\n\n if (!state.seeking) {\n inline.showControl(player.isPaused());\n control.volume.show();\n }\n\n var volume = parseFloat(getRecentVolume()) - 0.1;\n var newVolume = volume < 0.0 ? 0.0 : volume;\n var newVolumePercentage = newVolume * 100;\n var muteOn = checkMuteRange(newVolumePercentage);\n\n updateVolume(newVolumePercentage);\n setRecentVolume(newVolume);\n inline.saveRecentMute(muteOn);\n\n control.keyboard.setup(\n newVolume === 0 ? KEYBOARD_TYPE.VOLUME_MUTE : KEYBOARD_TYPE.VOLUME_DOWN,\n newVolumePercentage.toFixed(0) + '%'\n );\n control.keyboard.show();\n },\n left: function(keyDownCount) {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n if (!isSeekable()) {\n return;\n }\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n\n if (keyDownCount < 1) {\n state.mutedBeforeSeek = player.getMute();\n }\n\n var currentTime = player.getCurrentTimeRound() - 5;\n if (currentTime < 0) {\n return;\n }\n player.setMute(true);\n player.seekTo(currentTime);\n inline.showControl(player.isPaused());\n control.keyboard.setup(KEYBOARD_TYPE.BACK_5S);\n control.keyboard.show();\n }\n },\n right: function(keyDownCount) {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n if (!isSeekable()) {\n return;\n }\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n\n if (keyDownCount < 1) {\n state.mutedBeforeSeek = player.getMute();\n }\n\n var currentTime = player.getCurrentTimeRound() + 5;\n if (currentTime > player.getDurationRound()) {\n return;\n }\n player.setMute(true);\n player.seekTo(currentTime);\n inline.showControl(player.isPaused());\n control.keyboard.setup(KEYBOARD_TYPE.FRONT_5S);\n control.keyboard.show();\n }\n },\n space: function() {\n var currentVideo = state.currentVideo;\n var frontVideo = queue.front;\n\n if (state.ended) {\n exports.queue.emit('loadAndPlay:videoById', currentVideo.id, currentVideo.profile);\n return;\n }\n\n if (frontVideo && frontVideo.type === constants.VIDEO_TYPE.AD) {\n togglePlayback();\n return;\n }\n\n if (state.isFirstPlay) {\n if (currentVideo.type !== constants.VIDEO_TYPE.VOD) {\n exports.queue.emit('play:vod', currentVideo.profile);\n } else if (currentVideo.type !== constants.VIDEO_TYPE.LIVE) {\n exports.queue.emit('play:live', currentVideo.profile);\n }\n } else {\n togglePlayback();\n }\n },\n z: function() {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n var speed = player.setPlaybackRate(DEFAULT_SPEED, false);\n control.speed.setSpeedText(speed);\n state.playbackRate = speed;\n }\n },\n comma: function() {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n var speed = player.setPlaybackRate(-0.25, true);\n control.speed.setSpeedText(speed);\n state.playbackRate = speed;\n\n inline.showControl(player.isPaused());\n control.keyboard.setup(KEYBOARD_TYPE.SPEED_UP, speed.toString());\n control.keyboard.show();\n }\n },\n period: function() {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n var speed = player.setPlaybackRate(0.25, true);\n control.speed.setSpeedText(speed);\n state.playbackRate = speed;\n\n inline.showControl(player.isPaused());\n control.keyboard.setup(KEYBOARD_TYPE.SPEED_DOWN, speed.toString());\n control.keyboard.show();\n }\n },\n pageUp: function(keyDownCount) {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n if (queue.front.type === constants.VIDEO_TYPE.VOD) {\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n\n if (keyDownCount < 1) {\n state.mutedBeforeSeek = player.getMute();\n }\n\n var currentTime = player.getCurrentTimeRound() + 60;\n if (currentTime > player.getDurationRound()) {\n currentTime = player.getDurationRound();\n state.ended = true;\n }\n player.setMute(true);\n player.seekTo(currentTime);\n inline.showControl(player.isPaused());\n control.keyboard.setup(KEYBOARD_TYPE.FRONT_60S);\n control.keyboard.show();\n }\n }\n },\n pageDown: function(keyDownCount) {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n if (queue.front.type === constants.VIDEO_TYPE.VOD) {\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n\n if (keyDownCount < 1) {\n state.mutedBeforeSeek = player.getMute();\n }\n\n var currentTime = player.getCurrentTimeRound() - 60;\n if (currentTime < 0) {\n currentTime = 0;\n }\n player.setMute(true);\n player.seekTo(currentTime);\n inline.showControl(player.isPaused());\n inline.onSeeked();\n control.keyboard.setup(KEYBOARD_TYPE.BACK_60S);\n control.keyboard.show();\n }\n }\n },\n end: function() {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n var currentTime = player.getDurationRound();\n state.ended = true;\n\n player.seekTo(currentTime);\n inline.showControl(player.isPaused());\n inline.onSeeked();\n }\n },\n home: function() {\n if (queue.front && queue.front.type === constants.VIDEO_TYPE.VOD) {\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n var currentTime = 0;\n player.seekTo(currentTime);\n inline.showControl(player.isPaused());\n }\n },\n tab: function() {\n if (!queue.front) {\n return;\n }\n\n if (player.videoElement.src !== '' && !state.modalContentActivated && !state.ended) {\n inline.showControl(player.isPaused());\n }\n },\n esc: function() {\n if (!queue.front) {\n return;\n }\n\n if (state.modalContentActivated) {\n exports.queue.emit('hide:modal');\n }\n if (state.isSettingMenuOpened) {\n closeMenuBox();\n }\n if (state.isContextMenuOpened) {\n contextMenu.hide();\n }\n },\n f: function() {\n if (inline.isFullScreenSupport()) {\n toggleFullScreen();\n }\n }\n },\n keyupCallback: {\n up: function() {\n pctTracker.track('keyboard', 'volume_up');\n },\n down: function() {\n pctTracker.track('keyboard', 'volume_down');\n },\n left: function() {\n pctTracker.track('keyboard', 'prev');\n },\n right: function() {\n pctTracker.track('keyboard', 'next');\n },\n space: function() {\n pctTracker.track('keyboard', !player.isPaused() ? 'play' : 'pause');\n },\n z: function() {\n pctTracker.track('keyboard', 'z');\n pctTracker.track('speed', player.getPlaybackRate());\n },\n comma: function() {\n pctTracker.track('keyboard', '<');\n pctTracker.track('speed', player.getPlaybackRate());\n },\n period: function() {\n pctTracker.track('keyboard', '>');\n pctTracker.track('speed', player.getPlaybackRate());\n },\n pageUp: function() {\n pctTracker.track('keyboard', 'pageUp');\n },\n pageDown: function() {\n pctTracker.track('keyboard', 'pageDown');\n },\n home: function() {\n pctTracker.track('keyboard', 'home');\n },\n end: function() {\n pctTracker.track('keyboard', 'end');\n },\n f: function() {\n pctTracker.track('keyboard', 'f');\n }\n }\n });\n }\n };\n\n InlinePC.prototype.togglePlayPause = function(isPaused) {\n inline.togglePlayPause(isPaused);\n togglePlayPause(isPaused);\n };\n\n InlinePC.prototype.toggleMuteUI = function(volume, muteOn) {\n toggleMuteUI(volume, muteOn);\n };\n\n InlinePC.prototype.onEndVideo = function() {\n var video = queue.front;\n\n if (env.isPrivateIp && video && video.type === constants.VIDEO_TYPE.VOD) {\n closeChartBox();\n contextMenu.videoChartToggle();\n analytics.detailHide();\n }\n\n if (state.currentVideo.purchase) {\n inline.hideTvod();\n exports.queue.emit('show:error', {\n info: {\n checkUrl: state.currentVideo.purchase.purchaseLink,\n code: constants.CONFIRM.STATUS.NeedPurchased.NAME\n }\n });\n } else if (video && video.type === constants.VIDEO_TYPE.AD) {\n // 포스트롤 광고가 끝난경우\n if (video.timeOffset === 'start') {\n return;\n }\n\n queue.enqueue(state.currentVideo);\n exports.queue.emit('load:videoUrl', state.currentVideo, function() {\n existRelatedClip();\n });\n } else {\n // 컨텐츠 영상이 끝난경우\n resetSpeed();\n\n if (env.service === 'daum_ad_brand_search') {\n var isAutoPlay = false;\n var startTime = 0;\n\n exports.queue.emit('load:videoById', startTime, isAutoPlay);\n } else {\n if (video.type === 'LIVE') {\n exports.queue.emit('show:error', {\n info: {\n code: constants.ERROR.STATUS.LiveFinished.NAME\n }\n });\n } else {\n existRelatedClip();\n }\n }\n }\n inline.hideControlHead();\n control.stillImage.off();\n };\n\n InlinePC.prototype.changeProfileLabel = function() {\n var label = EL.QUALITY_BUTTON.getAttribute('data-label-temp');\n control.profile.updateLabel(label);\n };\n\n InlinePC.prototype.setAutoPlay = function(isAutoPlay) {\n state.autoplay = isAutoPlay;\n if (EL.AUTO_PLAY) {\n EL.AUTO_PLAY.checked = isAutoPlay;\n }\n };\n\n InlinePC.prototype.setWideScreen = function(isWideScreen) {\n if (EL.WIDE_SCREEN_BUTTON) {\n if (isWideScreen) {\n dt.classList.remove(EL.WIDE_SCREEN_BUTTON, 'btn_cinema');\n dt.classList.add(EL.WIDE_SCREEN_BUTTON, 'btn_basic');\n EL.WIDE_SCREEN_BUTTON.setAttribute('aria-label', '기본 모드');\n EL.WIDE_SCREEN_BUTTON.nextElementSibling.innerHTML = '기본 모드';\n\n inline.showWithResetRating();\n } else {\n dt.classList.remove(EL.WIDE_SCREEN_BUTTON, 'btn_basic');\n dt.classList.add(EL.WIDE_SCREEN_BUTTON, 'btn_cinema');\n EL.WIDE_SCREEN_BUTTON.setAttribute('aria-label', '시네마 모드');\n EL.WIDE_SCREEN_BUTTON.nextElementSibling.innerHTML = '시네마 모드';\n }\n }\n };\n\n InlinePC.prototype.setRecentVolume = function(volume) {\n if (volume > 0) {\n setRecentVolume(volume);\n }\n };\n\n InlinePC.prototype.updateVolumePanel = function(volume) {\n updateVolume(volume * 100);\n if (volume > 0) {\n setRecentVolume(volume);\n }\n };\n\n InlinePC.prototype.showAutoPlay = function() {\n control.setting.showAutoPlay();\n };\n\n InlinePC.prototype.hideAutoPlay = function() {\n control.setting.hideAutoPlay();\n };\n\n InlinePC.prototype.showWide = function() {\n control.screen.showWide();\n };\n\n InlinePC.prototype.hideWide = function() {\n control.screen.hideWide();\n };\n\n InlinePC.prototype.hideProfileList = function() {\n control.profile.hideList();\n };\n\n InlinePC.prototype.closeMenuBox = function() {\n closeMenuBox();\n };\n\n InlinePC.prototype.onCompleteMeta = function() {\n initModifyButton();\n createProfileList();\n inline.setShowTitle();\n inline.setKakaoTVLink();\n inline.setRatingLevel();\n\n if (\n (!state.hls || !state.drm) &&\n (state.currentVideo.type === constants.VIDEO_TYPE.VOD || env.useNPP || !ua.os.mac)\n ) {\n customUI.control.setting.showDpQualityButton();\n }\n };\n\n InlinePC.prototype.onLoadStart = function() {\n var video = queue.front;\n if (video.type === constants.VIDEO_TYPE.VOD) {\n setClipInfoAndCover();\n setSeekThumbnail();\n }\n createProfileList();\n };\n\n InlinePC.prototype.onLoadedData = function() {\n var video = queue.front;\n var storeSubtitle = helpers.store.get(SUBTITLE_KEY);\n\n if (video.type === constants.VIDEO_TYPE.VOD) {\n createSubtitle();\n if (storeSubtitle) {\n setSubtitle(storeSubtitle);\n }\n }\n };\n\n InlinePC.prototype.clearRelatedTimer = function() {\n if (existRelatedTimer !== null) {\n clearTimeout(existRelatedTimer);\n }\n };\n\n InlinePC.prototype.resetSpeed = function() {\n resetSpeed();\n };\n\n InlinePC.prototype.hideMenuOnCast = function(isAirplay) {\n if (!isAirplay) {\n customUI.control.setting.hideDpQualityButton();\n }\n customUI.control.setting.hideSubtitleButton();\n customUI.control.setting.hideSpeedButton();\n control.popup.hide();\n };\n\n InlinePC.prototype.showMenuOnCast = function(isAirplay) {\n if (!isAirplay && (!state.drm || !state.hls)) {\n customUI.control.setting.showDpQualityButton();\n }\n customUI.control.setting.showSubtitleButton();\n customUI.control.setting.showSpeedButton();\n control.popup.show();\n };\n\n InlinePC.prototype.hideLoadedMenuOnCast = function() {\n customUI.control.tv.hideMirroringText();\n };\n\n InlinePC.prototype.showLoadedMenuOnCast = function() {\n customUI.control.tv.showMirroringText();\n };\n\n InlinePC.prototype.updateSetupView = function(profile) {\n customUI.control.install.setupView(profile);\n };\n\n InlinePC.prototype.initVolumeControl = function() {\n initVolumeControl();\n };\n\n InlinePC.prototype.hideQualityButton = function() {\n customUI.control.setting.hideDpQualityButton();\n };\n\n return InlinePC;\n })();\n\n exports.addModule('view.inline.pc', new InlinePC());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n var state = exports.loadModule('controller.state');\n var pctTracker = exports.loadModule('pct.tracker');\n var playerTemplate = exports.template;\n\n var Cover;\n\n Cover = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n var env = exports.ENV;\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var PROFILE_KEY = constants.STORAGE.PROFILE;\n var ABR_KEY = constants.STORAGE.ABR;\n\n var EL = {\n COVER: $('customCover'),\n COVER_THUMB: $('coverImage'),\n COVER_TIME_CONTATINER: $$('.custom_cover .time_player')[0],\n COVER_TIME_SCREEN_OUT: $$('.custom_cover .time_player span')[0],\n COVER_TIME: $$('.custom_cover .time_player em')[0],\n PLAYER_TITLE: $$('.custom_cover .tit_player')[0],\n COVER_TITLE: $$('.custom_cover .link_title')[0],\n SHARE_BUTTON: $$('.custom_cover .btn_share')[0],\n SOCIAL_SHARE_KAKAOTALK: $$('.kakaotalk')[0],\n SOCIAL_SHARE_KAKAOSTORY: $$('.kakaostory')[0],\n PLAY_BUTTON: $$('.custom_cover .link_play')[0],\n QUALITY_CONTAINER: $$('.cover_quality div')[0],\n APPLINK_BUTTON: $$('.custom_cover .btn_liveHD')[0]\n };\n\n var cover = {\n el: EL.COVER,\n show: function() {\n dt.classList.remove(this.el, 'hidden');\n dt.classList.add(this.el, 'visible');\n },\n hide: function() {\n dt.classList.add(this.el, 'hidden');\n dt.classList.remove(this.el, 'visible');\n },\n setThumbnail: function(url) {\n if (url && EL.COVER_THUMB) {\n EL.COVER_THUMB.style.backgroundImage = 'url(\"' + url + '\")';\n }\n },\n setTime: function(duration) {\n if (EL.COVER_TIME) {\n EL.COVER_TIME.innerHTML = helpers.string.delimitTimes(duration);\n }\n\n if (EL.COVER_TIME_SCREEN_OUT) {\n var text = document.createTextNode(helpers.string.timeToString(duration));\n EL.COVER_TIME_SCREEN_OUT.appendChild(text);\n }\n },\n hideTime: function() {\n if (EL.COVER_TIME_CONTATINER) {\n dt.classList.add(EL.COVER_TIME_CONTATINER, 'hide');\n }\n },\n setTitle: function(url, title) {\n EL.COVER_TITLE.innerHTML = helpers.string.escapeHtml(title);\n },\n showTitle: function() {\n if (EL.PLAYER_TITLE) {\n dt.classList.remove(EL.PLAYER_TITLE, 'hide');\n }\n },\n showShareButton: function() {\n if (EL.SHARE_BUTTON) {\n dt.classList.remove(EL.SHARE_BUTTON, 'hide');\n }\n },\n hideShareButton: function() {\n if (EL.SHARE_BUTTON) {\n dt.classList.add(EL.SHARE_BUTTON, 'hide');\n }\n },\n showAppLinkButton: function() {\n if (EL.APPLINK_BUTTON) {\n dt.classList.remove(EL.APPLINK_BUTTON, 'hide');\n }\n },\n hideAppLinkButton: function() {\n if (EL.APPLINK_BUTTON) {\n dt.classList.add(EL.APPLINK_BUTTON, 'hide');\n }\n },\n profile: {\n el: EL.QUALITY_CONTAINER,\n template: {\n profileList: playerTemplate.cover_profile_list,\n supHD: playerTemplate.superscript_hd,\n sup4K: playerTemplate.superscript_4k\n },\n create: function(outputs) {\n var storeABR = helpers.store.get(ABR_KEY);\n var storeProfile = helpers.store.get(PROFILE_KEY);\n\n var supHDTemplate = this.template.supHD;\n var sup4KTemplate = this.template.sup4K;\n var profile, profileLabel;\n var view = {\n outputs: []\n };\n\n var storeCheck = outputs.filter(function(p) {\n return state.abr\n ? constants.DASH_PROFILE[p.profile] === storeProfile\n : p.profile === storeProfile;\n });\n\n for (var i in outputs) {\n if (outputs.hasOwnProperty(i) && isAvailableProfile(outputs, i)) {\n profile = outputs[i].profile;\n profileLabel = outputs[i].label;\n\n view.outputs.push({\n profileName: profile,\n profileLabel: this.removeText(profileLabel),\n supHD: (function() {\n if (profileLabel.indexOf('HD') >= 0) {\n return supHDTemplate.render();\n } else {\n return '';\n }\n })(),\n sup4K: (function() {\n if (profileLabel.indexOf('4K') >= 0) {\n return sup4KTemplate.render();\n } else {\n return '';\n }\n })(),\n profileOn: (function() {\n if (storeProfile && storeCheck.length > 0) {\n if (\n outputs[i].profile === storeProfile ||\n (constants.DASH_PROFILE[outputs[i].profile] === storeProfile &&\n storeABR === 'false')\n ) {\n return 'on';\n }\n } else if (\n outputs[i].profile === state.currentVideo.profile ||\n (outputs[i].profile === 2 && storeABR === 'false')\n ) {\n return 'on';\n }\n return '';\n })()\n });\n }\n }\n\n view.outputs = outputLengthCheck(view.outputs);\n\n var fragment = this.createTemplate(view);\n this.render(fragment);\n },\n createTemplate: function(view) {\n var template = this.template.profileList;\n return template.render(view);\n },\n render: function(htmlStr) {\n EL.QUALITY_CONTAINER.innerHTML = htmlStr;\n },\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n },\n removeText: function(text) {\n var re = / |P|HD|4K/g;\n return text.replace(re, '');\n }\n }\n };\n\n function onCoverPlayBtn(type, profile) {\n if (type === 'VOD') {\n exports.queue.emit('play:vod', profile);\n } else if (type === 'LIVE') {\n if (state.autoplayFail && state.playerClass === constants.PLAYERCLASS.KAMP) {\n player.play();\n } else {\n exports.queue.emit('play:live', profile);\n }\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onClickEventStart, [\n constants.PLAYER_CLICK_ACTION.PLAY,\n state.currentVideo.id\n ]);\n }\n\n function showCover() {\n if (env.showCover) {\n cover.show();\n }\n }\n\n function hideCover() {\n cover.hide();\n }\n\n function checkVisibleExtensionInLegacy() {\n if (ua.platform === 'pc') {\n if (state.currentVideo.isLegacy) {\n if (state.currentVideo.canScrap) {\n cover.showShareButton();\n } else {\n cover.hideShareButton();\n }\n } else {\n cover.showShareButton();\n }\n } else {\n if (state.currentVideo.isLegacy) {\n cover.hideShareButton();\n } else {\n cover.showShareButton();\n }\n }\n }\n\n function checkVisibleShareButton() {\n if (env.extensions) {\n checkVisibleExtensionInLegacy();\n } else {\n cover.hideShareButton();\n }\n }\n\n function applyParameters() {\n if (ua.platform !== 'pc') {\n if (!env.coverProfile) {\n cover.profile.hide();\n }\n\n if (!env.coverTime) {\n cover.hideTime();\n }\n }\n }\n\n function isAvailableProfile(outputs, index) {\n var autoProfileCheck = outputs[index].profile !== constants.PROFILE.AUTO;\n\n return autoProfileCheck;\n }\n\n function outputLengthCheck(outputList) {\n var list = [];\n\n for (var i in outputList) {\n if (list.length > 3) {\n list.splice(list[0].profileOn === 'on' ? 1 : 0, 1);\n }\n list.push(outputList[i]);\n }\n\n return list;\n }\n\n function toggleAppLink() {\n var video = state.currentVideo;\n\n if (env.appLink && video.shouldShowHDLabel) {\n cover.showAppLinkButton();\n } else {\n cover.hideAppLinkButton();\n }\n }\n\n function bindEvent(player) {\n event.on(EL.PLAY_BUTTON, 'click', function(e) {\n helpers.ui.preventDoubleClick(this);\n\n var storeABR = helpers.store.get(ABR_KEY);\n var storeProfile = helpers.store.get(PROFILE_KEY);\n var outputs = state.currentVideo.outputList;\n var storeCheck = null;\n var profile;\n\n if (player.type === 'LIVE') {\n profile = env.profile || constants.PROFILE.MAIN;\n } else {\n storeCheck = outputs.filter(function(p) {\n return state.abr\n ? constants.DASH_PROFILE[p.profile] === storeProfile\n : p.profile === storeProfile;\n });\n\n if (storeProfile && storeCheck.length > 0) {\n profile = storeProfile;\n } else {\n profile = state.currentVideo.profile;\n }\n\n if (state.abr && (ua.platform === 'pc' || storeABR !== 'false')) {\n profile = constants.PROFILE.AUTO;\n }\n }\n\n onCoverPlayBtn(player.type, profile);\n\n event.preventDefault(e);\n event.stopPropagation(e);\n\n pctTracker.track('play');\n });\n\n event.delegate(EL.COVER, '.btn_quality', 'click', function(e) {\n var buttonEl = e.target;\n var profile = buttonEl.getAttribute('data-profile');\n\n if (!helpers.feature.supportsVideoProfile(profile) && !state.abr) {\n profile = constants.PROFILE.BASE;\n }\n\n if (profile !== constants.PROFILE.AUTO) {\n helpers.store.set(PROFILE_KEY, state.abr ? constants.DASH_PROFILE[profile] : profile);\n helpers.store.set(ABR_KEY, false);\n } else {\n helpers.store.set(ABR_KEY, true);\n }\n\n onCoverPlayBtn(player.type, profile);\n\n event.preventDefault(e);\n event.stopPropagation(e);\n\n pctTracker.track('cover_profile', profile);\n });\n\n event.delegate(EL.COVER, '.btn_liveHD', 'click', function(e) {\n onCoverPlayBtn(player.type, 'HIGH');\n\n event.preventDefault(e);\n event.stopPropagation(e);\n\n pctTracker.track('liveapp', 'open');\n });\n\n event.on(EL.COVER, 'click', function(e) {\n if (e.target === EL.SHARE_BUTTON) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n exports.queue.emit('show:modal', {\n target: 'socialShare',\n callback: function() {\n cover.showShareButton();\n }\n });\n\n if (ua.platform === 'pc') {\n EL.SOCIAL_SHARE_KAKAOSTORY.focus();\n } else {\n EL.SOCIAL_SHARE_KAKAOTALK.focus();\n }\n cover.hideShareButton();\n }\n });\n }\n\n function Cover() {}\n\n Cover.prototype.init = function(player, sandbox) {\n applyParameters();\n bindEvent(player, sandbox);\n };\n\n Cover.prototype.setThumbnail = function(url) {\n cover.setThumbnail(url);\n };\n\n Cover.prototype.setTime = function(duration) {\n cover.setTime(duration);\n };\n\n Cover.prototype.setTitle = function(url, title) {\n cover.setTitle(url, title);\n };\n\n Cover.prototype.showCover = function() {\n showCover();\n };\n\n Cover.prototype.hideCover = function() {\n hideCover();\n };\n\n Cover.prototype.onCompleteMeta = function() {\n var video = state.currentVideo;\n\n if (env.popup || (!env.isInternal && env.showInfo)) {\n if (video.type !== 'LIVE' || env.showLiveIcon) {\n cover.showTitle();\n }\n }\n\n toggleAppLink();\n checkVisibleShareButton();\n };\n\n Cover.prototype.createProfileList = function(outputList) {\n cover.profile.create(outputList);\n };\n\n return Cover;\n })();\n\n exports.addModule('view.cover', new Cover());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var Extension;\n\n Extension = (function() {\n var shaka = exports.loadModule('player.shaka');\n var player = exports.loadModule('player.adapter');\n var inline = exports.loadModule('view.inline');\n var contextMenu = exports.loadModule('view.contextmenu');\n var state = exports.loadModule('controller.state');\n var pctTracker = exports.loadModule('pct.tracker');\n var pvtTracker = exports.loadModule('pvt.tracker');\n var playerTemplate = exports.template;\n\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n var PHASE = constants.PHASE[env.phase.toUpperCase()];\n\n var SHARE_URL_HOST = helpers.serverHost.link(PHASE);\n\n var VOD_LINK = SHARE_URL_HOST + '/v/#{clipLinkId}';\n var LIVE_LINK = SHARE_URL_HOST + '/l/#{liveLinkId}';\n var SCRAP_LINK = 'http://scrap.cafe.daum.net/_dss_/scrap_tvpot?';\n\n var PROFILE_KEY = constants.STORAGE.PROFILE;\n var ABR_KEY = constants.STORAGE.ABR;\n var SUBTITLE_KEY = constants.STORAGE.SUBTITLE;\n\n var ID = {\n SOCIAL_SHARE: 'socialShare',\n SHARE_PANEL_URL: 'sharePanelUrl',\n SHARE_PANEL_EMBED: 'sharePanelEmbed'\n };\n\n var CNAME = {\n CLOSE_BUTTON: '.btn_close'\n };\n\n var EL = {\n PLAYER: $('player'),\n PLAYER_CONTROLLER: $('controller'),\n PLAYER_MODAL: $('playerModal'),\n MODAL_CONTENTS: $$('#playerModal .modal_content'),\n MODAL_CLOSE_BUTTON: $$(CNAME.CLOSE_BUTTON),\n SHARE_BUTTON: $('socialShareBtn'),\n SOCIAL_SHARE_KAKAOTALK: $$('.kakaotalk')[0],\n SOCIAL_SHARE_KAKAOSTORY: $$('.kakaostory')[0],\n RELATED_BUTTON: $('relatedClipBtn'),\n ADD_PLAYLIST_BUTTON: $$('#controller .btn_plus')[0],\n SOCIAL_SHARE_URLCOPY: $$('#socialShare .urlcopy')[0],\n SHARE_URL: $('shareUrl'),\n COPYURL_BOX: $('copyUrlBox'),\n EMBED_URL: $('iframeUrl'),\n EXTENSION_LAYER: $('extension'),\n SOCIAL_SHARE: $(ID.SOCIAL_SHARE) || null,\n SHARE_PANEL_URL: $(ID.SHARE_PANEL_URL) || null,\n SHARE_PANEL_EMBED: $(ID.SHARE_PANEL_EMBED) || null,\n EMBED_SIZE_LIST: $$('#' + ID.SHARE_PANEL_EMBED + ' .opt_comm')[0] || null,\n DEFAULT_SETTING: $('defaultSetting') || null,\n DETAIL_SETTING: $('detailSetting') || null,\n SIZE_SELECT_BUTTON: $$('#' + ID.SHARE_PANEL_EMBED + ' .link_selected')[0] || null,\n PROFILE_LIST_CONTAINER: $$('.list_quality')[0],\n SUBTITLE_BUTTON: $$('.subtitle')[0],\n SUBTITLE_LIST_CONTAINER: $$('.list_subtitle')[0],\n MENU_LIST_CONTAINER: $$('.list_menu')[0],\n KAKAOTALK_SHARE_BUTTON: $('kakaotalkBtn'),\n AUTOPLAY_CHECKBOX: $('autoplayCheckbox'),\n FACEBOOK: $$('.facebook')[0]\n };\n\n var profileTemplate = {\n profileList: playerTemplate.extension_profile_list,\n supHD: playerTemplate.superscript_hd,\n sup4K: playerTemplate.superscript_4k\n };\n\n var isSupportClipBoard = window.ClipboardJS.isSupported();\n\n function createShareLink() {\n var video = state.currentVideo;\n\n if (!video) {\n return constants.HOST;\n }\n\n if (video.type === 'VOD') {\n return helpers.string.format(VOD_LINK, {\n channelId: video.channelId,\n clipLinkId: video.id\n });\n } else {\n return helpers.string.format(LIVE_LINK, {\n channelId: video.channelId,\n liveLinkId: video.id\n });\n }\n }\n function openWindow(url) {\n var options = '';\n if (ua.platform === 'pc') {\n options = 'width=500, height=500, toolbar=0, menubar=no';\n }\n\n window.open(url, '_blank', options);\n }\n\n function selectTextField(target) {\n target.focus();\n target.select();\n }\n\n var extension = {\n modal: {\n el: EL.PLAYER_MODAL,\n callback: null,\n focusedElement: null,\n show: function() {\n state.modalContentActivated = true;\n dt.classList.remove(this.el, 'hide');\n this.el.setAttribute('aria-hidden', 'false');\n },\n hide: function() {\n state.modalContentActivated = false;\n dt.classList.add(this.el, 'hide');\n this.el.setAttribute('aria-hidden', 'true');\n },\n clearContent: function() {\n dt.classListAll.add(EL.MODAL_CONTENTS, 'hide');\n },\n selectContent: function(modalContent) {\n dt.classList.remove(modalContent, 'hide');\n },\n isHide: function() {\n return dt.classList.has(this.el, 'hide');\n }\n },\n share: {\n kakaotalk: {\n create: function(kakaoLink) {\n if (!kakaoLink.templateId || !kakaoLink.templateArgs) {\n return;\n }\n\n var templateId = parseInt(kakaoLink.templateId, 10);\n var templateArgs = kakaoLink.templateArgs;\n\n window.Kakao.Link.createCustomButton({\n container: '#kakaotalkBtn',\n templateId: templateId,\n templateArgs: templateArgs,\n installTalk: true\n });\n }\n },\n kakaostory: function() {\n var video = state.currentVideo;\n var link = createShareLink();\n var title = video.title;\n\n if (ua.platform !== 'pc') {\n window.Kakao.Story.open({\n url: link,\n text: title,\n install: true\n });\n } else {\n window.Kakao.Story.share({\n url: link,\n text: title\n });\n }\n },\n facebook: {\n el: EL.FACEBOOK,\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el.parentElement, 'hide');\n }\n },\n open: function() {\n var link = createShareLink();\n var url = 'https://m.facebook.com/sharer.php?u=' + encodeURIComponent(link);\n\n openWindow(url);\n }\n },\n twitter: function() {\n var link = createShareLink();\n var title = state.currentVideo.title;\n var url =\n 'https://twitter.com/intent/tweet?url=' +\n encodeURIComponent(link) +\n '&text=' +\n encodeURIComponent(title);\n\n openWindow(url);\n },\n cafe: function() {\n var params = {\n folder_id: 0,\n location_id: state.currentVideo.channelId,\n data_id: state.currentVideo.id,\n source_location_code: 8,\n target_location_code: 1\n };\n\n var queryString = helpers.string.jsonToQueryString(params);\n var url = SCRAP_LINK + queryString;\n\n openWindow(url);\n },\n blog: function() {\n var params = {\n folder_id: 0,\n location_id: state.currentVideo.channelId,\n data_id: state.currentVideo.id,\n source_location_code: 8,\n target_location_code: 4\n };\n\n var queryString = helpers.string.jsonToQueryString(params);\n var url = SCRAP_LINK + queryString;\n\n openWindow(url);\n },\n setShareUrl: function() {\n var shareUrl = createShareLink();\n EL.SHARE_URL.value = shareUrl;\n dt.dataset(EL.SOCIAL_SHARE_URLCOPY, 'clipboard-text', shareUrl);\n\n if (ua.platform === 'pc') {\n contextMenu.setShareUrl(shareUrl);\n }\n },\n embed: {\n activateTab: $$('#socialShare .on a')[0] || null,\n setEmbedUrl: function(_start, _width, _height, _autoplay) {\n var video = state.currentVideo;\n var iframeTemplate =\n '';\n\n var width = _width || 640;\n var height = _height || 360;\n\n var embedUrl = constants.SHARE_DOMAIN;\n\n if (video.type === 'VOD') {\n embedUrl += '/embed/player/cliplink/' + video.id + '?service=player_share';\n\n if (_start > 0) {\n embedUrl += '&start=' + _start;\n }\n } else if (video.type === 'LIVE') {\n // TODO: 서버 쪽 cliplink도 수정되면 cliplink도 적용 필요.\n embedUrl += '/embed/player/livelink?liveLinkId=' + video.id + '&service=player_share';\n }\n\n if (_autoplay) {\n embedUrl += '&autoplay=1';\n }\n\n var htmlString = iframeTemplate.replace('##TITLE##', state.currentVideo.title);\n htmlString = htmlString.replace('##IFRAME_URL##', embedUrl);\n htmlString = htmlString.replace('##WIDTH##', width);\n htmlString = htmlString.replace('##HEIGHT##', height);\n\n EL.EMBED_URL.innerHTML = helpers.string.escapeHtml(htmlString);\n },\n setOption: function() {\n var size = this.getSelectedSize();\n var start = this.getStartTime();\n var autoplay = this.getAutoPlay();\n var width = size.split('x')[0];\n var height = size.split('x')[1];\n\n this.setEmbedUrl(start, width, height, autoplay);\n },\n selectSize: function(size) {\n EL.SIZE_SELECT_BUTTON.setAttribute('data-selected', size);\n EL.SIZE_SELECT_BUTTON.innerHTML = size;\n },\n getSelectedSize: function() {\n return EL.SIZE_SELECT_BUTTON.getAttribute('data-selected');\n },\n getAutoPlay: function() {\n return EL.AUTOPLAY_CHECKBOX.checked;\n },\n validateStartTime: function() {\n var minute = $('minute').value;\n var second = $('second').value;\n\n if (isNaN(minute)) {\n alert('시작시간은 숫자로 입력해주세요.');\n $('minute').value = '';\n $('minute').focus();\n return false;\n }\n\n if (isNaN(second)) {\n alert('시작시간은 숫자로 입력해주세요.');\n $('minute').value = '';\n $('second').focus();\n return false;\n }\n return true;\n },\n getStartTime: function() {\n var checkedEl = $$('input[name=\"playType\"]:checked');\n var startTime = 0;\n\n if (checkedEl.length === 0) {\n return;\n }\n\n if (dt.classList.has(checkedEl[0], 'current')) {\n if (player.getCurrentTimeRound() > 0) {\n startTime = player.getCurrentTimeRound();\n }\n }\n\n if (dt.classList.has(checkedEl[0], 'point')) {\n if (this.validateStartTime()) {\n var minute = $('minute').value || 0;\n var second = $('second').value || 0;\n\n startTime = parseInt(minute, 10) * 60 + parseInt(second, 10);\n }\n }\n\n return startTime;\n },\n showSizeList: function() {\n dt.classList.add(EL.EMBED_SIZE_LIST, 'opt_open');\n },\n hideSizeList: function() {\n dt.classList.remove(EL.EMBED_SIZE_LIST, 'opt_open');\n },\n toggleSizeList: function() {\n if (dt.classList.has(EL.EMBED_SIZE_LIST, 'opt_open')) {\n this.hideSizeList();\n } else {\n this.showSizeList();\n }\n },\n resetPanel: function() {\n var video = state.currentVideo;\n var selectTab;\n\n if (video.isLegacy) {\n dt.classList.add(EL.SHARE_PANEL_URL, 'hide');\n dt.classList.remove(EL.SHARE_PANEL_EMBED, 'hide');\n\n selectTab = ID.SHARE_PANEL_EMBED;\n } else {\n dt.classList.remove(EL.SHARE_PANEL_URL, 'hide');\n dt.classList.add(EL.SHARE_PANEL_EMBED, 'hide');\n\n selectTab = ID.SHARE_PANEL_URL;\n }\n\n this.selectTab(selectTab);\n this.setOption();\n },\n showDefaultSetting: function() {\n dt.classList.remove(EL.DEFAULT_SETTING, 'hide');\n dt.classList.add(EL.DETAIL_SETTING, 'hide');\n },\n hideDefaultSetting: function() {\n dt.classList.add(EL.DEFAULT_SETTING, 'hide');\n dt.classList.remove(EL.DETAIL_SETTING, 'hide');\n },\n selectTab: function(targetId) {\n if (targetId) {\n dt.classList.remove(this.activateTab.parentNode, 'on');\n\n var selectedTab = $$('a[href=\"#' + targetId + '\"]')[0];\n dt.classList.remove(selectedTab.parentNode, 'hide');\n dt.classList.add(selectedTab.parentNode, 'on');\n\n this.activateTab = selectedTab;\n }\n },\n showTab: function(targetId) {\n if (targetId) {\n var selectedTab = $$('a[href=\"#' + targetId + '\"]')[0];\n dt.classList.remove(selectedTab.parentNode, 'hide');\n }\n },\n hideTab: function(targetId) {\n if (targetId) {\n var selectedTab = $$('a[href=\"#' + targetId + '\"]')[0];\n dt.classList.add(selectedTab.parentNode, 'hide');\n }\n },\n togglePanel: function(target) {\n if ($(target) === EL.SHARE_PANEL_URL) {\n dt.classList.remove(EL.SHARE_PANEL_URL, 'hide');\n dt.classList.add(EL.SHARE_PANEL_EMBED, 'hide');\n }\n\n if ($(target) === EL.SHARE_PANEL_EMBED) {\n dt.classList.remove(EL.SHARE_PANEL_EMBED, 'hide');\n dt.classList.add(EL.SHARE_PANEL_URL, 'hide');\n\n this.showDefaultSetting();\n }\n }\n }\n },\n profile: {\n template: profileTemplate.profileList,\n create: function(profileList) {\n var supHDTemplate = profileTemplate.supHD;\n var sup4KTemplate = profileTemplate.sup4K;\n\n var view = {\n outputs: []\n };\n\n var profile, profileLabel;\n\n for (var i in profileList) {\n if (profileList.hasOwnProperty(i)) {\n profile = profileList[i].profile;\n profileLabel = profileList[i].label;\n\n view.outputs.push({\n profileName: profile,\n profileLabel: removeText(profileLabel),\n supHD: (function() {\n if (profileLabel.indexOf('HD') >= 0) {\n return supHDTemplate.render();\n } else {\n return '';\n }\n })(),\n sup4K: (function() {\n if (profileLabel.indexOf('4K') >= 0) {\n return sup4KTemplate.render();\n } else {\n return '';\n }\n })(),\n profileOn: (function() {\n if (profile === 'MAIN') {\n return 'on';\n }\n return '';\n })()\n });\n }\n }\n\n EL.PROFILE_LIST_CONTAINER.innerHTML = this.template.render(view);\n },\n setOn: function(profile) {\n var selectProfile = $$('[data-profile=\"' + profile + '\"]', EL.PROFILE_LIST_CONTAINER)[0];\n var preSelectProfile = $$('.on', EL.PROFILE_LIST_CONTAINER)[0];\n\n if (selectProfile) {\n if (typeof preSelectProfile !== 'undefined') {\n dt.classList.remove(preSelectProfile, 'on');\n }\n dt.classList.add(selectProfile.parentElement, 'on');\n }\n }\n },\n subtitle: {\n template: playerTemplate.mobile_subtitle_list,\n showButton: function() {\n if (EL.SUBTITLE_BUTTON && EL.SUBTITLE_BUTTON.parentElement) {\n dt.classList.remove(EL.SUBTITLE_BUTTON.parentElement, 'hide');\n }\n },\n create: function(textTracks) {\n var view = {\n textTracks: []\n };\n\n textTracks.forEach(function(v) {\n var isoCode = v.language.substr(0, 2);\n if (window.ISO6391.getNativeName(isoCode)) {\n view.textTracks.push({\n subtitle: v.language,\n subtitleText: window.ISO6391.getNativeName(isoCode)\n });\n }\n });\n\n if (view.textTracks.length > 0) {\n EL.SUBTITLE_LIST_CONTAINER.innerHTML = this.template.render(view);\n this.showButton();\n }\n },\n setOn: function(subtitle) {\n var selectSubtitle = $$('[data-subtitle=\"' + subtitle + '\"]', EL.SUBTITLE_LIST_CONTAINER)[0];\n var preSelectSubtitle = $$('.on', EL.SUBTITLE_LIST_CONTAINER)[0];\n\n if (selectSubtitle) {\n if (typeof preSelectSubtitle !== 'undefined') {\n dt.classList.remove(preSelectSubtitle, 'on');\n }\n dt.classList.add(selectSubtitle.parentElement, 'on');\n }\n }\n }\n };\n\n function showModal(data) {\n var target = data.target;\n\n if (!target || typeof target !== 'string') {\n debug.log('target does not exsist');\n return;\n }\n\n if (data) {\n if (typeof data.callback === 'function') {\n extension.modal.callback = data.callback;\n }\n }\n\n var modalContent = $(target);\n if (modalContent) {\n extension.modal.clearContent();\n extension.modal.selectContent(modalContent);\n extension.modal.show();\n inline.hideActivatedControl();\n exports.queue.emit('hide:action');\n target = target.replace('socialShare', 'share');\n pctTracker.track(target);\n }\n }\n\n function hideModal(data) {\n var isHide = extension.modal.isHide();\n\n if (!state.modalContentActivated && isHide) {\n return;\n }\n\n extension.modal.hide();\n\n if (data && typeof data.callback === 'function') {\n data.callback();\n }\n\n if (typeof extension.modal.callback === 'function') {\n extension.modal.callback();\n extension.modal.callback = null;\n }\n\n if (extension.modal.focusedElement) {\n extension.modal.focusedElement.focus();\n }\n\n exports.queue.emit('show:action');\n }\n\n function showAddPlayListButton() {\n if (EL.ADD_PLAYLIST_BUTTON) {\n dt.classList.remove(EL.ADD_PLAYLIST_BUTTON, 'hide');\n }\n }\n\n function hideAddPlayListButton() {\n if (EL.ADD_PLAYLIST_BUTTON) {\n dt.classList.add(EL.ADD_PLAYLIST_BUTTON, 'hide');\n }\n }\n\n function showShareButton() {\n if (EL.SHARE_BUTTON) {\n dt.classList.remove(EL.SHARE_BUTTON, 'hide');\n }\n }\n\n function hideShareButton() {\n if (EL.SHARE_BUTTON) {\n dt.classList.add(EL.SHARE_BUTTON, 'hide');\n }\n }\n\n function showRelatedButton() {\n if (EL.RELATED_BUTTON) {\n dt.classList.remove(EL.RELATED_BUTTON, 'hide');\n }\n }\n\n function hideRelatedButton() {\n if (EL.RELATED_BUTTON) {\n dt.classList.add(EL.RELATED_BUTTON, 'hide');\n }\n }\n\n function closeModal(data) {\n inline.hideBlind();\n hideModal(data);\n }\n\n function initSharePanel() {\n if (state.currentVideo.isLegacy) {\n if (state.currentVideo.canScrap) {\n extension.share.embed.selectTab('sharePanelEmbed');\n extension.share.embed.hideTab('sharePanelUrl');\n extension.share.embed.togglePanel('sharePanelEmbed');\n }\n } else {\n if (state.currentVideo.canScrap) {\n extension.share.embed.showTab('sharePanelEmbed');\n extension.share.embed.selectTab('sharePanelUrl');\n extension.share.embed.togglePanel('sharePanelUrl');\n }\n }\n\n if (!state.currentVideo.canScrap) {\n extension.share.embed.hideTab('sharePanelEmbed');\n extension.share.embed.togglePanel('sharePanelUrl');\n }\n\n if (isSupportClipBoard) {\n dt.classList.remove(EL.SOCIAL_SHARE_URLCOPY, 'hide');\n } else {\n dt.classList.add(EL.SOCIAL_SHARE_URLCOPY, 'hide');\n }\n }\n\n function checkVisibleShareButton() {\n if (env.extensions) {\n if (ua.platform === 'pc') {\n if (state.currentVideo.isLegacy) {\n if (state.currentVideo.canScrap) {\n showShareButton();\n } else {\n hideShareButton();\n }\n } else {\n showShareButton();\n }\n } else {\n if (state.currentVideo.isLegacy) {\n hideShareButton();\n } else {\n showShareButton();\n }\n }\n } else {\n hideShareButton();\n }\n }\n\n function removeText(text) {\n var re = / |P|HD|4K/g;\n return text.replace(re, '');\n }\n\n function createProfileList(profileList) {\n extension.profile.create(profileList);\n }\n\n function createSubtitleList() {\n var textTracks = player.getTextTracks();\n\n if (textTracks.length > 0) {\n extension.subtitle.create(textTracks);\n }\n }\n\n function setSubtitle(subtitle) {\n player.setTextTrack(subtitle);\n extension.subtitle.setOn(subtitle);\n }\n\n var listener = {\n viewEvent: function() {\n var share = extension.share;\n\n event.on(EL.PLAYER_CONTROLLER, 'click', function(e) {\n if (e.target === EL.SHARE_BUTTON) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n inline.hideControl();\n\n if (ua.platform === 'pc') {\n share.embed.resetPanel();\n }\n\n exports.queue.emit('show:modal', {\n target: 'socialShare'\n });\n\n if (ua.platform === 'pc') {\n EL.SOCIAL_SHARE_KAKAOSTORY.focus();\n } else {\n EL.SOCIAL_SHARE_KAKAOTALK.focus();\n }\n }\n\n if (e.target === EL.ADD_PLAYLIST_BUTTON) {\n if (ua.platform === 'pc' && inline.isFullScreen()) {\n inline.cancelFullscreen(document);\n }\n\n exports.queue.emit('hide:nonelinear');\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onAddPlaylist, [\n state.currentVideo.clipId\n ]);\n pctTracker.track('keep');\n }\n\n if (e.target === EL.RELATED_BUTTON) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n inline.hideActivatedControl();\n exports.queue.emit('show:completion');\n\n pctTracker.track('related');\n }\n });\n\n event.delegate(EL.PLAYER_MODAL, '.kakaostory', 'click', function() {\n share.kakaostory();\n pctTracker.track('share', 'story');\n });\n\n event.delegate(EL.PLAYER_MODAL, '.facebook', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n share.facebook.open();\n pctTracker.track('share', 'facebook');\n });\n\n event.delegate(EL.PLAYER_MODAL, '.twitter', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n share.twitter();\n pctTracker.track('share', 'twitter');\n });\n\n event.delegate(EL.PLAYER_MODAL, '.cafe', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n share.cafe();\n });\n\n event.delegate(EL.PLAYER_MODAL, '.blog', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n share.blog();\n });\n\n event.delegate(EL.PLAYER_MODAL, CNAME.CLOSE_BUTTON, 'click', function() {\n exports.queue.emit('hide:modal');\n pctTracker.track('quit_layer');\n });\n\n event.on(EL.SHARE_URL, 'click', function() {\n selectTextField(this);\n });\n\n if (ua.platform === 'pc') {\n event.delegate(EL.SHARE_PANEL_EMBED, '.link_selected', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n share.embed.toggleSizeList();\n });\n\n event.delegate(EL.SHARE_PANEL_EMBED, '.link_select', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n var element = e.target;\n var size = element.getAttribute('data-size');\n\n share.embed.selectSize(size);\n share.embed.hideSizeList();\n });\n\n event.delegate(EL.SHARE_PANEL_EMBED, '.link_option', 'click', function() {\n share.embed.hideDefaultSetting();\n });\n\n event.delegate(EL.SHARE_PANEL_EMBED, '.inp_autoplay', 'click', function() {\n var autoplay = share.embed.getAutoPlay();\n share.embed.setOption();\n pctTracker.track('get_source', autoplay ? 'autoplay_check' : 'autoplay_uncheck');\n });\n\n event.delegate(EL.DETAIL_SETTING, '.btn_function', 'click', function(e) {\n var video = state.currentVideo;\n var playPointType = 'playpoint_first';\n\n if (dt.classList.has(e.target, 'btn_finish')) {\n share.embed.setOption();\n\n var checkedEl = $$('input[name=\"playType\"]:checked');\n if (dt.classList.has(checkedEl[0], 'current')) {\n playPointType = 'playpoint_now';\n } else if (dt.classList.has(checkedEl[0], 'point')) {\n playPointType = 'playpoint_custom';\n }\n\n if (video.type !== 'LIVE') {\n pctTracker.track('get_source', playPointType);\n }\n pctTracker.track('get_source', 'size_' + share.embed.getSelectedSize());\n }\n\n share.embed.showDefaultSetting();\n });\n\n event.delegate(EL.SOCIAL_SHARE, '.link_share', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n var current = e.target;\n var target = current.href.split('#')[1];\n\n share.embed.selectTab(target);\n share.embed.togglePanel(target);\n });\n\n event.on(EL.EMBED_URL, 'click', function() {\n selectTextField(this);\n });\n } else {\n // PC 카카오톡 공유하기 추가 전까지 모바일에만 적용되도록 분기 처리\n event.on(EL.KAKAOTALK_SHARE_BUTTON, 'click', function() {\n pctTracker.track('share', 'talk');\n });\n\n event.on(EL.PLAYER_MODAL, 'click', function(e) {\n if (e.target.tagName !== 'A' && e.target.tagName !== 'SPAN' && e.target.tagName !== 'INPUT') {\n exports.queue.emit('hide:modal');\n }\n });\n\n event.delegate(EL.SUBTITLE_LIST_CONTAINER, '.link_subtitle', 'click', function(e) {\n var buttonEl = e.target;\n var subtitle = buttonEl.getAttribute('data-subtitle');\n var subtitleText = subtitle === constants.SUBTITLE.STATUS.OFF ? subtitle : buttonEl.innerText;\n\n helpers.store.set(SUBTITLE_KEY, subtitle);\n\n if (!dt.classList.has(buttonEl.parentElement, 'on')) {\n setSubtitle(subtitle);\n }\n\n pctTracker.track('subtitles', subtitleText);\n });\n\n if (EL.PROFILE_LIST_CONTAINER) {\n event.delegate(EL.PROFILE_LIST_CONTAINER, '.link_quality', 'click', function(e) {\n var buttonEl = e.target;\n var profile = buttonEl.getAttribute('data-profile');\n\n if (!helpers.feature.supportsVideoProfile(profile) && !state.abr) {\n profile = constants.PROFILE.BASE;\n }\n\n if (state.abr) {\n state.currentVideo.profile = profile;\n shaka.setTrack(profile);\n } else {\n inline.getClipLocation(profile);\n }\n\n if (profile !== constants.PROFILE.AUTO) {\n helpers.store.set(PROFILE_KEY, state.abr ? constants.DASH_PROFILE[profile] : profile);\n helpers.store.set(ABR_KEY, false);\n } else {\n helpers.store.set(ABR_KEY, true);\n }\n\n inline.setProfile(profile);\n extension.profile.setOn(profile);\n exports.queue.emit('hide:modal');\n\n pvtTracker.pause();\n pctTracker.track('profile', state.abr ? constants.DASH_PROFILE[profile] : profile);\n });\n }\n }\n },\n customEvent: function(sandbox) {\n sandbox.on('show:modal', function(data) {\n showModal(data);\n });\n\n sandbox.on('hide:modal', function(data) {\n closeModal(data);\n });\n },\n clipboardEvent: function(clipboard) {\n clipboard.on('success', function(e) {\n extension.modal.hide();\n\n var delimiter = ua.platform !== 'pc' ? '
    ' : ' ';\n var relatedData = {\n message: ['URL을 복사했습니다.', delimiter, '원하는 곳에 붙여넣기 하세요.'].join(''),\n callback: function() {\n inline.hideBlind();\n extension.modal.show();\n\n if (state.ended) {\n inline.showControl(true);\n exports.queue.emit('show:completion');\n }\n }\n };\n exports.queue.emit('show:notification', relatedData);\n e.clearSelection();\n\n pctTracker.track('share', 'url_copy');\n });\n\n clipboard.on('error', function() {\n if (ua.platform !== 'pc') {\n dt.classList.remove(EL.COPYURL_BOX, 'hide');\n\n exports.queue.emit('show:modal', {\n target: 'copyUrlBox'\n });\n }\n });\n }\n };\n\n function Extension() {}\n\n Extension.prototype.init = function(player, sandbox) {\n this.videoElement = player.videoElement;\n var clipboard = new window.ClipboardJS('#socialShare .urlcopy', { container: $('playerContainer') });\n listener.viewEvent(player.videoElement);\n listener.customEvent(sandbox);\n listener.clipboardEvent(clipboard);\n\n if (helpers.device.isIeBrowser11Under(ua)) {\n extension.share.facebook.hide();\n }\n };\n\n Extension.prototype.hideModal = function(data) {\n closeModal(data);\n };\n\n Extension.prototype.showRelatedButton = function() {\n showRelatedButton();\n };\n\n Extension.prototype.hideRelatedButton = function() {\n hideRelatedButton();\n };\n\n Extension.prototype.onCompleteMeta = function() {\n var video = state.currentVideo;\n extension.share.setShareUrl();\n\n if (ua.platform === 'pc') {\n extension.share.embed.setEmbedUrl();\n initSharePanel();\n } else {\n if (video.kakaoLink) {\n extension.share.kakaotalk.create(video.kakaoLink);\n }\n }\n\n if (env.isInternal && env.showSave && !env.popup && video.status === 'AVAILABLE') {\n showAddPlayListButton();\n } else {\n hideAddPlayListButton();\n }\n checkVisibleShareButton();\n };\n\n Extension.prototype.createProfileList = function(profileList) {\n createProfileList(profileList);\n };\n\n Extension.prototype.setProfile = function(profile) {\n extension.profile.setOn(profile);\n };\n\n Extension.prototype.onLoadedData = function() {\n var storeSubtitle = helpers.store.get(SUBTITLE_KEY);\n if (state.currentVideo.type === constants.VIDEO_TYPE.VOD) {\n createSubtitleList();\n }\n\n if (storeSubtitle) {\n setSubtitle(storeSubtitle);\n }\n };\n\n return Extension;\n })();\n\n exports.addModule('view.extension', new Extension());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var inline = exports.loadModule('view.inline');\n var inlinePC = exports.loadModule('view.inline.pc');\n var shaka = exports.loadModule('player.shaka');\n var player = exports.loadModule('player.adapter');\n var error = exports.loadModule('view.error');\n var dataloader = exports.loadModule('playlist.dataloader');\n var state = exports.loadModule('controller.state');\n var extension = exports.loadModule('view.extension');\n var tracker = exports.loadModule('etc.tracker');\n var pctTracker = exports.loadModule('pct.tracker');\n\n var Completion;\n\n Completion = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n var playerTemplate = exports.template;\n\n var orien = new dt.Orientation();\n var iscroll;\n\n var EL = {\n COMPLETION_CONTAINER: $('completionContainer'),\n WAITING_CONTAINER: $('waitingContainer'),\n COMPLETION: $('completion'),\n WAITING: $('waiting'),\n NEXT_VIDEO_TITLE: $('nextVideoTitle'),\n COMPLETION_MORE_INFO: $$('#completion .more_info')[0],\n RECOMMENDED_CLIP_LIST: $$('#completion .list_item')[0],\n RECOMMENDED_CLIP_LIST_ITEM: $$('#completion .list_item li'),\n SCROLLER: $('scroller'),\n LIST: $$('#completionContainer ul')[0],\n SHARE_BUTTON: $$('#completion .btn_share')[0],\n CLOSE_BUTTON: $$('#completion .btn_close')[0],\n SOCIAL_SHARE_KAKAOTALK: $$('.kakaotalk')[0],\n SOCIAL_SHARE_KAKAOSTORY: $$('.kakaostory')[0],\n NEXT_BTN: $$('#completion .btn_next')[0],\n PREV_BTN: $$('#completion .btn_prev')[0],\n REPLAY_BTN: $$('#completion .link_replay')[0],\n ITEM_OTHER: $$('#completion .item_other')[0]\n };\n\n var loader = {\n relateClip: function(id, size) {\n var options = {\n uuid: helpers.uuid.get()\n };\n dataloader.getRelatedClip(id, options, size);\n },\n recommendClip: function(id, callback) {\n dataloader.getRecommendedClip(id, callback);\n }\n };\n\n var torosTracker = {\n commonFeedbackData: {},\n trackViewImp: function(viewImpContents) {\n if (viewImpContents && viewImpContents.length > 0) {\n tracker.tiara.trackViewImp({\n action: '',\n extra: {\n customProps: this.commonFeedbackData.viewImp.custom_props,\n viewImpContents: viewImpContents\n }\n });\n }\n },\n trackEvent: function(idx, customProps) {\n if (player.type === constants.VIDEO_TYPE.VOD) {\n tracker.tiara.trackEvent({\n extra: {\n click: {\n ordnum: idx,\n layer1: 'recommend_video'\n },\n customProps: customProps\n }\n });\n }\n }\n };\n\n var completion = {\n el: EL.COMPLETION,\n template: {\n clipList: ua.platform === 'pc' ? playerTemplate.pc_clip_list : playerTemplate.m_clip_list,\n noData: playerTemplate.list_no_data\n },\n clipList: [],\n first: 0,\n last: null,\n maxLength: null,\n totalItem: null,\n totalPageNum: null,\n nextItemCount: null,\n currentPage: 1,\n init: function(id, callback) {\n if (player.type === 'VOD') {\n var size = ua.platform === 'mobile' ? 10 : 36;\n loader.relateClip(id, size);\n } else if (player.type === 'LIVE') {\n loader.recommendClip(id, callback);\n }\n\n state.completionLoaded = true;\n },\n create: function(clipList) {\n var thumbnailUrl, coverImgUrl;\n var duration = '';\n\n var partial = {\n noData: this.template.noData\n };\n\n var view = {\n clipList: [],\n noDataList: function() {\n var noImageLength = 8;\n var j = 0;\n\n while (j < noImageLength) {\n j++;\n }\n return new Array(j);\n }\n };\n\n var size = 'C600x320';\n\n if (ua.platform === 'mobile') {\n size = 'C140x80';\n view.noDataList = [];\n }\n\n for (var i = 0; i < clipList.length; i++) {\n thumbnailUrl = clipList[i].clip.thumbnailUrl;\n\n if (thumbnailUrl) {\n coverImgUrl = helpers.string.getThumbnailFarmUrl(thumbnailUrl, size);\n }\n\n duration = helpers.string.delimitTimes(clipList[i].clip.duration);\n\n view.clipList.push({\n orderNum: i,\n linkUrl: '/embed/player/cliplink/' + clipList[i].id,\n clipLinkID: clipList[i].id,\n clipID: clipList[i].clip.id,\n channelID: clipList[i].channelId,\n imageUrl: coverImgUrl || '',\n title: clipList[i].clip.title || '',\n viewCount: clipList[i].clip.playCount || '',\n duration: duration\n });\n }\n\n var fragment = this.createTemplate(view, partial);\n this.render(fragment);\n },\n createTemplate: function(view, partial) {\n var template = this.template.clipList;\n return template.render(view, partial);\n },\n render: function(htmlStr) {\n var template = this.template.noData;\n EL.LIST.innerHTML = htmlStr;\n\n var thumbImgs = $$('.thumb_item', EL.LIST);\n if (thumbImgs && thumbImgs.length > 0) {\n for (var i = 0; i < thumbImgs.length; i++) {\n thumbImgs[i].onerror = function() {\n var liElement = this.parentElement.parentElement;\n liElement.innerHTML = template.render();\n };\n }\n }\n },\n resizeScroll: function() {\n var itemWidth = 189;\n var margin = 30;\n EL.SCROLLER.style.width = itemWidth * this.clipList.length + margin + 'px';\n },\n updateNavigation: function() {\n if (this.nextItemCount > 0) {\n dt.classList.remove(EL.NEXT_BTN, 'hide');\n\n if (this.last > this.totalItem) {\n dt.classList.add(EL.NEXT_BTN, 'hide');\n }\n } else {\n dt.classList.add(EL.NEXT_BTN, 'hide');\n }\n\n if (this.currentPage > 1) {\n dt.classList.remove(EL.PREV_BTN, 'hide');\n } else {\n dt.classList.add(EL.PREV_BTN, 'hide');\n\n if (this.nextItemCount > 0) {\n dt.classList.remove(EL.NEXT_BTN, 'hide');\n }\n }\n },\n updateListItemDisplay: function() {\n this.first = this.last - this.maxLength;\n var listItems = $$('li', EL.RECOMMENDED_CLIP_LIST);\n var feedbackData;\n var viewImpContents = [];\n\n for (var i = 0; i < listItems.length; i++) {\n dt.classList.add(listItems[i], 'hide');\n\n if (i >= this.first && i < this.last) {\n dt.classList.remove(listItems[i], 'hide');\n\n feedbackData = completion.clipList[i] && completion.clipList[i].feedbackData;\n if (feedbackData && feedbackData.viewImp && feedbackData.viewImp.viewimp_contents) {\n viewImpContents.push(feedbackData.viewImp.viewimp_contents);\n delete feedbackData.viewImp;\n }\n }\n }\n torosTracker.trackViewImp(viewImpContents);\n },\n calculate: function(pageNum) {\n this.maxLength = getMaxItemLength();\n this.currentPage = pageNum && pageNum > 1 ? pageNum : 1;\n this.last = this.maxLength * (pageNum || 1);\n\n if (!this.clipList || this.clipList.length < 1) {\n return;\n }\n\n if (this.last < this.totalItem) {\n this.nextItemCount = this.totalItem - this.last;\n } else {\n this.nextItemCount = 0;\n }\n },\n resize: function() {\n if (!state.modalContentActivated) {\n return;\n }\n\n if (ua.platform === 'pc') {\n this.calculate();\n completion.updateNavigation();\n completion.updateListItemDisplay();\n } else {\n this.resizeScroll();\n }\n },\n showPrev: function() {\n if (this.currentPage > 1) {\n this.currentPage = this.currentPage - 1;\n }\n\n debug.log('show prev', this.currentPage);\n\n this.calculate(this.currentPage);\n completion.updateNavigation();\n completion.updateListItemDisplay();\n },\n showNext: function() {\n if (this.nextItemCount > 0) {\n this.currentPage = this.currentPage + 1;\n }\n\n this.calculate(this.currentPage);\n completion.updateNavigation();\n completion.updateListItemDisplay();\n },\n show: function() {\n state.modalContentActivated = true;\n dt.classList.remove(EL.COMPLETION_CONTAINER, 'hide');\n },\n hide: function() {\n state.modalContentActivated = false;\n dt.classList.add(EL.COMPLETION_CONTAINER, 'hide');\n },\n showReplay: function() {\n if (EL.REPLAY_BTN) {\n dt.classList.remove(EL.REPLAY_BTN, 'hidden');\n }\n },\n hideReplay: function() {\n if (EL.REPLAY_BTN) {\n dt.classList.add(EL.REPLAY_BTN, 'hidden');\n }\n },\n showItem: function() {\n if (EL.ITEM_OTHER) {\n dt.classList.remove(EL.ITEM_OTHER, 'hidden');\n }\n },\n hideItem: function() {\n if (EL.ITEM_OTHER) {\n dt.classList.add(EL.ITEM_OTHER, 'hidden');\n }\n },\n showMoreInfo: function() {\n if (EL.COMPLETION_MORE_INFO) {\n dt.classList.add(EL.COMPLETION_MORE_INFO, 'visible');\n dt.classList.remove(EL.COMPLETION_MORE_INFO, 'hidden');\n }\n },\n hideMoreInfo: function() {\n if (EL.COMPLETION_MORE_INFO) {\n dt.classList.remove(EL.COMPLETION_MORE_INFO, 'visible');\n dt.classList.add(EL.COMPLETION_MORE_INFO, 'hidden');\n }\n },\n showShareButton: function() {\n if (EL.SHARE_BUTTON) {\n dt.classList.remove(EL.SHARE_BUTTON, 'hide');\n }\n },\n hideShareButton: function() {\n if (EL.SHARE_BUTTON) {\n dt.classList.add(EL.SHARE_BUTTON, 'hide');\n }\n },\n hideCloseButton: function() {\n if (EL.CLOSE_BUTTON) {\n dt.classList.add(EL.CLOSE_BUTTON, 'hide');\n }\n },\n showCloseButton: function() {\n if (EL.CLOSE_BUTTON) {\n dt.classList.remove(EL.CLOSE_BUTTON, 'hide');\n }\n }\n };\n\n var waiting = {\n el: EL.WAITING,\n autoPlayTimer: null,\n progressBar: null,\n clearTimer: function() {\n if (this.autoPlayTimer) {\n clearTimeout(this.autoPlayTimer);\n }\n },\n show: function(callback) {\n var self = this;\n\n if (!this.el) {\n return;\n }\n\n dt.classList.remove(EL.WAITING_CONTAINER, 'hide');\n dt.classList.remove(this.el, 'hidden');\n dt.classList.add(this.el, 'visible');\n\n this.clearTimer();\n this.progress();\n\n this.autoPlayTimer = setTimeout(function() {\n if (callback && typeof callback === 'function') {\n callback();\n }\n\n self.autoPlayTimer = null;\n }, 5000);\n },\n hide: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'visible');\n dt.classList.add(this.el, 'hidden');\n dt.classList.add(EL.WAITING_CONTAINER, 'hide');\n }\n },\n progress: function() {\n if (!this.progressBar) {\n this.progressBar = new window.ProgressBar.Circle('#loaderCircle', {\n strokeWidth: 6,\n easing: 'linear',\n duration: 5000,\n color: '#FAE100'\n });\n }\n this.progressBar.set(0);\n this.progressBar.animate(1);\n }\n };\n\n function scrollEndUpdate(position) {\n var orientation = helpers.orientation.getOrientation();\n\n if (orientation === 'landscape' && window.innerWidth >= 480) {\n return;\n }\n\n if (position < 0) {\n completion.hideMoreInfo();\n } else {\n completion.showMoreInfo();\n }\n }\n\n function attachEventForMobile() {\n iscroll = new window.IScroll('#scrollWrap', {\n probeType: 1,\n scrollX: true,\n snap: true,\n click: true,\n momentum: true,\n resizePolling: 30,\n disablePointer: false,\n disableTouch: false,\n disableMouse: false\n });\n\n iscroll.on('scroll', function() {\n scrollEndUpdate(this.x);\n });\n\n iscroll.on('scrollEnd', function() {\n scrollEndUpdate(this.x);\n });\n\n orien.onPortrait(function() {\n scrollEndUpdate(iscroll.x);\n });\n\n orien.onLandscape(function() {\n completion.showMoreInfo();\n });\n }\n\n function getMaxItemLength() {\n var maxItemLength = 9;\n var listItemLength = $$('li', EL.RECOMMENDED_CLIP_LIST).length;\n\n if (listItemLength > 0) {\n if (window.innerWidth >= 1024) {\n maxItemLength = 9;\n } else if (window.innerWidth >= 850 && window.innerWidth < 1024) {\n maxItemLength = 6;\n } else if (window.innerWidth >= 640 && window.innerWidth < 850) {\n maxItemLength = 4;\n } else if (window.innerWidth >= 560 && window.innerWidth < 640) {\n maxItemLength = 2;\n } else if (window.innerWidth < 560) {\n maxItemLength = 1;\n }\n\n if (ua.platform === 'mobile') {\n maxItemLength = 10;\n }\n\n debug.info('maxItemLength', maxItemLength);\n }\n return maxItemLength;\n }\n\n function attachEventForPC() {\n event.on(\n window,\n 'resize',\n helpers.waiter.throttle(function() {\n var prevMaxLength = completion.maxLength;\n\n if (prevMaxLength !== getMaxItemLength()) {\n completion.resize();\n }\n }, 50)\n );\n }\n\n function createCompletion(callback) {\n if (!state.completionLoaded) {\n completion.init(state.currentVideo.id, callback);\n }\n\n if (ua.platform !== 'pc') {\n attachEventForMobile();\n } else {\n attachEventForPC();\n }\n }\n\n function renderCompletion() {\n if (completion.clipList && completion.clipList.length > 0) {\n completion.create(completion.clipList);\n completion.calculate();\n }\n }\n\n function showExtensionButton() {\n if (!state.ended) {\n completion.hideShareButton();\n completion.showCloseButton();\n } else {\n if (env.extensions) {\n if (!state.currentVideo.canScrap && state.currentVideo.isLegacy) {\n completion.hideShareButton();\n } else {\n completion.showShareButton();\n }\n } else {\n completion.hideShareButton();\n }\n\n completion.hideCloseButton();\n }\n }\n\n function showCompletion() {\n debug.log('showCompletion', state.hasRelated);\n\n if (state.hasRelated) {\n if (ua.platform !== 'pc') {\n setTimeout(function() {\n iscroll.refresh();\n }, 100);\n } else {\n completion.showItem();\n completion.updateNavigation();\n completion.updateListItemDisplay();\n completion.hideReplay();\n showExtensionButton();\n }\n } else {\n if (!state.ended) {\n return;\n }\n\n completion.hideItem();\n completion.showReplay();\n completion.hideCloseButton();\n if (state.currentVideo.canScrap) {\n completion.showShareButton();\n }\n }\n renderCompletion();\n completion.show();\n\n if (player.type !== constants.VIDEO_TYPE.LIVE && ua.platform === 'pc') {\n completion.updateNavigation();\n completion.updateListItemDisplay();\n }\n exports.queue.emit('hide:action');\n }\n\n function hideCompletion() {\n completion.hide();\n\n if (!state.ended) {\n exports.queue.emit('show:action');\n }\n }\n\n function showWaiting(callback) {\n waiting.show(callback);\n }\n\n function hideWaiting() {\n waiting.hide();\n }\n\n function goRecommendedClip(channelId, clipLinkId, feedbackData) {\n var channelViewLink = '/channel/' + channelId + '/cliplink/' + clipLinkId;\n\n if (env.isInternal && !env.popup) {\n top.location.href = channelViewLink;\n } else {\n if (player.type === constants.VIDEO_TYPE.LIVE) {\n location.href = env.host + '/embed/player/cliplink/' + clipLinkId + '?service=' + env.service;\n } else {\n exports.queue.emit(\n 'loadAndPlay:videoById:withPlayerUnload',\n clipLinkId,\n state.currentVideo.profile,\n 0,\n feedbackData\n );\n }\n }\n }\n\n function onClickRecommendedList(e) {\n var target = e.target.closest('.link_item');\n var clipLinkId = target.getAttribute('data-cliplink-id');\n var channelId = target.getAttribute('data-channel-id');\n\n exports.queue.emit('hide:completion');\n exports.queue.emit('hide:error');\n\n var orderNum = target.getAttribute('data-order-num');\n var clipListItem = completion.clipList[orderNum];\n\n var feedbackData = {};\n if (clipListItem && clipListItem.feedbackData) {\n feedbackData = clipListItem.feedbackData;\n\n if (feedbackData.event && feedbackData.event.custom_props) {\n torosTracker.trackEvent(orderNum, feedbackData.event.custom_props);\n }\n }\n\n pctTracker.track('relate_clip', clipLinkId);\n goRecommendedClip(channelId, clipLinkId, feedbackData);\n }\n\n var listener = {\n dataloaderEvent: function(sandbox) {\n sandbox.on('load:clip:related', function(result) {\n if (result.status !== 'success') {\n return;\n }\n\n completion.clipList = result.data.list;\n completion.totalItem = completion.clipList.length;\n torosTracker.commonFeedbackData = result.data.commonFeedbackData;\n\n if (completion.clipList.length > 0) {\n state.hasRelated = true;\n extension.showRelatedButton();\n renderCompletion();\n } else {\n state.hasRelated = false;\n extension.hideRelatedButton();\n }\n });\n\n sandbox.on('load:clip:recommended', function(result) {\n debug.log('load:clip:recommended', result);\n\n if (\n result.status !== 'success' ||\n (player.type === constants.VIDEO_TYPE.LIVE && ua.platform === 'pc')\n ) {\n return;\n }\n\n completion.clipList = result.data.list;\n torosTracker.commonFeedbackData = result.data.commonFeedbackData;\n\n if (completion.clipList.length > 0) {\n state.hasRelated = true;\n renderCompletion();\n\n var errorStatus = error.getErrorStatus();\n if (state.isShowError && errorStatus.NAME === 'LiveFinished') {\n showCompletion();\n }\n } else {\n state.hasRelated = false;\n error.addStyle('no_data');\n debug.warn('recommended clip is empty');\n }\n\n if (result.callback && typeof result.callback === 'function') {\n result.callback(result);\n }\n });\n },\n viewEvent: function() {\n if (!helpers.device.isSupportCustomController(ua)) {\n return;\n }\n\n event.delegate(EL.COMPLETION_CONTAINER, '.btn_share', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n exports.queue.emit('hide:completion');\n\n var callback = function() {\n exports.queue.emit('show:completion');\n };\n\n exports.queue.emit('show:modal', { target: 'socialShare', callback: callback });\n\n if (ua.platform === 'pc') {\n var isfreeze = true;\n inline.showControl(isfreeze);\n EL.SOCIAL_SHARE_KAKAOSTORY.focus();\n } else {\n EL.SOCIAL_SHARE_KAKAOTALK.focus();\n }\n });\n\n event.delegate(EL.COMPLETION_CONTAINER, '.btn_plus', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onAddPlaylist, [\n state.currentVideo.clipId\n ]);\n });\n\n event.delegate(EL.COMPLETION_CONTAINER, '.link_replay', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n exports.queue.emit('hide:completion');\n\n if (state.abr) {\n shaka.unload();\n }\n var profile = state.abr\n ? constants.DASH_PROFILE[state.currentVideo.profile]\n : state.currentVideo.profile;\n\n exports.queue.emit('loadAndPlay:videoById:withPlayerUnload', state.currentVideo.id, profile, 0);\n pctTracker.track('replay');\n });\n\n event.delegate(EL.COMPLETION_CONTAINER, '.btn_close', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n exports.queue.emit('hide:completion');\n });\n\n event.delegate(EL.COMPLETION_CONTAINER, '.btn_prev', 'click', function() {\n completion.showPrev();\n });\n\n event.delegate(EL.COMPLETION_CONTAINER, '.btn_next', 'click', function() {\n completion.showNext();\n });\n\n event.delegate(EL.COMPLETION_CONTAINER, '.link_item', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n onClickRecommendedList(e);\n });\n\n if (ua.platform === 'pc') {\n event.delegate(EL.WAITING_CONTAINER, '.link_waiting', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n debug.info('link_waiting', e.target);\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onEndAutoPlayTimer);\n });\n\n event.delegate(EL.WAITING_CONTAINER, '.link_next', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onEndAutoPlayTimer);\n });\n\n event.delegate(EL.WAITING_CONTAINER, '.link_cancel', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n waiting.clearTimer();\n waiting.hide();\n\n inlinePC.onEndVideo();\n });\n }\n },\n customEvent: function(player, sandbox) {\n sandbox.on('show:completion', function() {\n showCompletion();\n });\n\n sandbox.on('hide:completion', function() {\n hideCompletion();\n });\n\n sandbox.on('create:completion', function() {\n createCompletion();\n });\n }\n };\n\n function Completion() {}\n\n Completion.prototype.init = function(player, sandbox) {\n listener.dataloaderEvent(sandbox);\n listener.viewEvent();\n listener.customEvent(player, sandbox);\n };\n\n Completion.prototype.createCompletion = function(callback) {\n createCompletion(callback);\n };\n\n Completion.prototype.showCompletion = function() {\n showCompletion();\n };\n\n Completion.prototype.hideCompletion = function() {\n hideCompletion();\n };\n\n Completion.prototype.setNextVideo = function(title) {\n if (EL.NEXT_VIDEO_TITLE) {\n EL.NEXT_VIDEO_TITLE.innerHTML = title;\n }\n };\n\n Completion.prototype.hasNextVideo = function() {\n var title = EL.NEXT_VIDEO_TITLE.innerHTML;\n return title !== '';\n };\n\n Completion.prototype.showWaiting = function() {\n showWaiting.apply(this, arguments);\n };\n\n Completion.prototype.hideWaiting = function() {\n hideWaiting();\n };\n\n return Completion;\n })();\n\n exports.addModule('view.completion', new Completion());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n var shaka = exports.loadModule('player.shaka');\n var state = exports.loadModule('controller.state');\n var inline = exports.loadModule('view.inline');\n\n var Retry;\n\n Retry = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n\n var helpers = exports.helpers;\n var constants = exports.constants;\n var debug = helpers.debug;\n\n var timer;\n\n var EL = {\n RETRY_CONTAINER: $('retryContainer'),\n RETRY_BUTTON: $$('#retryContainer .link_retry')\n };\n\n var retry = {\n el: EL.RETRY_CONTAINER,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n }\n };\n\n function showRetry() {\n exports.queue.emit('layerStatus:check');\n retry.show();\n }\n\n function hideRetry() {\n retry.hide();\n }\n\n function clearTimer() {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n\n function setTimer() {\n var pastTime = player.getCurrentTimeRound();\n\n clearTimer();\n\n timer = setTimeout(function() {\n var currentTime = player.getCurrentTimeRound();\n\n var isTimeout = currentTime > 0 && currentTime <= pastTime;\n\n inline.endSpinner();\n\n if (!state.ended && isTimeout) {\n debug.log('[timeout - showRetry]', 'pastTime: ' + pastTime, 'currentTime: ' + currentTime);\n if (state.currentVideo && state.currentVideo.type !== 'LIVE') {\n showRetry();\n }\n }\n }, 8 * 1000);\n }\n\n var listener = {\n viewEvent: function() {\n event.delegate(EL.RETRY_CONTAINER, '.link_retry', 'click', function(e) {\n event.preventDefault(e);\n event.stopPropagation(e);\n\n hideRetry();\n\n if (state.abr) {\n shaka.unload();\n }\n var profile = state.abr\n ? constants.DASH_PROFILE[state.currentVideo.profile]\n : state.currentVideo.profile;\n\n exports.queue.emit('loadAndPlay:videoById', state.currentVideo.id, profile);\n });\n }\n };\n\n function Retry() {}\n\n Retry.prototype.init = function() {\n listener.viewEvent();\n };\n\n Retry.prototype.showRetry = function() {\n showRetry();\n };\n\n Retry.prototype.hideRetry = function() {\n hideRetry();\n };\n\n Retry.prototype.setTimer = function() {\n setTimer();\n };\n\n Retry.prototype.clearTimer = function() {\n hideRetry();\n clearTimer();\n };\n\n Retry.prototype.resetTimer = function() {\n hideRetry();\n setTimer();\n };\n\n return Retry;\n })();\n\n exports.addModule('view.retry', new Retry());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n function Confirm() {}\n\n Confirm.prototype = (function() {\n var state = exports.loadModule('controller.state');\n var error = exports.loadModule('view.error');\n var pctTracker = exports.loadModule('pct.tracker');\n\n var $ = dt.$;\n var $$ = dt.$$;\n var ua = exports.ua;\n var event = dt.event;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var CONFIRM = constants.CONFIRM;\n var env = exports.ENV;\n var PHASE = constants.PHASE[env.phase.toUpperCase()];\n\n var EL = {\n CONFIRM: $('confirmView'),\n CONFIRM_INFO: $('confirmInfo'),\n COVER_IMAGE: $('coverImage2'),\n PASSWORD_FORM: $$('.pass_input form')[0],\n PASSWORD_INPUT: $('inpPass'),\n PASSWORD_BUTTON: $('btnPass'),\n PASSWORD_LABEL: $('lblPass'),\n PASSWORD_TITLE: $('titPass'),\n PURCHASE_BUTTON: $('btnPurchase'),\n PURCHASE_REPLAY: $('btnPurchaseReplay'),\n THUMBNAIL_CONTAINER: $('confirmThumbnailImageContainer'),\n THUMBNAIL_IMAGE: $('confirmThumbnailImage')\n };\n\n var confirmEl = {\n el: EL.CONFIRM,\n acceptCallback: function() {},\n cancelCallback: function() {},\n setOption: function(option) {\n dt.extend(this, option, true);\n },\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n },\n showBackground: function() {\n if (EL.COVER_IMAGE) {\n dt.classList.remove(EL.COVER_IMAGE, 'hide');\n }\n },\n hideBackground: function() {\n if (EL.COVER_IMAGE) {\n dt.classList.add(EL.COVER_IMAGE, 'hide');\n }\n },\n setPasswordBtnDisable: function() {\n if (EL.PASSWORD_BUTTON) {\n dt.classList.add(EL.PASSWORD_BUTTON, 'btn_disabled');\n dt.classList.remove(EL.PASSWORD_LABEL, 'screen_out');\n EL.PASSWORD_BUTTON.disabled = true;\n }\n },\n setPasswordBtnEnable: function() {\n if (EL.PASSWORD_BUTTON) {\n dt.classList.remove(EL.PASSWORD_BUTTON, 'btn_disabled');\n dt.classList.add(EL.PASSWORD_LABEL, 'screen_out');\n EL.PASSWORD_BUTTON.disabled = false;\n }\n },\n setPasswordTitle: function(text) {\n if (EL.PASSWORD_TITLE) {\n EL.PASSWORD_TITLE.innerHTML = text;\n }\n },\n setPurchaseBtnText: function(text) {\n if (EL.PURCHASE_BUTTON) {\n EL.PURCHASE_BUTTON.innerHTML = text;\n }\n },\n setThumbnailImage: function(url) {\n if (EL.THUMBNAIL_IMAGE) {\n EL.THUMBNAIL_IMAGE.style['background'] = 'url(' + url + ')';\n EL.THUMBNAIL_IMAGE.style['background-size'] = '100%';\n }\n },\n showThumbnailImage: function() {\n if (EL.THUMBNAIL_CONTAINER) {\n dt.classList.remove(EL.THUMBNAIL_CONTAINER, 'hide');\n }\n }\n };\n\n function getConfirmStatus(code) {\n var status = CONFIRM.STATUS[code];\n var isSupportH264 = helpers.feature.supportsH264();\n var isSupportHLS = !!(helpers.feature.canPlayHLSAndroid() || helpers.feature.canPlayHLS());\n\n if (code === CONFIRM.STATUS.NeedLogin.NAME || code === CONFIRM.STATUS.NeedPassword) {\n if (ua.platform === 'mobile') {\n if (!isSupportH264 || !isSupportHLS) {\n status = CONFIRM.STATUS.NeedLaunchApp;\n }\n }\n }\n\n return status;\n }\n\n function show(statusCode, info, option) {\n exports.queue.emit('spinner:end');\n exports.queue.emit('hide:cover');\n\n var confirmStatus = getConfirmStatus(statusCode);\n debug.info('confirmStatus', confirmStatus);\n\n if (!confirmStatus) {\n return;\n }\n\n resetConfirmView();\n error.setTemplate(confirmStatus, info, EL.CONFIRM_INFO);\n\n if (statusCode !== CONFIRM.STATUS.NeedLogin.NAME && statusCode === CONFIRM.STATUS.NeedPassword) {\n confirmEl.showBackground();\n }\n\n if (statusCode === CONFIRM.STATUS.PasswordIncorrect.NAME) {\n confirmEl.setPasswordTitle(info.message);\n confirmEl.setPasswordBtnDisable();\n }\n\n if (\n statusCode === CONFIRM.STATUS.NoPurchased.NAME ||\n statusCode === CONFIRM.STATUS.NeedPurchased.NAME ||\n statusCode === CONFIRM.STATUS.NoPurchasedForMobile.NAME\n ) {\n var text = ua.platform === 'mobile' ? '카카오톡에서 구매하기' : '카카오톡으로 구매 링크 받기';\n confirmEl.setPurchaseBtnText(text);\n\n if (info.preview) {\n if (EL.PURCHASE_REPLAY) {\n dt.classList.remove(EL.PURCHASE_REPLAY, 'hide');\n }\n }\n }\n\n confirmEl.setOption(option);\n confirmEl.show();\n }\n\n function showConfirmThumbnailImage() {\n if (state.currentVideo && state.currentVideo.coverUrl) {\n confirmEl.setThumbnailImage(state.currentVideo.coverUrl);\n }\n confirmEl.showThumbnailImage();\n }\n\n function resetConfirmView() {\n var buttons = $$('.function_btn>div', EL.CONFIRM_INFO);\n for (var i = 0; i < buttons.length; i++) {\n dt.classList.add(buttons[i], 'hide');\n }\n }\n\n function hide() {\n confirmEl.hide();\n }\n\n function checkLogin(callback) {\n var _callback = function() {};\n\n if (typeof callback === 'function') {\n _callback = callback;\n }\n\n window.Kakao.Auth.getStatusInfo(function(status) {\n debug.log('Auth status', status);\n\n if (status !== undefined && status.status !== undefined) {\n if (status.status === 'not_connected') {\n window.Kakao.Auth.login({\n persistAccessToken: false,\n persistRefreshToken: false,\n success: function() {\n _callback();\n },\n fail: function() {\n alert('로그인에 실패하였습니다. 다시 시도해 주세요.');\n },\n throughTalk: false\n });\n } else {\n location.reload();\n }\n }\n });\n }\n\n var listener = {\n viewEvent: function() {\n event.delegate(EL.CONFIRM, '.cancel', 'click', function() {\n debug.log('cancel');\n confirmEl.cancelCallback();\n hide();\n });\n event.delegate(EL.CONFIRM, '.accept', 'click', function() {\n debug.log('accept');\n confirmEl.acceptCallback();\n hide();\n });\n event.delegate(EL.CONFIRM, '.link_refresh', 'click', function() {\n location.reload();\n });\n event.delegate(EL.CONFIRM, '.login button', 'click', function(e) {\n if (e.target.tagName === 'BUTTON') {\n checkLogin(function() {\n e.target.innerHTML = '인증완료';\n location.reload();\n });\n\n pctTracker.track('login');\n }\n });\n\n event.on(EL.PASSWORD_FORM, 'submit', function(e) {\n e.preventDefault();\n\n var password = EL.PASSWORD_INPUT.value;\n EL.PASSWORD_INPUT.value = '';\n confirmEl.hide();\n\n state.currentVideo = state.currentVideo || {};\n state.currentVideo.playingInfo = null;\n state.currentVideo.profile = env.profile;\n state.currentVideo.password = password;\n exports.queue.emit('load:videoById', 0, true, password);\n\n pctTracker.track('password', 'play');\n });\n\n event.delegate(EL.CONFIRM, '.inp_pass', 'input', function(e) {\n e.preventDefault();\n\n if (e.target.value) {\n confirmEl.setPasswordBtnEnable();\n } else {\n confirmEl.setPasswordBtnDisable();\n }\n });\n event.delegate(EL.CONFIRM, '.app', 'click', function() {\n var profile = constants.PROFILE.HIGH;\n var linkId = state.currentVideo.id;\n\n helpers.web2app.launchKakaoTV(ua, linkId, profile);\n pctTracker.track('liveapp_only');\n });\n event.delegate(EL.CONFIRM, '.btn_purchase', 'click', function(e) {\n e.preventDefault();\n var purchaseUrl = e.target.getAttribute('data-url');\n var purchasePoint;\n\n if (ua.platform === 'mobile') {\n helpers.web2app.launchTalk(purchaseUrl);\n purchasePoint = 'finished';\n } else {\n var video = state.currentVideo;\n var templateID = PHASE === constants.PHASE.SANDBOX ? 865 : 37938;\n var templateArgs = {};\n templateArgs.title = video.channelName + ' - ' + video.title;\n templateArgs.description = '영상 시청을 위해 구매가 필요합니다.';\n templateArgs.thumbnail_url = video.coverUrl;\n templateArgs.mobile_url = purchaseUrl;\n var relatedData = {\n message: '',\n callback: function() {\n exports.queue.emit('hide:modal');\n }\n };\n\n helpers.kakao.sendMe(\n templateID,\n templateArgs,\n function() {\n relatedData.message = '카카오톡으로 구매 링크가 발송되었습니다.';\n exports.queue.emit('show:notification', relatedData);\n },\n function() {\n relatedData.message = '카카오톡이 연결된 카카오TV 계정 로그인이 필요합니다.';\n exports.queue.emit('show:notification', relatedData);\n }\n );\n }\n pctTracker.track('original_tvod', 'purchase', purchasePoint);\n });\n\n event.delegate(EL.CONFIRM, '.btn_replay', 'click', function() {\n confirmEl.hide();\n var profile = state.abr\n ? constants.DASH_PROFILE[state.currentVideo.profile]\n : state.currentVideo.profile;\n\n pctTracker.track('original_tvod', 'refresh');\n\n exports.queue.emit('loadAndPlay:videoById', state.currentVideo.id, profile);\n });\n },\n customEvent: function(sandbox) {\n sandbox.on('show:confirm', function(data) {\n show(data.status, data.info, data.option);\n debug.info('show confirm');\n });\n\n sandbox.on('hide:confirm', function() {\n hide();\n debug.info('hide confirm');\n });\n\n sandbox.on('show:confirmThumbnailImage', function() {\n showConfirmThumbnailImage();\n debug.info('show confirmThumbnailImage');\n });\n }\n };\n\n return {\n init: function(player, sandbox) {\n listener.viewEvent();\n listener.customEvent(sandbox);\n },\n show: function(statusCode, info, option) {\n show(statusCode, info, option);\n },\n hide: function() {\n hide();\n }\n };\n })();\n\n exports.addModule('view.confirm', new Confirm());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var player = exports.loadModule('player.adapter');\n var pctTracker = exports.loadModule('pct.tracker');\n\n var Cast;\n\n Cast = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var event = dt.event;\n\n var ua = exports.ua;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n var EL = {\n TV_CAST_BOX: $$('.cast_tv')[0],\n AIRPLAY: $('airplay'),\n CHROMECAST: $('chromecast'),\n CHROMECAST_BOX: $$('.box_chromecast')[0],\n CONNECTED_DEVICE_TEXT: $$('.connected_device')[0]\n };\n\n var cast = {\n castBox: {\n el: EL.TV_CAST_BOX,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n }\n },\n chromecastBox: {\n el: EL.CHROMECAST_BOX,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n }\n },\n airplay: {\n el: EL.AIRPLAY,\n show: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'hide');\n }\n },\n hide: function() {\n if (this.el) {\n dt.classList.add(this.el, 'hide');\n }\n },\n connected: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'disconnected');\n dt.classList.add(this.el, 'connected');\n }\n },\n disconnected: function() {\n if (this.el) {\n dt.classList.remove(this.el, 'connected');\n dt.classList.add(this.el, 'disconnected');\n }\n }\n },\n text: {\n setConnectedDeviceText: function(device) {\n if (EL.CONNECTED_DEVICE_TEXT) {\n EL.CONNECTED_DEVICE_TEXT.innerText = device;\n }\n }\n }\n };\n\n var listener = {\n viewEvent: function() {\n if (ua.platform === 'pc') {\n var videoElement = player.videoElement;\n\n if (window.WebKitPlaybackTargetAvailabilityEvent) {\n videoElement.addEventListener('webkitplaybacktargetavailabilitychanged', function(event) {\n debug.log('[AirPlay Event] airplay button state: ', event.availability);\n\n switch (event.availability) {\n case 'available':\n cast.castBox.show();\n cast.airplay.disconnected();\n cast.airplay.show();\n break;\n case 'not-available':\n cast.airplay.hide();\n break;\n }\n });\n }\n\n if (EL.TV_CAST_BOX) {\n event.on(EL.TV_CAST_BOX, 'click', function(e) {\n if (e.target === EL.AIRPLAY) {\n if (!window.WebKitPlaybackTargetAvailabilityEvent) {\n return;\n }\n\n videoElement.webkitShowPlaybackTargetPicker();\n\n pctTracker.track('airplay');\n }\n\n if (e.target === EL.CHROMECAST) {\n pctTracker.track('chromecast');\n }\n });\n }\n }\n }\n };\n\n function Cast() {}\n\n Cast.prototype.init = function() {\n listener.viewEvent();\n };\n\n Cast.prototype.showBox = function() {\n cast.castBox.show();\n };\n\n Cast.prototype.hideBox = function() {\n cast.castBox.hide();\n };\n\n Cast.prototype.showChromecastBox = function() {\n cast.chromecastBox.show();\n };\n\n Cast.prototype.hideChromecastBox = function() {\n cast.chromecastBox.hide();\n };\n\n Cast.prototype.showConnected = function() {\n cast.airplay.connected();\n };\n\n Cast.prototype.showDisconnected = function() {\n cast.airplay.disconnected();\n };\n\n Cast.prototype.setConnectedDeviceText = function(device) {\n cast.text.setConnectedDeviceText(device);\n };\n\n return Cast;\n })();\n\n exports.addModule('view.cast', new Cast());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var inline = exports.loadModule('view.inline');\n var completion = exports.loadModule('view.completion');\n var mediaSession = exports.loadModule('media.session');\n var state = exports.loadModule('controller.state');\n\n var ImaAds;\n\n ImaAds = (function() {\n var $ = dt.$;\n var ua = exports.ua;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n var adsLoader;\n var adsManager;\n var adDisplayContainer;\n var videoEndedCallback;\n var videoContent;\n var adsDone = false;\n var contentCompleteCalled = false;\n var googleIma = window.google && window.google.ima;\n\n var IMAERRORCODE = {\n VAST_EMPTY_RESPONSE: 1009\n };\n\n var PAT = {\n URL_LIST: {},\n PARAM: {},\n EVENT: {\n IMPRESSION: 'impression',\n START: 'start',\n SKIP: 'skip',\n CLICK: 'click',\n COMPLETE: 'complete',\n FIRST_QUARTILE: 'firstQuartile',\n MID_POINT: 'midpoint',\n THIRD_QUARTILE: 'thirdQuartile',\n PAUSE: 'pause',\n RESUME: 'resume',\n PROGRESS: 'progress',\n ERROR: 'error'\n }\n };\n\n var TAG_URL = {\n LINEAR_PC_VOD:\n 'https://googleads.g.doubleclick.net/pagead/ads?' +\n 'client=ca-video-pub-3302927352513848&' +\n 'slotname=9888066795&' +\n 'ad_type=skippablevideo&' +\n 'description_url=https%3A%2F%2Ftv.kakao.com&' +\n 'videoad_start_delay=0'\n };\n\n var EL = {\n AD_CONTAINER: $('adContainer')\n };\n\n var videoAdUI = {\n el: EL.AD_CONTAINER,\n show: function() {\n dt.classList.remove(this.el, 'hidden');\n dt.classList.add(this.el, 'visible');\n },\n hide: function() {\n dt.classList.remove(this.el, 'visible');\n dt.classList.add(this.el, 'hidden');\n }\n };\n\n function onAdError(adErrorEvent) {\n var error = adErrorEvent.getError();\n var errorCode = error.getErrorCode();\n var errorMessage = error.getMessage();\n\n if (adsManager) {\n adsManager.destroy();\n }\n if (typeof videoEndedCallback === 'function') {\n videoEndedCallback();\n }\n\n if (errorCode === IMAERRORCODE.VAST_EMPTY_RESPONSE) {\n debug.warn('Ad event: Error ', errorMessage);\n } else {\n debug.error('Ad event: Error Code = ', errorCode, errorMessage);\n }\n }\n\n function normalizeURL(eventName) {\n var trackUrl = PAT.URL_LIST[eventName] && PAT.URL_LIST[eventName].url;\n\n if (!trackUrl) {\n return;\n }\n\n if (PAT.URL_LIST[eventName] && eventName !== PAT.EVENT.PAUSE && eventName !== PAT.EVENT.RESUME) {\n delete PAT.URL_LIST[eventName];\n }\n\n if (!PAT.PARAM.mediaUrl) {\n var currentAdData = adsManager.getCurrentAd();\n PAT.PARAM.duration = currentAdData.getDuration();\n PAT.PARAM.skipOffset = currentAdData.getSkipTimeOffset();\n PAT.PARAM.mediaUrl = encodeURIComponent(currentAdData.getMediaUrl());\n }\n\n debug.info('normalizeURL eventName = ' + eventName);\n\n trackUrl = trackUrl\n .replace('[DURATION]', PAT.PARAM.duration)\n .replace('[SKIPOFFSET]', PAT.PARAM.skipOffset)\n .replace('[MEDIAURL]', PAT.PARAM.mediaUrl);\n\n return trackUrl;\n }\n\n function track(eventName) {\n var trackUrl = normalizeURL(eventName);\n\n if (!trackUrl) {\n return;\n }\n\n helpers.http.sendBeacon(trackUrl);\n\n debug.info('pat event', eventName, trackUrl);\n }\n\n function contentEndedListener() {\n contentCompleteCalled = true;\n adsLoader.contentComplete();\n\n if (typeof videoEndedCallback === 'function') {\n videoEndedCallback();\n }\n }\n\n function onContentPauseRequested() {\n debug.info('Ad event: CONTENT_PAUSE_REQUESTED');\n videoContent.pause();\n videoContent.removeEventListener('ended', contentEndedListener);\n }\n\n function onContentResumeRequested() {\n debug.info('Ad event: CONTENT_RESUME_REQUESTED');\n videoContent.addEventListener('ended', contentEndedListener);\n\n if (!contentCompleteCalled) {\n videoContent.play();\n }\n }\n\n function startAds() {\n adsManager.init('100%', '100%', googleIma.ViewMode.NORMAL);\n adsManager.start();\n }\n\n function updateMediaSessionMetadata() {\n var title = '광고 재생 중입니다.';\n var isPlayGdn = true;\n\n mediaSession.updateMetadata(title, isPlayGdn);\n }\n\n function onAdsManagerLoaded(adsManagerLoadedEvent) {\n var adsRenderingSettings = new googleIma.AdsRenderingSettings();\n // Tell the SDK NOT to save and restore content video state on our behalf.\n adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = false;\n\n adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings);\n\n var googleAdEventType = googleIma.AdEvent.Type;\n var googleAdErrorEventType = googleIma.AdErrorEvent.Type;\n\n adsManager.addEventListener(googleAdErrorEventType.AD_ERROR, onAdError);\n\n adsManager.addEventListener(googleAdEventType.IMPRESSION, function() {\n debug.info('gdn event - impression');\n\n state.onIma = true;\n\n track(PAT.EVENT.IMPRESSION);\n });\n\n adsManager.addEventListener(googleAdEventType.STARTED, function() {\n debug.info('gdn event - started');\n updateMediaSessionMetadata();\n\n inline.hideBlind();\n inline.endSpinner();\n completion.hideCompletion();\n exports.queue.emit('hide:action');\n track(PAT.EVENT.START);\n });\n\n adsManager.addEventListener(googleAdEventType.SKIPPED, function() {\n debug.info('gdn event - skipped');\n\n track(PAT.EVENT.SKIP);\n });\n\n adsManager.addEventListener(googleAdEventType.AD_PROGRESS, function(e) {\n track(PAT.EVENT.PROGRESS + '-' + Math.round(e.getAdData().currentTime));\n });\n\n adsManager.addEventListener(googleAdEventType.CLICK, function() {\n debug.info('gdn event - click');\n\n track(PAT.EVENT.CLICK);\n });\n\n adsManager.addEventListener(googleAdEventType.COMPLETE, function() {\n debug.info('gdn event - complete');\n\n track(PAT.EVENT.COMPLETE);\n });\n\n adsManager.addEventListener(googleAdEventType.FIRST_QUARTILE, function() {\n debug.info('gdn event - first quartile');\n\n track(PAT.EVENT.FIRST_QUARTILE);\n });\n\n adsManager.addEventListener(googleAdEventType.MIDPOINT, function() {\n debug.info('gdn event - midpoint');\n\n track(PAT.EVENT.MID_POINT);\n });\n\n adsManager.addEventListener(googleAdEventType.THIRD_QUARTILE, function() {\n debug.info('gdn event - third quartile');\n\n track(PAT.EVENT.THIRD_QUARTILE);\n });\n\n adsManager.addEventListener(googleAdEventType.CONTENT_PAUSE_REQUESTED, onContentPauseRequested);\n\n adsManager.addEventListener(googleAdEventType.CONTENT_RESUME_REQUESTED, onContentResumeRequested);\n\n adsManager.addEventListener(googleAdEventType.LOADED, function() {\n videoAdUI.show();\n });\n\n adsManager.addEventListener(googleAdEventType.PAUSED, function() {\n mediaSession.setPlaybackState(true);\n track(PAT.EVENT.PAUSE);\n });\n\n adsManager.addEventListener(googleAdEventType.RESUMED, function() {\n inline.endSpinner();\n mediaSession.setPlaybackState(false);\n track(PAT.EVENT.RESUME);\n });\n\n adsManager.addEventListener(googleAdEventType.ALL_ADS_COMPLETED, function() {\n debug.info('gdn event - all ads complete');\n\n adsManager.destroy();\n\n if (typeof videoEndedCallback === 'function') {\n videoEndedCallback();\n }\n });\n\n startAds();\n videoAdUI.show();\n }\n\n function initialImaAds() {\n debug.info('initialImaAds');\n\n googleIma.settings.setLocale('ko');\n\n if (ua.os.ios && ua.os.version.major >= 10 && ua.platform === 'mobile') {\n googleIma.settings.setDisableCustomPlaybackForIOS10Plus(true);\n }\n\n adDisplayContainer = new googleIma.AdDisplayContainer(EL.AD_CONTAINER, videoContent);\n adsLoader = new googleIma.AdsLoader(adDisplayContainer);\n\n adsLoader.addEventListener(\n googleIma.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n onAdsManagerLoaded,\n false\n );\n\n adsLoader.addEventListener(googleIma.AdErrorEvent.Type.AD_ERROR, onAdError, false);\n }\n\n function initialUserAction() {\n adDisplayContainer.initialize();\n videoContent.load();\n }\n\n var listener = {\n customEvent: function(sandbox) {\n sandbox.on('play:ima', function() {\n if (adsManager) {\n adsManager.resume();\n }\n });\n\n sandbox.on('pause:ima', function() {\n if (adsManager) {\n adsManager.pause();\n }\n });\n }\n };\n\n function ImaAds() {}\n\n ImaAds.prototype.init = function(player, sandbox) {\n videoContent = player.videoElement;\n listener.customEvent(sandbox);\n };\n\n ImaAds.prototype.setup = function(callback) {\n videoEndedCallback = callback;\n\n if (googleIma && !adsDone) {\n initialImaAds();\n initialUserAction();\n adsDone = true;\n }\n };\n\n ImaAds.prototype.setTracker = function(trackingList) {\n var eventName, url;\n\n trackingList.forEach(function(item) {\n eventName = item.event;\n url = item.value;\n\n if (eventName === 'progress') {\n var offset = helpers.string.stringToSec(item.offset);\n eventName = eventName + '-' + offset;\n }\n\n PAT.URL_LIST[eventName] = {};\n PAT.URL_LIST[eventName].url = url;\n });\n };\n\n ImaAds.prototype.destroy = function() {\n if (googleIma && adsManager) {\n adsManager.destroy();\n this.hide();\n }\n };\n\n ImaAds.prototype.requestAds = function() {\n if (googleIma) {\n this.destroy();\n\n var adsRequest = new googleIma.AdsRequest();\n adsRequest.adTagUrl = TAG_URL.LINEAR_PC_VOD;\n adsLoader.requestAds(adsRequest);\n }\n };\n\n ImaAds.prototype.hide = function() {\n if (googleIma) {\n videoAdUI.hide();\n }\n };\n\n return ImaAds;\n })();\n\n exports.addModule('controller.ima', new ImaAds());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var AdController;\n\n AdController = (function() {\n var adParser = exports.loadModule('ads.parser');\n var inline = exports.loadModule('view.inline');\n var adBean = exports.loadModule('model.ad');\n var state = exports.loadModule('controller.state');\n var queue = exports.loadModule('playlist.queue');\n var cover = exports.loadModule('view.cover');\n var imaAds = exports.loadModule('controller.ima');\n var player = exports.loadModule('player.adapter');\n var shaka = exports.loadModule('player.shaka');\n var dataloader = exports.loadModule('playlist.dataloader');\n\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var ua = exports.ua;\n var constants = exports.constants;\n\n function activateAdControl() {\n state.seekEnabled = false;\n state.adControlActivated = true;\n\n inline.showAd();\n\n if (ua.platform === 'pc') {\n inline.hideControlHead();\n }\n }\n\n function inactivateAdControl() {\n state.seekEnabled = true;\n state.adControlActivated = false;\n inline.hideAd();\n }\n\n function getNonLinearAd() {\n var overlayAds = queue.overlayAds;\n var overlayAd;\n\n for (var i = 0; i < overlayAds.length; i++) {\n overlayAd = overlayAds[i].customObject.MidTextAd || overlayAds[i].customObject.RemindBanner;\n if (overlayAd) {\n break;\n }\n }\n return overlayAd;\n }\n\n function showNonLinearAd() {\n inline.showNonLinearAd();\n }\n\n function hideNonLinearAd() {\n inline.hideNonLinearAd();\n }\n\n function setupNonLinearAd() {\n var nonLinearAd = getNonLinearAd();\n if (nonLinearAd) {\n inline.setupNonLinearAd(nonLinearAd);\n }\n }\n\n function setupMidrollAd() {\n var midrollReq = state.currentVideo.midrollReq;\n inline.removeMidrollPoint();\n\n if (midrollReq) {\n midrollReq.forEach(function(v, i) {\n inline.setupMidrollAd(i, v.isStarted, helpers.string.stringToSec(v['@_timeOffset']));\n });\n }\n }\n\n function pauseNonLinearAd() {\n if (state.isNonLinearAdShown) {\n inline.pauseNonLinearAd();\n }\n }\n\n function resumeNonLinearAd() {\n if (state.isNonLinearAdShown) {\n inline.resumeNonLinearAd();\n }\n }\n\n function checkNonLinearAd(currentTime, duration) {\n var nonLinearAd = getNonLinearAd();\n var displayPer = nonLinearAd.DisplayPer > 0 ? nonLinearAd.DisplayPer : 1;\n var displaySec = parseInt((duration * displayPer) / 100);\n var adType;\n\n debug.info('Check NonLinear Ad - time(sec): ' + displaySec + '/' + currentTime + '(display/current)');\n\n if (!nonLinearAd || state.isNonLinearAdShown || state.modalContentActivated) {\n return;\n }\n\n if (currentTime === displaySec) {\n if (nonLinearAd.Title) {\n adType = 'text';\n } else if (nonLinearAd.BannerUrl) {\n adType = 'image';\n }\n\n if (adType) {\n state.isNonLinearAdShown = true;\n inline.showNonLinearAd(true, adType);\n }\n }\n }\n\n function checkMidrollAd(isSeeking, callback) {\n var midrollReq = state.currentVideo.midrollReq;\n var currentTime = player.getCurrentTimeRound();\n var offsetArray = [];\n\n midrollReq.forEach(function(v) {\n offsetArray.push(helpers.string.stringToSec(v['@_timeOffset']));\n });\n\n for (var i = 0; i < offsetArray.length; i++) {\n if ((!isSeeking && offsetArray[i] === currentTime) || (isSeeking && offsetArray[i] < currentTime)) {\n if (\n (offsetArray[i + 1] && currentTime < offsetArray[i + 1]) ||\n typeof offsetArray[i + 1] === 'undefined'\n ) {\n state.midrollIndex = i;\n if (!midrollReq[i].isStarted) {\n fetchMidroll().then(function() {\n callback();\n });\n }\n break;\n }\n }\n }\n }\n\n function fetchAds(clip) {\n return dataloader.fetchVmap(clip.vmapReq);\n }\n\n function fetchVastAd(adReq) {\n return new Promise(function(resolve, reject) {\n debug.info('%c%s', 'color: #20b408', '[adController] fetch vast', adReq);\n var isRejectedAutoplay = !queue.contents.length && !state.isPrerollEnded;\n\n if (isRejectedAutoplay || !helpers.device.isSupportAd(ua) || !adReq) {\n resolve();\n return;\n }\n\n state.isVastRequesting = true;\n dataloader\n .fetchVast(adReq)\n .then(resolve)\n .catch(reject);\n });\n }\n\n function fetchPreroll() {\n var clip = state.currentVideo;\n\n return new Promise(function(resolve, reject) {\n if (queue.prerolls.length > 0 || state.isPrerollEnded) {\n resolve();\n return;\n }\n\n fetchVastAd(clip.prerollReq)\n .then(function() {\n clip.prerollReq = null;\n queue.enqueueArray(queue.prerolls);\n resolve();\n })\n .catch(function() {\n reject();\n });\n });\n }\n\n function fetchMidroll() {\n return new Promise(function(resolve) {\n debug.info(\n '%c%s',\n 'color: #2074c0;',\n 'Midroll fetchMidroll - state.midrollIndex ',\n state.midrollIndex,\n ', midroll playingTime',\n dt.StopWatch.has('midrollPlayingTime')\n );\n\n fetchVastAd(state.currentVideo.midrollReq[state.midrollIndex]).then(function() {\n if (queue.midrolls.length > 0) {\n queue.enqueueArray(queue.midrolls.shift());\n player.setTime(player.getCurrentTime());\n dt.StopWatch.stop('midrollPlayingTime');\n exports.queue.emit('close:menubox');\n exports.queue.emit('close:settingbox');\n exports.queue.emit('hide:modal');\n if (state.abr) {\n shaka.detach().then(resolve);\n } else {\n resolve();\n }\n }\n });\n });\n }\n\n function fetchPostroll() {\n var clip = state.currentVideo;\n return fetchVastAd(clip.postrollReq).then(function() {\n queue.enqueueArray(queue.postrolls);\n });\n }\n\n function fetchSdkData(sdkDataUrl) {\n return new Promise(function(resolve, reject) {\n helpers.http\n .fetch(sdkDataUrl, {\n async: false,\n type: constants.HTTP.TYPE.JSON,\n credentials: 'include',\n method: constants.HTTP.METHOD.GET\n })\n .then(resolve)\n .catch(reject);\n });\n }\n\n function updateMidrollState() {\n state.currentVideo.midrollReq[state.midrollIndex].isStarted = true;\n inline.setupMidrollAd(state.midrollIndex, true);\n }\n\n function getSdkAdData(sdkAdUrls) {\n return new Promise(function(resolve, reject) {\n if (sdkAdUrls) {\n fetchSdkData(sdkAdUrls)\n .then(function(data) {\n if (data.dsp === 'gdn' && helpers.device.isIMASupportedBrowser(ua)) {\n imaAds.setTracker(data.tracking_list);\n loadGdnAd(resolve);\n } else {\n resolve();\n }\n })\n .catch(function(e) {\n debug.warn('Failed fetchSdkData e = ', e);\n reject();\n });\n } else {\n resolve();\n }\n });\n }\n\n function loadGdnAd(callback) {\n imaAds.setup(callback);\n cover.hideCover();\n inline.startSpinner();\n imaAds.requestAds();\n }\n\n function getSdkAds(extension) {\n var sdkAds = [];\n\n extension.forEach(function(v) {\n if (v['@_type'] === 'sdk' && v.SdkAdData) {\n sdkAds.push(v.SdkAdData);\n }\n });\n\n return sdkAds;\n }\n\n var adRequestSetter = {\n preroll: function(adBreak, clipBean) {\n clipBean.prerollReq = adBreak;\n if (adBreak.extensions && adBreak.extensions.extension && adBreak.extensions.extension.length > 0) {\n queue.sdkAds = getSdkAds(adBreak.extensions.extension);\n }\n },\n midroll: function(adBreak, clipBean) {\n adBreak.isStarted = false;\n adBreak.index = clipBean.midrollReq.length;\n clipBean.midrollReq.push(adBreak);\n },\n postroll: function(adBreak, clipBean) {\n clipBean.postrollReq = adBreak;\n }\n };\n\n function resolveVmap(response) {\n var clipBean = state.currentVideo;\n var vmap = adParser.parseVmap(response);\n var adBreaks = vmap.adBreak;\n\n if (!adBreaks) {\n debug.info('adBreaks is empty');\n return;\n }\n\n for (var i = 0; i < adBreaks.length; i++) {\n var adBreak = adBreaks[i];\n var breakId = adBreak['@_breakId'];\n\n if (adRequestSetter.hasOwnProperty(breakId)) {\n adRequestSetter[breakId](adBreak, clipBean);\n }\n }\n }\n\n var adQueueSetter = {\n preroll: function(adClipBean) {\n if (adClipBean.creative.linear) {\n queue.prerolls.push(adClipBean);\n }\n\n if (adClipBean.extension) {\n for (var i = 0; i < adClipBean.extension.length; i++) {\n queue.overlayAds.push(adClipBean.extension[i]);\n }\n }\n },\n midroll: function(adClipBean) {\n queue.midrolls.push(adClipBean);\n },\n postroll: function(adClipBean) {\n queue.postrolls.push(adClipBean);\n }\n };\n\n function insertAdQueue(adClipBean) {\n var breakId = adClipBean.breakId;\n\n if (adQueueSetter.hasOwnProperty(breakId)) {\n adQueueSetter[breakId](adClipBean);\n }\n }\n\n function validateAvailableAd(creatives, errorUrls) {\n var adAvailableList = ['linear', 'creativeExtensions'];\n var creativeKeys = Object.keys(creatives);\n\n if (!errorUrls || !creativeKeys) {\n return;\n }\n\n for (var i = 0; i < creativeKeys.length; i++) {\n if (adAvailableList.indexOf(creativeKeys[i]) < 0) {\n var errorUrl = JSON.parse(JSON.stringify(errorUrls));\n for (var k = 0; k < errorUrl.length; k++) {\n var sendUrl = errorUrl[k]['@_uri'].replace('[ERRORCODE]', '200');\n helpers.http.sendBeacon(sendUrl);\n }\n }\n }\n }\n\n function setAdClipBean(data) {\n var creative = data.creative;\n var linear = creative.linear;\n var skipOffset;\n var adIndexLabel;\n var clickThrough;\n var clickTrackings;\n var videoUrl;\n var icon;\n var creativeExtension = creative.creativeExtensions ? creative.creativeExtensions.creativeExtension : null;\n\n if (linear) {\n if (linear.mediaFiles.mediaFile) {\n videoUrl = linear.mediaFiles.mediaFile[0]['@_uri'];\n }\n if (linear.videoClicks) {\n clickThrough = linear.videoClicks.clickThrough;\n clickTrackings = linear.videoClicks.clickTracking;\n }\n\n if (linear.icons) {\n icon = linear.icons.icon;\n }\n\n if (linear['@_skipoffset']) {\n skipOffset = helpers.string.stringToSec(linear['@_skipoffset']);\n adIndexLabel = 'ad_' + skipOffset;\n }\n }\n\n adBean.set({\n id: data.adId,\n videoUrl: videoUrl,\n breakId: data.breakId,\n breakType: data.breakType,\n timeOffset: data.timeOffset,\n skipOffset: skipOffset,\n ad: data.ad,\n creative: data.creative,\n extension: creativeExtension,\n clickThrough: clickThrough,\n clickTracking: clickTrackings,\n dsp: data.advertiser,\n adIndexLabel: adIndexLabel,\n icon: icon\n });\n\n insertAdQueue(adBean);\n debug.info('%c%s', 'color: #20b408', '[adController] set adClipBean');\n debug.table(adBean);\n }\n\n function resolveVast(request, response) {\n var vast = adParser.parseVast(response);\n var ads = vast.ad;\n\n if (!ads) {\n debug.info('ad is empty');\n return;\n }\n\n for (var i = 0; i < ads.length; i++) {\n var ad = ads[i];\n var inline = ad.inline;\n var creatives = inline.creatives.creative;\n\n if (creatives) {\n creatives.forEach(function(creative) {\n validateAvailableAd(creative, inline.error);\n setAdClipBean({\n ad: ad,\n adIndex: i,\n adId: ad['@_id'],\n advertiser: inline.advertiser,\n breakId: request['@_breakId'],\n breakType: request['@_breakType'],\n timeOffset: request['@_timeOffset'],\n creative: creative\n });\n });\n }\n }\n }\n\n var listener = {\n customEvent: function(sandbox) {\n sandbox.on('show:modal', function() {\n inline.hideNonLinearAdContainer();\n });\n\n sandbox.on('hide:modal', function() {\n inline.showNonLinearAdContainer();\n });\n\n sandbox.on('show:completion', function() {\n inline.hideNonLinearAdContainer();\n });\n\n sandbox.on('hide:completion', function() {\n inline.showNonLinearAdContainer();\n });\n\n sandbox.on('show:nonelinear', function() {\n inline.showNonLinearAdContainer();\n });\n\n sandbox.on('hide:nonelinear', function() {\n inline.hideNonLinearAdContainer();\n });\n }\n };\n\n function AdController() {}\n\n AdController.prototype.init = function(player, sandbox) {\n listener.customEvent(sandbox);\n };\n\n AdController.prototype.setupAdControl = function() {\n inline.setupAdControl();\n inline.setupAd();\n };\n\n AdController.prototype.activateAdControl = function() {\n activateAdControl();\n };\n\n AdController.prototype.inactivateAdControl = function() {\n inactivateAdControl();\n };\n\n AdController.prototype.showLinearAdContainer = function() {\n inline.showLinearAdContainer();\n };\n\n AdController.prototype.hideLinearAdContainer = function() {\n inline.hideLinearAdContainer();\n };\n\n AdController.prototype.showNonLinearAd = function() {\n showNonLinearAd();\n };\n\n AdController.prototype.hideNonLinearAd = function() {\n hideNonLinearAd();\n };\n\n AdController.prototype.checkNonLinearAd = function(currentTime, duration) {\n checkNonLinearAd(currentTime, duration);\n };\n\n AdController.prototype.checkMidrollAd = function(isSeeking, callback) {\n checkMidrollAd(isSeeking, callback);\n };\n\n AdController.prototype.updateMidrollState = function() {\n updateMidrollState();\n };\n\n AdController.prototype.setupNonLinearAd = function() {\n setupNonLinearAd();\n };\n\n AdController.prototype.setupMidrollAd = function() {\n setupMidrollAd();\n };\n\n AdController.prototype.pauseNonLinearAd = function() {\n pauseNonLinearAd();\n };\n\n AdController.prototype.resumeNonLinearAd = function() {\n resumeNonLinearAd();\n };\n\n AdController.prototype.resolveVmap = function(request) {\n resolveVmap(request);\n };\n\n AdController.prototype.resolveVast = function(request, response) {\n resolveVast(request, response);\n };\n\n AdController.prototype.fetchAds = function(bean) {\n return fetchAds(bean);\n };\n\n AdController.prototype.fetchPostroll = function() {\n return fetchPostroll();\n };\n\n AdController.prototype.fetchPreroll = function() {\n return fetchPreroll();\n };\n\n AdController.prototype.getSdkAdData = function(sdkAdUrls) {\n return getSdkAdData(sdkAdUrls);\n };\n\n return AdController;\n })();\n\n exports.addModule('controller.ad', new AdController());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports) {\n 'use strict';\n var dataloader = exports.loadModule('playlist.dataloader');\n var actionView = exports.loadModule('view.action');\n\n var ActionController;\n\n ActionController = (function() {\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n function load(url) {\n fetchAction(url)\n .then(function(action) {\n completeAction(action);\n exports.queue.emit('show:action');\n })\n .catch(function(e) {\n debug.error('fetchAction error = ', e);\n });\n }\n\n function fetchAction(url) {\n return dataloader.getAction(url);\n }\n\n function completeAction(action) {\n if (action.actionButton && action.actionButton !== null) {\n actionView.setButton(action);\n }\n }\n\n function ActionController() {}\n\n ActionController.prototype.init = function() {};\n\n ActionController.prototype.load = function(url) {\n load(url);\n };\n\n return ActionController;\n })();\n\n exports.addModule('controller.action', new ActionController());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports, dt) {\n 'use strict';\n\n var cover = exports.loadModule('view.cover');\n var error = exports.loadModule('view.error');\n var queue = exports.loadModule('playlist.queue');\n var tracker = exports.loadModule('etc.tracker');\n var websocket = exports.loadModule('etc.websocket');\n var state = exports.loadModule('controller.state');\n var shaka = exports.loadModule('player.shaka');\n var player = exports.loadModule('player.adapter');\n var dataloader = exports.loadModule('playlist.dataloader');\n var imaAds = exports.loadModule('controller.ima');\n var inline = exports.loadModule('view.inline');\n var inlinePC = exports.loadModule('view.inline.pc');\n var extension = exports.loadModule('view.extension');\n var completion = exports.loadModule('view.completion');\n var confirmView = exports.loadModule('view.confirm');\n var pvtTracker = exports.loadModule('pvt.tracker');\n var adController = exports.loadModule('controller.ad');\n var actionController = exports.loadModule('controller.action');\n\n var Controller;\n\n Controller = (function() {\n var $ = dt.$;\n var $$ = dt.$$;\n var ua = exports.ua;\n var env = exports.ENV;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n\n var PHASE = constants.PHASE[env.phase.toUpperCase()];\n var APP_KEY = constants.APP_KEY[PHASE];\n var ERROR_STATUS = constants.ERROR.STATUS;\n var CONFIRM_STATUS = constants.CONFIRM.STATUS;\n var AGE_LIMIT = constants.AGE_LIMIT;\n\n function isSupportedCodecWindows() {\n var isSupportH264 = helpers.feature.supportsH264();\n return !(ua.platform === 'pc' && ua.os.windows && !isSupportH264);\n }\n\n function showError(info, option) {\n var code = info.code;\n inline.endSpinner();\n error.showError(code, info, option);\n }\n\n function showConfirm(option) {\n var MESSAGE_COOKIE_NAME = constants.STORAGE.ALERT_MSG;\n var isVisibleMsg = true;\n\n var defaults = {\n status: {},\n accept: function() {},\n cancel: function() {}\n };\n\n dt.extend(defaults, option, true);\n\n if (defaults.status.NAME === CONFIRM_STATUS.CARRIER.NAME) {\n isVisibleMsg = helpers.store.get(MESSAGE_COOKIE_NAME) !== '1';\n }\n\n if (isVisibleMsg) {\n confirmView.show(\n defaults.status.NAME,\n {},\n {\n acceptCallback: function() {\n helpers.store.set(MESSAGE_COOKIE_NAME, '1', 3);\n return defaults.accept();\n },\n cancelCallback: function() {\n return defaults.cancel();\n }\n }\n );\n } else {\n return defaults.accept();\n }\n }\n\n function alert3G4G(status, callback) {\n var isWifi = helpers.webapi.network.isWifi();\n var isShowConfirm =\n ua.platform !== 'pc' && !helpers.device.isFacebookWebview() && !isWifi && env.showConfirm;\n\n if (isShowConfirm) {\n return showConfirm({\n status: status,\n accept: function() {\n callback();\n },\n cancel: function() {\n cover.showCover();\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onPlayCancel);\n }\n });\n } else {\n error.hideError();\n callback();\n }\n }\n\n function checkLoadedVideo(callback) {\n var interval = setInterval(function() {\n if (player.videoElement.readyState > 0 || state.playerClass === constants.PLAYERCLASS.KAMP) {\n if (typeof callback === 'function') {\n callback();\n }\n clearInterval(interval);\n }\n }, 50);\n }\n\n function shakaLoadCallback() {\n shaka.getOutputs(function(outputList) {\n state.currentVideo.outputList = outputList;\n\n if (ua.platform === 'pc') {\n inlinePC.onLoadStart();\n } else {\n extension.createProfileList(state.currentVideo.outputList);\n extension.setProfile(state.currentVideo.profile);\n inline.setProfile(state.currentVideo.profile);\n inline.onLoadStart();\n }\n });\n }\n\n function loadFlashPlayer() {\n location.href = location.href + '&flash=1';\n }\n\n function loadVideoResource(clip, callback) {\n debug.info(\n '%c%s',\n 'color: #FF5722; font-weight: bold;',\n '------- load video resource -------',\n clip.videoUrl\n );\n\n var videoUrl = clip.videoUrl;\n var overlayAds = queue.overlayAds;\n\n state.ended = state.allAdsCompleted;\n state.isCheckNextVideo = false;\n\n var loadDatas = {\n videoUrl: videoUrl,\n playerClass: null,\n callback: null\n };\n\n loadDatas.playerClass = state.playerClass = constants.PLAYERCLASS.HTML5;\n\n if (state.currentVideo.type === 'LIVE' && ua.platform === 'pc') {\n if (player.isSupportedLiveAgentHLS()) {\n if (clip.type !== 'AD') {\n loadDatas.playerClass = state.playerClass = constants.PLAYERCLASS.KAMP;\n }\n } else {\n loadFlashPlayer();\n return;\n }\n } else if (state.abr && clip.type !== 'AD') {\n loadDatas.playerClass = state.playerClass = constants.PLAYERCLASS.SHAKA;\n loadDatas.callback = shakaLoadCallback;\n } else if (helpers.tv.isConnected()) {\n loadDatas.playerClass = state.playerClass = constants.PLAYERCLASS.CAST;\n loadDatas.remote = {\n videoInfo: {\n url: videoUrl,\n mediaType: constants.MEDIA_TYPE.MP4\n }\n };\n }\n\n tracker.setTracker(clip);\n if (overlayAds) {\n tracker.setNonLinearTracker(overlayAds);\n }\n\n player.load(loadDatas);\n\n checkLoadedVideo(function() {\n if (typeof callback === 'function') {\n callback();\n }\n });\n }\n\n function loadReadyAndPlay(id, profile, feedbackData, isReplay) {\n return fetchReadyAndPlay(id, profile, feedbackData).then(function(readyAndPlay) {\n setReadyAndPlay(id, readyAndPlay, isReplay);\n });\n }\n\n function loadMeta() {\n fetchMeta().then(function() {\n onCompleteMeta();\n var clipBean = state.currentVideo;\n\n if (ua.platform !== 'pc') {\n if (state.abr) {\n shaka.getOutputs(function(outputList) {\n clipBean.outputList = outputList;\n setProfile(clipBean.outputList, clipBean.profile);\n });\n } else {\n if (state.hls) {\n clipBean.outputList.splice(0, 0, { profile: constants.PROFILE.AUTO, label: '자동' });\n }\n setProfile(clipBean.outputList, clipBean.profile);\n }\n }\n });\n }\n\n function fetchMeta() {\n var video = state.currentVideo;\n var metaUrl = video.metaUrl;\n var options = {\n type: video.type,\n service: env.service\n };\n\n if (env.ptoken) {\n options.ptoken = env.ptoken;\n }\n\n return new Promise(function(resolve, reject) {\n dataloader\n .getMeta(metaUrl, options)\n .then(function(meta) {\n appendBean(meta);\n resolve(meta);\n })\n .catch(function(e) {\n debug.log('Meta server error', e);\n reject(e);\n });\n });\n }\n\n function appendBean(meta) {\n var video = state.currentVideo;\n if (video.type === constants.VIDEO_TYPE.VOD) {\n appendClipBean(meta);\n } else if (video.type === constants.VIDEO_TYPE.LIVE) {\n appendLiveBean(meta);\n }\n }\n\n function stopVideo() {\n var isAutoPlay = false;\n var startTime = 0;\n\n try {\n imaAds.destroy();\n adController.inactivateAdControl();\n } catch (e) {\n debug.error(e);\n }\n exports.queue.emit('load:videoById', startTime, isAutoPlay);\n }\n\n function checkAgeLimit() {\n var video = queue.front;\n var isAd = video && video.type === constants.VIDEO_TYPE.AD;\n var timing = player.videoElement.getAttribute('data-current-time');\n\n if (isAgeLimit() && !isAd && !timing) {\n player.pause();\n inline.hideRating();\n error.showAgeLimit();\n }\n }\n\n function playVideo() {\n var playPromise = player.play();\n state.autoplayFail = false;\n\n if (playPromise !== undefined) {\n playPromise\n .then(function() {\n cover.hideCover();\n checkAgeLimit();\n })\n .catch(function(error) {\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onFailAutoPlay);\n debug.tooltip(\n '현재 브라우저의 환경에서는 자동재생 기능을 지원하지 않습니다. Play버튼을 클릭하면 재생할 수 있습니다.' +\n error\n );\n state.autoplayFail = true;\n stopVideo();\n });\n } else {\n inline.endSpinner();\n checkAgeLimit();\n }\n }\n\n function isAgeLimit() {\n var video = queue.front;\n var ageLimit = state.currentVideo.ageLimit;\n var isAgeLimit = ageLimit === AGE_LIMIT.AGE_18.name || ageLimit === AGE_LIMIT.AGE_19.name;\n\n return video.type === constants.VIDEO_TYPE.VOD && isAgeLimit;\n }\n\n function startVideo(clip) {\n debug.info('%c%s', 'color: #20b408', '[controller] startVideo', clip.type, clip.timeOffset);\n\n if (clip && clip.breakId === 'midroll') {\n pvtTracker.pause();\n }\n\n inline.startSpinner();\n imaAds.destroy();\n\n if (!clip || !clip.videoUrl) {\n return;\n }\n\n if (clip.type !== constants.VIDEO_TYPE.AD) {\n if (!error.checkValidation(clip)) {\n return;\n }\n }\n\n loadVideoResource(clip, function() {\n playVideo();\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onPlayStart, [\n state.currentVideo.vid,\n clip && clip.type,\n state.currentVideo.id,\n state.currentVideo.tid\n ]);\n });\n }\n\n function startNextQueue(callback) {\n var bean;\n\n if (queue.contents.length > 0) {\n bean = queue.contents.shift();\n queue.enqueue(bean);\n } else if (queue.front && queue.front.breakId === 'midroll') {\n if (callback && typeof callback === 'function') {\n callback();\n }\n } else {\n if (state.isPrerollEnded && !state.isPostrollEnded && queue.playList.length === 0) {\n state.isPostrollEnded = true;\n state.allAdsCompleted = true;\n\n if (callback && typeof callback === 'function') {\n callback();\n return;\n }\n }\n }\n\n if (queue.prerolls.length === 0 && !state.isPrerollEnded) {\n adController\n .getSdkAdData(queue.sdkAds.shift())\n .catch(function() {\n debug.info('Failed getSdkAdData Or no ad data');\n })\n .finally(function() {\n state.isPrerollEnded = true;\n state.onIma = false;\n startNextQueue();\n });\n return;\n }\n\n if (queue.playList.length > 0) {\n startVideo(queue.dequeue());\n\n if (queue.front && queue.front.type !== constants.VIDEO_TYPE.AD) {\n dt.StopWatch.start('startPlay');\n }\n }\n\n debug.info('startNextQueue - state.allAdsCompleted:', state.allAdsCompleted, ', state.ended:', state.ended);\n }\n\n function loadVideo(clip) {\n debug.info('%c%s', 'color: #20b408', '[controller] load video', clip);\n\n var callbackParameters = helpers.sdk.getDefaultCallbackParams(state.currentVideo);\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onStartLoadVideo, callbackParameters);\n\n adController\n .fetchPreroll()\n .then(startNextQueue)\n .catch(function() {\n if (clip.skipOnErrorOfAdApi) {\n readyVideo();\n }\n });\n }\n\n function preStartVideo(profile) {\n if (!state.currentVideo) {\n return;\n }\n\n alert3G4G(CONFIRM_STATUS.CARRIER, function() {\n cover.hideCover();\n inline.startSpinner();\n\n if (ua.platform === 'pc') {\n loadVideo(state.currentVideo);\n } else {\n if (profile && state.currentVideo.profile === profile) {\n loadVideo(state.currentVideo);\n } else if (state.abr) {\n state.currentVideo.profile = profile;\n loadVideo(state.currentVideo);\n state.needSetTrack = true;\n } else {\n if (player.type === 'VOD') {\n inline.getClipLocation(profile, function() {\n loadVideo(state.currentVideo);\n });\n } else {\n inline.getLiveLocation(profile, function() {\n loadVideo(state.currentVideo);\n });\n }\n }\n\n extension.setProfile(profile);\n inline.setProfile(profile);\n }\n });\n }\n\n function setStartTime(start) {\n var instanceStart = state.initialState.start;\n var startTime = start || (instanceStart !== '' ? instanceStart : '0');\n startTime = startTime.replace(',', '');\n\n if (!isNaN(startTime)) {\n startTime = parseFloat(startTime);\n\n if (startTime > 0) {\n player.setTime(startTime);\n }\n }\n }\n\n function cancelFullScreen() {\n inline.cancelFullscreen();\n }\n\n function setClipCover() {\n if (env.showCover) {\n var clipBean = state.currentVideo;\n var vodLink = '/channel/#{channelId}/cliplink/#{clipLinkId}';\n vodLink = helpers.string.format(vodLink, {\n channelId: clipBean.channelId,\n clipLinkId: clipBean.id\n });\n\n var size = ua.platform === 'pc' ? 'C640x360' : 'C480x270';\n var coverUrl = helpers.string.getThumbnailFarmUrl(clipBean.coverUrl, size);\n if (env.coverUrl !== '') {\n coverUrl = env.coverUrl;\n }\n cover.setThumbnail(coverUrl);\n cover.setTime(clipBean.duration);\n cover.setTitle(vodLink, clipBean.title);\n }\n }\n\n function onCompleteMeta() {\n debug.info('isSupportedCodecWindows', isSupportedCodecWindows());\n\n if (!isSupportedCodecWindows()) {\n error.showError(ERROR_STATUS.CodecNotInstalled.NAME, {});\n return;\n }\n\n setClipCover();\n }\n\n function fetchReadyAndPlay(id, profile, feedbackData) {\n var uuid = helpers.uuid.get();\n var options = {\n service: env.service,\n section: env.section,\n uuid: uuid,\n profile: profile || env.profile,\n dteType: helpers.device.getDteType(ua),\n continuousPlay: state.continuousPlay,\n autoPlay: env.feedType,\n contentType: '',\n startPosition: state.initialState.start || '0',\n playerVersion: env.playerVersion,\n appVersion: ua.browser.version.info,\n drmType: helpers.drm.getType(ua),\n ab: env.ab,\n literalList: env.literallist\n };\n\n if (env.adenc) {\n options.adenc = env.adenc;\n }\n\n if (env.section2) {\n options.section2 = env.section2;\n }\n\n if (env.ptoken) {\n options.ptoken = env.ptoken;\n }\n\n if (env.serviceReferrer) {\n options.pageReferer = env.serviceReferrer;\n }\n\n if (env.cpID) {\n options.cpID = env.cpID;\n }\n\n if (feedbackData && feedbackData.usage && feedbackData.usage.request_params) {\n var requestParams = feedbackData.usage.request_params;\n options.recRefId = requestParams.recRefId;\n options.recUserType = requestParams.recUserType;\n options.recFileKey = requestParams.recFileKey;\n options.recBucketId = requestParams.recBucketId; // todo recImpId 키값이 recBucketId로 변경된건가? 확인\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onStartImpression, [id]);\n\n return dataloader.getClipReadyAndPlay(id, options);\n }\n\n function setProfile(outputList, profile) {\n cover.createProfileList(outputList);\n extension.createProfileList(outputList);\n extension.setProfile(profile);\n inline.setProfile(profile);\n }\n\n function setReadyAndPlay(id, readyAndPlay, isReplay) {\n var uuid = readyAndPlay.uuid;\n helpers.uuid.set(uuid);\n setReadyAndPlayBean(id, readyAndPlay, isReplay);\n\n if (readyAndPlay && readyAndPlay.pct) {\n tracker.setPCTTracker(readyAndPlay.pct);\n }\n\n if (readyAndPlay && readyAndPlay.pit && readyAndPlay.pit.url) {\n helpers.http.sendBeacon(readyAndPlay.pit.url);\n }\n\n if (window.WebSocket && readyAndPlay.ws) {\n websocket.setConfig(readyAndPlay.ws);\n if (websocket.getConnectionTiming() === 'IMMEDIATELY') {\n websocket.open();\n }\n }\n\n inline.endSpinner();\n pvtTracker.clear();\n\n loadMeta();\n\n if (env.isPrivateIp && ua.platform === 'pc' && state.currentVideo.type === 'VOD' && !ua.browser.msie) {\n dataloader.getAnalyticsClipPlay(state.currentVideo.linkId);\n }\n }\n\n function setDrmShakaConfig(token, server) {\n var drmData = {\n token: token,\n server: server,\n type: helpers.drm.getType(ua)\n };\n shaka.setDrmData(drmData);\n state.drm = true;\n }\n\n function setDrmShakaCert(certUrl) {\n shaka.setDrmCertUrl(certUrl);\n }\n\n function setReadyAndPlayBean(id, readyAndPlay, isReplay) {\n var metaUrl = readyAndPlay.metaUrl;\n var clipBean = {};\n var videoLocation = readyAndPlay.videoLocation;\n\n if (!videoLocation || !videoLocation.url) {\n throw Error('Clip url not found');\n }\n\n if (\n readyAndPlay.abrVideoLocationList &&\n readyAndPlay.abrVideoLocationList.length > 0 &&\n !state.abrError &&\n env.dash\n ) {\n debug.tooltip('Dash Support : ', 'true');\n readyAndPlay.abrVideoLocationList.forEach(function(v) {\n if (!clipBean.videoUrl) {\n if (\n shaka.isBrowserSupported() &&\n v.type.toUpperCase() === constants.CONTENT_TYPE.DASH &&\n ua.os.name !== 'ios'\n ) {\n clipBean.videoUrl = v.url + '?' + (v.params ? v.params : '');\n clipBean.profile = constants.PROFILE.AUTO;\n\n clipBean.originVideoUrl = videoLocation && videoLocation.url;\n clipBean.originProfile = videoLocation && videoLocation.profile;\n\n if (v.token) {\n setDrmShakaConfig(v.token, readyAndPlay.licenseUrl);\n }\n shaka.setManifestUri(clipBean.videoUrl);\n state.abr = true;\n } else if (v.type.toUpperCase() === constants.CONTENT_TYPE.HLS) {\n clipBean.videoUrl = v.url;\n clipBean.profile = v.profile;\n\n clipBean.originVideoUrl = videoLocation && videoLocation.url;\n clipBean.originProfile = videoLocation && videoLocation.profile;\n\n if (v.token) {\n if (readyAndPlay.certUrl) {\n setDrmShakaCert(readyAndPlay.certUrl);\n }\n\n setDrmShakaConfig(v.token, readyAndPlay.licenseUrl);\n\n shaka.setManifestUri(clipBean.videoUrl);\n state.abr = true;\n }\n state.hls = true;\n }\n }\n });\n\n if (!clipBean.videoUrl) {\n clipBean.videoUrl = videoLocation && videoLocation.url;\n clipBean.profile = videoLocation && videoLocation.profile;\n state.abr = false;\n }\n } else {\n debug.tooltip('Dash Support :', 'false');\n clipBean.videoUrl = videoLocation && videoLocation.url;\n clipBean.profile = videoLocation && videoLocation.profile;\n state.abr = false;\n }\n\n clipBean.tid = readyAndPlay.tid;\n clipBean.linkId = readyAndPlay.linkId;\n clipBean.metaUrl = metaUrl;\n clipBean.tracking = {\n pvt: readyAndPlay.pvt\n };\n clipBean.vmapReq = readyAndPlay.vmapReq;\n clipBean.skipOnErrorOfAdApi = readyAndPlay.skipOnErrorOfAdApi;\n clipBean.skipOnErrorOfAdContents = readyAndPlay.skipOnErrorOfAdContents;\n clipBean.seekUrl = readyAndPlay.seekUrl;\n clipBean.abrVideoLocationList = readyAndPlay.abrVideoLocationList;\n clipBean.contentType = videoLocation && videoLocation.contentType;\n clipBean.ageLimit = readyAndPlay.ageLimit; // todo 필요한 코드가 맞는지 확인\n clipBean.purchase = readyAndPlay.purchase;\n clipBean.feedBackData = readyAndPlay.feedBackData;\n clipBean.autoplayPreroll = readyAndPlay.autoplayPreroll;\n clipBean.isDrm = readyAndPlay.licenseUrl;\n\n if (readyAndPlay && readyAndPlay.qoe) {\n tracker.setQOETracker(readyAndPlay.qoe);\n }\n\n if (readyAndPlay.resumeOffset && !isReplay) {\n player.setTime(readyAndPlay.resumeOffset);\n }\n\n inline.endSpinner();\n\n try {\n clipBean.dsp = readyAndPlay.vmapReq.pre.imp_request.dsp_id;\n } catch (e) {}\n\n if (readyAndPlay.actionReq) {\n actionController.load(readyAndPlay.actionReq.url);\n }\n\n if (readyAndPlay.purchase) {\n inline.setTvod(readyAndPlay.purchase);\n } else {\n clipBean.resumeOffset = readyAndPlay.resumeOffset;\n }\n\n state.currentVideo.set(clipBean);\n }\n\n function checkAutoPlay(isAutoplay) {\n var autoplay = !!env.autoplay;\n var isDrmContent = state.currentVideo.isDrm;\n\n if (typeof isAutoplay === 'boolean') {\n autoplay = isAutoplay;\n }\n\n if (\n ua.os.android &&\n !helpers.device.isAllowContentAcessTalkWebView() &&\n helpers.device.isTalkWebView(ua) &&\n isDrmContent &&\n env.feedType\n ) {\n autoplay = false;\n }\n\n return autoplay;\n }\n\n function readyVideo(isAutoplay, profile) {\n var autoplay = checkAutoPlay(isAutoplay);\n var callbackParameters = helpers.sdk.getDefaultCallbackParams(state.currentVideo);\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onReadyVideo, callbackParameters);\n\n if (autoplay) {\n preStartVideo(profile);\n } else {\n inline.endSpinner();\n cover.showCover();\n }\n }\n\n function readyClipVideo(isAutoPlay, start, profile) {\n var clipBean = state.currentVideo;\n queue.contents.push(clipBean);\n setStartTime(start);\n readyVideo(isAutoPlay, profile);\n }\n\n function resetCustomUIForPC() {\n inline.showControlHead();\n inline.showControlFooter();\n inline.hideVideoCursor();\n inline.resizeControl();\n completion.hideWaiting();\n }\n\n function resetCustomUI() {\n error.hideError();\n cover.hideCover();\n extension.hideModal();\n completion.hideCompletion();\n inline.hideTvod();\n\n if (ua.platform === 'pc') {\n resetCustomUIForPC();\n }\n }\n\n function resetForLoad() {\n resetCustomUI();\n inline.startSpinner();\n inline.resetAriaAttr();\n resetPlayerInfo();\n adController.hideLinearAdContainer();\n adController.hideNonLinearAd();\n\n if (ua.platform === 'pc') {\n resetForLoadOnPc();\n }\n }\n\n function resetPlayerInfo() {\n state.init();\n queue.init();\n }\n\n function resetForLoadOnPc() {\n inlinePC.resetSpeed();\n }\n\n function initVolumeControl() {\n if (ua.platform === 'pc') {\n inlinePC.initVolumeControl();\n } else {\n inline.initVolumeControl();\n }\n }\n\n function appendClipBean(meta) {\n // 섬네일 이미지 리스트가 생성되지 않는 경우(sandbox환경)에서 테스트하는 용도\n var dummyThumbnailList = [\n {\n thumbnailUrl: 'http://t1.daumcdn.net/tvpot/thumb/s4da871AGx0iAmGCCmGimk1/0.png',\n timeInSec: 27,\n isDefault: true\n },\n {\n thumbnailUrl: 'http://t1.daumcdn.net/tvpot/thumb/s4da871AGx0iAmGCCmGimk1/1.png',\n timeInSec: 55,\n isDefault: false\n },\n {\n thumbnailUrl: 'http://t1.daumcdn.net/tvpot/thumb/s4da871AGx0iAmGCCmGimk1/2.png',\n timeInSec: 83,\n isDefault: false\n },\n {\n thumbnailUrl: 'http://t1.daumcdn.net/tvpot/thumb/s4da871AGx0iAmGCCmGimk1/3.png',\n timeInSec: 110,\n isDefault: false\n },\n {\n thumbnailUrl: 'http://t1.daumcdn.net/tvpot/thumb/s4da871AGx0iAmGCCmGimk1/4.png',\n timeInSec: 138,\n isDefault: false\n },\n {\n thumbnailUrl: 'http://t1.daumcdn.net/tvpot/thumb/s4da871AGx0iAmGCCmGimk1/5.png',\n timeInSec: 166,\n isDefault: false\n }\n ];\n\n var clipBean = {};\n var clip = meta.clipLink.clip;\n var channel = meta.clipLink.channel;\n var outputList = clip.videoOutputList || [];\n\n clipBean.channelId = meta.clipLink.channelId;\n clipBean.clipId = clip.id;\n clipBean.userId = clip.userId;\n clipBean.vid = clip.vid;\n clipBean.status = clip.status;\n clipBean.coverUrl = clip.thumbnailUrl;\n clipBean.thumbnailList =\n clip.clipChapterThumbnailList || (helpers.env.isSandbox() ? dummyThumbnailList : []);\n clipBean.duration = clip.duration;\n clipBean.title = clip.title;\n clipBean.canScrap = clip.canScrap;\n clipBean.shouldGeoBlock = clip.shouldGeoBlock;\n clipBean.isOpen = clip.isOpen;\n clipBean.isVertical = clip.isVertical;\n clipBean.wasLive = clip.wasLive;\n clipBean.hasPlusFriend = channel.hasPlusFriend || false;\n clipBean.plusFriendProfile = channel.plusFriendProfile || {};\n clipBean.isLegacy = channel.isLegacy;\n clipBean.isOriginal = clip.isOriginal;\n clipBean.isFullVod = clip.isFullVod;\n clipBean.description = clip.description;\n clipBean.login = meta.login;\n clipBean.owner = meta.owner;\n clipBean.playCount = clip.playCount;\n clipBean.channelName = channel.name;\n clipBean.profileImageUrl = (channel.channelSkinData || {}).profileImageUrl;\n clipBean.outputList = state.abr ? state.currentVideo.outputList : getOutputList(outputList);\n clipBean.originOutputList = getOutputList(outputList);\n clipBean.ageLimit = clip.ageLimit;\n clipBean.kakaoLink = meta.kakaoLink;\n clipBean.rating = meta.rating;\n\n state.currentVideo.set(clipBean);\n }\n\n function getOutputList(outputs) {\n var outputList = [];\n var profile;\n\n for (var i = 0; i < outputs.length; i++) {\n profile = outputs[i].profile.toString();\n\n if (profile !== 'AUDIO') {\n outputList.push(outputs[i]);\n }\n }\n\n return outputList;\n }\n\n function isBlockedPixelTag() {\n var pixelTag = $('adBlockPixelTag');\n var img = $$('img', pixelTag)[0];\n return (\n window.getComputedStyle(pixelTag).display === 'none' || window.getComputedStyle(img).display === 'none'\n );\n }\n\n function isBlockedBaitTag() {\n var ads = document.getElementsByClassName('banner_ad');\n var ad = ads[ads.length - 1];\n\n return !ad || ad.innerHTML.length === 0 || ad.clientHeight === 0;\n }\n\n function isActivatedAdBlock() {\n return isBlockedPixelTag() || isBlockedBaitTag();\n }\n\n function load(id, profile, start, isAutoPlay, feedbackData, preserveState, isReplay) {\n if (typeof isAutoPlay !== 'undefined' && !isAutoPlay && !(state.isPrerollEnded && state.isPostrollEnded)) {\n queue.dequeueCancel(queue.front);\n cover.showCover();\n inline.hideControl();\n return;\n }\n\n if (state.abrError) {\n setDefaultOptions();\n }\n\n var clipId = normalizeVideoId(id);\n\n player.stop();\n inline.hideActivatedControl();\n\n resetForLoad();\n initVolumeControl();\n state.initInitialState();\n state.initCurrentVideo(id, constants.VIDEO_TYPE.VOD);\n\n if (preserveState) {\n serPreserveState(preserveState);\n }\n\n loadReadyAndPlay(clipId, profile, feedbackData, isReplay)\n .then(function() {\n var clipBean = state.currentVideo;\n\n if (clipBean.vmapReq && clipBean.vmapReq.req_url && isActivatedAdBlock()) {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.UNAVAILABLE_ADBLOCK.NAME\n }\n });\n throw Error(ERROR_STATUS.UNAVAILABLE_ADBLOCK.NAME);\n }\n return adController.fetchAds(clipBean);\n })\n .then(function() {\n readyClipVideo(isAutoPlay, start, profile);\n })\n .catch(function(e) {\n var clipBean = state.currentVideo;\n\n if (clipBean.skipOnErrorOfAdApi) {\n readyClipVideo(isAutoPlay, start, profile);\n return;\n }\n\n debug.error('Failed clip loadReady: ', e);\n });\n }\n\n function unload() {\n var playingTime = dt.StopWatch.stop('playingTime');\n state.initInitialState();\n\n if (state.abr) {\n shaka.reset(player.videoElement);\n }\n pvtTracker.end(playingTime);\n trackUsage(playingTime);\n debug.info('unload function is called, playingTime', playingTime);\n }\n\n function trackUsage(playingTime) {\n var feedBackData = state.currentVideo.feedBackData;\n if (feedBackData && feedBackData.usage && feedBackData.usage.custom_props) {\n tracker.tiara.trackUsage({\n action: '',\n extra: {\n usage: {\n duration: playingTime\n },\n customProps: feedBackData.usage.custom_props\n }\n });\n }\n }\n\n function serPreserveState(preserveState) {\n for (var prop in preserveState) {\n if (preserveState.hasOwnProperty(prop)) {\n if (state[prop] !== undefined) {\n state[prop] = preserveState[prop];\n }\n }\n }\n }\n\n function seekToTime(time) {\n try {\n state.pausedBeforeSeek = state.ended ? false : player.isPaused();\n player.seekTo(time);\n } catch (err) {\n debug.error('video content might not be loaded');\n }\n }\n\n function normalizeVideoId(id) {\n if (isNaN(id)) {\n return id;\n } else {\n return parseInt(id, 10);\n }\n }\n\n function setupControl() {\n if (player.type === 'VOD') {\n inline.setupVideoControl();\n } else if (player.type === 'LIVE') {\n inline.setupLiveControl();\n }\n }\n\n function setMute(muteOn) {\n player.setMute(muteOn);\n }\n\n function setVolume(volume) {\n inlinePC.updateVolumePanel(volume);\n }\n\n function setAutoPlayMode(isAutoPlay) {\n var autoplay = isAutoPlay === 'true' || isAutoPlay === true;\n inlinePC.setAutoPlay(autoplay);\n }\n\n function setWideScreenMode(isWideScreen) {\n var wideScreen = isWideScreen === 'true' || isWideScreen === true;\n inlinePC.setWideScreen(wideScreen);\n }\n\n function changeVideoResource() {\n var clipBean = state.currentVideo;\n var timing = player.videoElement.getAttribute('data-current-time');\n var prevTime = player.getCurrentTimeRound();\n\n if (state.isFirstPlay) {\n if (timing) {\n prevTime = timing;\n } else if (env.start) {\n prevTime = env.start;\n } else {\n prevTime = 0;\n }\n }\n\n var loadDatas = {\n videoUrl: clipBean.videoUrl,\n playerClass: state.playerClass,\n callback: null\n };\n player.load(loadDatas);\n player.setTime(prevTime);\n }\n\n function appendLiveBean(meta) {\n var liveBean = {};\n var channel = meta.liveLink.channel;\n var live = meta.liveLink.live;\n\n if (!liveBean.id) {\n liveBean.id = meta.liveLink.id;\n }\n if (!liveBean.linkId) {\n liveBean.linkId = meta.liveLink.id;\n }\n liveBean.channelId = meta.liveLink.channelId;\n liveBean.liveId = live.id;\n liveBean.userId = live.userId;\n liveBean.coverUrl = live.thumbnailUri;\n liveBean.status = live.status;\n liveBean.duration = live.duration;\n liveBean.title = live.title;\n liveBean.liveType = live.liveType;\n liveBean.canScrap = live.canScrap;\n liveBean.hasPlusFriend = channel.hasPlusFriend;\n liveBean.shouldGeoBlock = live.shouldGeoBlock;\n liveBean.isOpen = live.isOpen;\n liveBean.needPassword = live.needPassword;\n liveBean.ccuCount = live.ccuCount;\n liveBean.playCount = live.playCount;\n liveBean.description = live.description;\n liveBean.isOriginal = live.isOriginal;\n liveBean.login = meta.login;\n liveBean.owner = meta.owner;\n liveBean.channelName = channel.name;\n liveBean.profileImageUrl = (channel.channelSkinData || {}).profileImageUrl;\n liveBean.coverThumbnailUrl = live.coverThumbnailUrl;\n liveBean.outputList = live.liveProfileList;\n liveBean.ageLimit = live.ageLimit;\n liveBean.needPassword = live.needPassword;\n liveBean.kakaoLink = meta.kakaoLink;\n liveBean.shouldShowHDLabel = meta.shouldShowHDLabel;\n\n state.currentVideo.set(liveBean);\n }\n\n function setPlaybackRate(rate) {\n player.setPlaybackRate(rate);\n }\n\n function initInitialEnvironment() {\n state.initInitialState();\n setDefaultOptions();\n }\n\n function setDefaultOptions() {\n var initialState = state.initialState;\n\n if (env.mute) {\n initialState.startMuted = true;\n }\n\n if (env.start) {\n initialState.start = env.start;\n }\n }\n\n function Controller() {}\n\n Controller.prototype.init = function() {\n if (inline) {\n inline.startSpinner();\n }\n\n initInitialEnvironment();\n window.registerApiMessenger(env.usePostMessage);\n\n if (typeof window.Kakao !== 'undefined' && window.Kakao.Auth === undefined) {\n (function(originPromise) {\n window.Kakao.init(APP_KEY);\n window.Promise = originPromise;\n })(window.Promise);\n }\n\n Promise.config({\n cancellation: true\n });\n\n if (!helpers.device.isSupportCustomController(ua)) {\n }\n };\n\n Controller.prototype.changeVideoResource = function() {\n changeVideoResource();\n };\n\n Controller.prototype.loadVideo = function(clip) {\n loadVideo(clip);\n };\n\n Controller.prototype.load = function(id, profile, start, isAutoPlay) {\n load(id, profile, start, isAutoPlay);\n };\n\n Controller.prototype.unload = function() {\n unload();\n };\n\n Controller.prototype.loadAndPlay = function(id, profile, start, feedbackData, preserveState, isReplay) {\n if (dt.StopWatch.has('playingTime')) {\n pvtTracker.end(dt.StopWatch.stop('playingTime'));\n }\n var isAutoPlay = true;\n load(id, profile, start, isAutoPlay, feedbackData, preserveState, isReplay);\n };\n\n Controller.prototype.normalizeVideoId = function(id) {\n normalizeVideoId(id);\n };\n\n Controller.prototype.startNextQueue = function(callback) {\n startNextQueue(callback);\n };\n\n Controller.prototype.preStartVideo = function(profile) {\n preStartVideo(profile);\n };\n\n Controller.prototype.play = function(profile) {\n if (player.videoElement.src !== '' && queue.front) {\n player.play();\n return;\n }\n\n if (!profile) {\n profile = state.currentVideo.profile;\n }\n\n if (\n ua.os.android &&\n !helpers.device.isAllowContentAcessTalkWebView() &&\n helpers.device.isTalkWebView(ua) &&\n state.currentVideo.isDrm &&\n env.feedType\n ) {\n return;\n }\n preStartVideo(profile);\n };\n\n Controller.prototype.pause = function() {\n player.pause();\n };\n\n Controller.prototype.stop = function() {\n stopVideo();\n player.stop();\n };\n\n Controller.prototype.seekTo = function(time) {\n seekToTime(time);\n };\n\n Controller.prototype.getDuration = function() {\n return player.getDurationRound();\n };\n\n Controller.prototype.setVolume = function(volume) {\n setVolume(volume);\n };\n\n Controller.prototype.setMute = function(muteOn) {\n setMute(muteOn);\n };\n\n Controller.prototype.setAutoPlayMode = function(isAutoPlay) {\n setAutoPlayMode(isAutoPlay);\n };\n\n Controller.prototype.setWideScreenMode = function(isWideScreen) {\n setWideScreenMode(isWideScreen);\n };\n\n Controller.prototype.setNextVideo = function(title) {\n if (title && title !== '') {\n debug.info('setNextVideo', decodeURIComponent(title));\n completion.setNextVideo(decodeURIComponent(title));\n }\n };\n\n Controller.prototype.setAutoplayVisible = function(visibility) {\n if (visibility === true) {\n inlinePC.showAutoPlay();\n } else {\n inlinePC.hideAutoPlay();\n }\n };\n\n Controller.prototype.setContinuousPlay = function(isContinuousPlay) {\n if (typeof isContinuousPlay !== 'boolean') {\n return;\n }\n\n state.continuousPlay = isContinuousPlay;\n };\n\n Controller.prototype.setBeaconData = function(beacon) {\n tracker.setBeaconData(beacon);\n };\n\n Controller.prototype.setPlaybackRate = function(rate) {\n setPlaybackRate(rate);\n };\n\n Controller.prototype.setupControl = function() {\n setupControl();\n };\n\n Controller.prototype.resetCustomUI = function() {\n resetCustomUI();\n };\n\n Controller.prototype.showError = function(info, option) {\n showError(info, option);\n };\n\n Controller.prototype.showConfirm = function(option) {\n showConfirm(option);\n };\n\n Controller.prototype.alert3G4G = function(status, callback) {\n alert3G4G(status, callback);\n };\n\n Controller.prototype.readyVideo = function(isAutoPlay, profile) {\n readyVideo(isAutoPlay, profile);\n };\n\n Controller.prototype.readyClipVideo = function(isAutoPlay, start, profile) {\n readyClipVideo(isAutoPlay, start, profile);\n };\n\n Controller.prototype.loadVideoResource = function(clip) {\n loadVideoResource(clip);\n };\n\n Controller.prototype.cancelFullScreen = function() {\n cancelFullScreen();\n };\n\n Controller.prototype.fetchMeta = function() {\n return fetchMeta();\n };\n\n Controller.prototype.resetPlayerInfo = function() {\n resetPlayerInfo();\n };\n\n Controller.prototype.isAdBlock = function() {\n return isActivatedAdBlock();\n };\n\n Controller.prototype.initVolumeControl = function() {\n initVolumeControl();\n };\n\n Controller.prototype.setDefaultOptions = function() {\n setDefaultOptions();\n };\n\n Controller.prototype.checkAutoPlay = function(isAutoPlay) {\n return checkAutoPlay(isAutoPlay);\n };\n\n return Controller;\n })();\n\n exports.addModule('controller.video', new Controller());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports) {\n 'use strict';\n\n var Controller;\n\n Controller = (function() {\n var inline = exports.loadModule('view.inline');\n var inlinePC = exports.loadModule('view.inline.pc');\n var cover = exports.loadModule('view.cover');\n var queue = exports.loadModule('playlist.queue');\n var tracker = exports.loadModule('etc.tracker');\n var websocket = exports.loadModule('etc.websocket');\n var state = exports.loadModule('controller.state');\n var player = exports.loadModule('player.adapter');\n var controller = exports.loadModule('controller.video');\n var actionController = exports.loadModule('controller.action');\n var dataloader = exports.loadModule('playlist.dataloader');\n var pvtTracker = exports.loadModule('pvt.tracker');\n var pctTracker = exports.loadModule('pct.tracker');\n var adController = exports.loadModule('controller.ad');\n\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n var ERROR_STATUS = constants.ERROR.STATUS;\n var CONFIRM_STATUS = constants.CONFIRM.STATUS;\n\n var canPlayHLSAndroid = helpers.feature.canPlayHLSAndroid();\n\n var livePlayer = {\n filter3G4GAlert: function(url, callback) {\n controller.alert3G4G(CONFIRM_STATUS.CARRIER, callback);\n },\n filterHDAlert: function(profile) {\n return controller.showConfirm({\n status: CONFIRM_STATUS.LAUNCH_APP,\n accept: function() {\n if (player.videoElement.src === '') {\n cover.showCover();\n }\n\n livePlayer.goApp(profile);\n\n pctTracker.track('liveapp', 'ok');\n },\n cancel: function() {\n if (player.videoElement.src === '') {\n cover.showCover();\n } else {\n inline.showControl();\n }\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onPlayCancel);\n }\n });\n },\n filterLinear: function(profile) {\n return controller.showConfirm({\n status: CONFIRM_STATUS.LinearLive,\n accept: function() {\n cover.showCover();\n livePlayer.goApp(profile);\n },\n cancel: function() {\n cover.showCover();\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onPlayCancel);\n }\n });\n },\n goApp: function(profile) {\n var liveLinkId = state.currentVideo.id;\n helpers.web2app.launchKakaoTV(ua, liveLinkId, profile);\n },\n canPlayHLS: function() {\n if (ua.os.android) {\n if (canPlayHLSAndroid) {\n return true;\n }\n }\n\n if (ua.os.ios) {\n if (helpers.feature.canPlayHLS()) {\n return true;\n }\n }\n\n return false;\n },\n isSupportNPP: function() {\n if (ua.platform === 'pc') {\n return true;\n }\n\n return false;\n }\n };\n\n function setLiveContentType(profile) {\n var contentType = constants.CONTENT_TYPE.HLS;\n\n if (ua.os.android && !canPlayHLSAndroid) {\n contentType = constants.CONTENT_TYPE.RTSP;\n } else if (\n ua.platform === 'pc' &&\n player.isInstalledLiveAgent() &&\n profile !== constants.PROFILE.BASE &&\n env.useNPP\n ) {\n contentType = constants.CONTENT_TYPE.NPP;\n }\n\n if (env.liveTypeLinear) {\n contentType = constants.CONTENT_TYPE.LINEAR;\n }\n\n if (state.currentVideo) {\n state.currentVideo.contentType = contentType;\n }\n return contentType;\n }\n\n function setLiveCover() {\n if (env.showCover) {\n var video = state.currentVideo;\n var liveLink = '/channel/#{channelId}/livelink/#{liveLinkId}';\n liveLink = helpers.string.format(liveLink, {\n channelId: video.channelId,\n liveLinkId: video.id\n });\n\n var coverUrl = helpers.string.getThumbnailFarmUrl(video.coverUrl, 'C640x360');\n\n if (env.coverUrl !== '') {\n coverUrl = env.coverUrl;\n }\n\n cover.setThumbnail(coverUrl);\n cover.setTitle(liveLink, video.title);\n }\n }\n\n function loadReadyAndPlay(id, profile, password) {\n return fetchReadyAndPlay(id, profile, password).then(function(readyAndPlay) {\n setReadyAndPlay(id, readyAndPlay);\n setLiveContentType(profile);\n\n var contentType = state.currentVideo.contentType;\n\n if (\n !player.isInstalledLiveAgent() &&\n ua.platform === 'pc' &&\n (profile === constants.PROFILE.MAIN ||\n profile === constants.PROFILE.HIGH ||\n profile === constants.PROFILE.HIGH4)\n ) {\n if (!ua.browser.msie) {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.LiveAgentNotInstalled.NAME,\n profile: profile\n }\n });\n } else {\n if (!player.isSupportedLiveAgentHLS()) {\n location.href = location.href + '&flash=1';\n }\n\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.LiveAgentNotInstalled.NAME,\n profile: profile\n }\n });\n }\n throw Error('Live agent not installed');\n }\n\n if (contentType === constants.CONTENT_TYPE.RTSP) {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.NotSupportedMedia.NAME\n }\n });\n throw Error('RTSP contentType is not supported!');\n }\n\n if (contentType === constants.CONTENT_TYPE.LINEAR) {\n livePlayer.filterLinear(profile);\n inline.endSpinner();\n throw Error('Linear contentType is not supported!');\n }\n\n if (readyAndPlay && readyAndPlay.pct) {\n tracker.setPCTTracker(readyAndPlay.pct);\n }\n\n if (readyAndPlay && readyAndPlay.pit) {\n helpers.http.sendBeacon(readyAndPlay.pit.url);\n }\n\n loadMeta();\n\n if (readyAndPlay.actionReq) {\n actionController.load(readyAndPlay.actionReq.url);\n }\n\n if (!env.useNPP && ua.os.mac) {\n inlinePC.hideQualityButton();\n }\n });\n }\n\n function fetchReadyAndPlay(id, profile, password) {\n var uuid = helpers.uuid.get();\n var options = {\n service: env.service,\n section: env.section,\n uuid: uuid,\n dteType: helpers.device.getDteType(ua),\n profile: profile,\n autoPlay: env.feedType,\n liveLinkId: id,\n contentType: setLiveContentType(profile),\n password: password ? encodeURIComponent(password) : '',\n ab: env.ab,\n literallist: env.literallist\n };\n\n if (env.adenc) {\n options.adenc = env.adenc;\n }\n\n if (env.section2) {\n options.section2 = env.section2;\n }\n\n if (env.ptoken) {\n options.ptoken = env.ptoken;\n }\n\n if (env.serviceReferrer) {\n options.pageReferer = env.serviceReferrer;\n }\n\n if (env.cpID) {\n options.cpID = env.cpID;\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onStartImpression, [id]);\n\n return dataloader.getLiveReadyAndPlay(id, options);\n }\n\n function loadMeta() {\n return controller\n .fetchMeta()\n .then(function() {\n onCompleteMeta();\n })\n .catch(function(e) {\n debug.log('Meta server error', e);\n });\n }\n\n function loadVideo(live) {\n debug.info('%c%s', 'color: #20b408', '[live controller] load video', live);\n\n var callbackParameters = helpers.sdk.getDefaultCallbackParams(state.currentVideo);\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onStartLoadVideo, callbackParameters);\n\n adController\n .fetchPreroll()\n .then(controller.startNextQueue)\n .catch(function() {\n if (live.skipOnErrorOfAdApi) {\n readyLiveVideo();\n }\n });\n }\n\n function preStartVideo(profile) {\n var video = state.currentVideo;\n\n if (!video) {\n return;\n }\n\n if (env.showHDConfirm && profile === constants.PROFILE.HIGH) {\n livePlayer.filterHDAlert(profile);\n return;\n }\n\n var videoUrl = state.currentVideo.videoUrl;\n var canPlayHLS = livePlayer.canPlayHLS();\n var isSupportNPP = livePlayer.isSupportNPP();\n debug.tooltip('canPlayHLS: ', canPlayHLS);\n\n livePlayer.filter3G4GAlert(videoUrl, function() {\n cover.hideCover();\n\n if (!canPlayHLS && !isSupportNPP) {\n window.open(videoUrl, '_top');\n cover.showCover();\n debug.tooltip('현재 브라우저의 환경에서는 라이브 재생(HLS, NPP)을 지원하지 않습니다.', '');\n } else {\n loadVideo(video);\n }\n });\n }\n\n function normalizeLiveId(id) {\n return isNaN(id) ? id : parseInt(id, 10);\n }\n\n function setReadyAndPlay(id, readyAndPlay) {\n var videoLocation = readyAndPlay.videoLocation;\n var liveBean = {};\n\n if (!videoLocation || !videoLocation.url) {\n throw Error('Live url not found');\n }\n helpers.uuid.set(readyAndPlay.uuid);\n\n liveBean.linkId = readyAndPlay.linkId;\n liveBean.tid = readyAndPlay.tid;\n liveBean.vid = env.vid;\n liveBean.videoUrl = videoLocation && videoLocation.url;\n liveBean.profile = videoLocation && videoLocation.profile;\n liveBean.vmapReq = readyAndPlay.vmapReq;\n liveBean.tracking = {\n pvt: readyAndPlay.pvt,\n pct: readyAndPlay.pct,\n pit: readyAndPlay.pit\n };\n liveBean.skipOnErrorOfAdApi = readyAndPlay.skipOnErrorOfAdApi;\n liveBean.skipOnErrorOfAdContents = readyAndPlay.skipOnErrorOfAdContents;\n liveBean.metaUrl = readyAndPlay.metaUrl;\n liveBean.autoplayPreroll = readyAndPlay.autoplayPreroll;\n liveBean.isDrm = readyAndPlay.licenseUrl;\n\n try {\n liveBean.dsp = readyAndPlay.vmapReq.pre.imp_request.dsp_id;\n } catch (e) {}\n\n if (readyAndPlay && readyAndPlay.qoe) {\n tracker.setQOETracker(readyAndPlay.qoe);\n }\n\n if (window.WebSocket && readyAndPlay.ws) {\n websocket.setConfig(readyAndPlay.ws);\n if (readyAndPlay.ws.connectionTiming === 'IMMEDIATELY') {\n websocket.open();\n }\n }\n\n state.currentVideo.set(liveBean);\n pvtTracker.clear();\n }\n\n function readyLiveVideo(isAutoPlay, profile) {\n var liveBean = state.currentVideo;\n queue.contents.push(liveBean);\n readyVideo(isAutoPlay, profile);\n }\n\n function readyVideo(isAutoPlay, profile) {\n var autoplay = controller.checkAutoPlay(isAutoPlay);\n var callbackParameters = helpers.sdk.getDefaultCallbackParams(state.currentVideo);\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onReadyVideo, callbackParameters);\n\n if (env.showHDConfirm && isAutoPlay && profile === constants.PROFILE.HIGH) {\n livePlayer.filterHDAlert(profile);\n return;\n }\n\n if (autoplay) {\n preStartVideo(profile);\n } else {\n inline.endSpinner();\n cover.showCover();\n }\n }\n\n function onCompleteMeta() {\n setLiveContentType(state.currentVideo.profile);\n setLiveCover();\n\n exports.queue.emit('create:kakaotalkLink');\n }\n\n function load($id, $profile, $isAutoPlay, $password) {\n var profile = $profile;\n var isAutoPlay = $isAutoPlay;\n\n player.stop();\n\n if (controller.isAdBlock()) {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.UNAVAILABLE_ADBLOCK.NAME\n }\n });\n return;\n }\n\n if (ua.platform === 'pc') {\n if (!player.isSupportedLiveAgentHLS()) {\n location.href = location.href + '&flash=1';\n return;\n }\n\n if (player.isInstalledLiveAgent() === null) {\n debug.warn('Live Agent 확인이 완료되지 않았습니다.');\n setTimeout(function() {\n load($id, profile, isAutoPlay, $password);\n }, 300);\n return;\n }\n }\n\n if (!player.isInstalledLiveAgent() && !env.forceProfile) {\n profile = constants.PROFILE.BASE;\n }\n\n if (!env.useNPP) {\n profile = constants.PROFILE.AUTO;\n }\n\n if (typeof isAutoPlay === 'boolean' && !isAutoPlay && !(state.isPrerollEnded && state.isPostrollEnded)) {\n queue.dequeueCancel(queue.front);\n cover.showCover();\n return;\n }\n\n controller.resetPlayerInfo();\n controller.initVolumeControl();\n inline.startSpinner();\n state.initInitialState();\n state.initCurrentVideo($id, constants.VIDEO_TYPE.LIVE);\n\n loadReadyAndPlay($id, profile, $password)\n .then(function() {\n return adController.fetchAds(state.currentVideo);\n })\n .then(function() {\n queue.contents.push(state.currentVideo);\n\n if (player.isSupportedLiveAgentHLS() && !env.popup) {\n isAutoPlay = false;\n }\n\n if ($password) {\n state.currentVideo.password = $password;\n }\n\n debug.tooltip('isSupportedLiveAgentHLS: ', player.isSupportedLiveAgentHLS());\n readyVideo(isAutoPlay, profile);\n })\n .catch(function(e) {\n debug.info('Failed live loadReadyAndPlay: ', e);\n });\n }\n\n function Controller() {}\n\n Controller.prototype.init = function() {};\n\n Controller.prototype.load = function($id, $profile, $isAutoPlay, $password) {\n var id = normalizeLiveId($id);\n load(id, $profile, $isAutoPlay, $password);\n };\n\n Controller.prototype.loadAndPlay = function($id, $profile) {\n var id = normalizeLiveId($id);\n load(id, $profile, true);\n };\n\n Controller.prototype.play = function($profile) {\n var profile = $profile;\n\n if (player.videoElement.src !== '' && queue.front) {\n if (queue.front.type !== constants.VIDEO_TYPE.AD) {\n inline.hideActivatedControl();\n }\n cover.hideCover();\n player.play();\n return;\n }\n\n if (!profile) {\n profile = state.currentVideo.profile;\n }\n\n preStartVideo(profile);\n };\n\n Controller.prototype.preStartVideo = function(profile) {\n preStartVideo(profile);\n };\n\n Controller.prototype.readyLiveVideo = function(isAutoPlay, profile) {\n readyLiveVideo(isAutoPlay, profile);\n };\n\n return Controller;\n })();\n\n exports.addModule('controller.live', new Controller());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var state = exports.loadModule('controller.state');\n var player = exports.loadModule('player.adapter');\n var shaka = exports.loadModule('player.shaka');\n var dataloader = exports.loadModule('playlist.dataloader');\n var inlinePC = exports.loadModule('view.inline.pc');\n var extension = exports.loadModule('view.extension');\n var contextMenu = exports.loadModule('view.contextmenu');\n var cast = exports.loadModule('view.cast');\n\n var CastController;\n\n CastController = (function() {\n var ua = exports.ua;\n var env = exports.ENV;\n var constants = exports.constants;\n var helpers = exports.helpers;\n\n var isDash = false;\n var castFramework = {};\n var chrome = {};\n var remotePlayer = {};\n var remoteController = {};\n var eventListener = function() {};\n\n function init() {\n remotePlayer = {};\n remoteController = {};\n\n create();\n }\n\n function create() {\n var options = {};\n\n castFramework = window.cast.framework;\n chrome = window.chrome;\n\n remotePlayer = new castFramework.RemotePlayer();\n\n options.receiverApplicationId = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;\n options.autoJoinPolicy = chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED;\n\n castFramework.CastContext.getInstance().setOptions(options);\n remoteController = new castFramework.RemotePlayerController(remotePlayer);\n }\n\n function resetCastPlayer() {\n var originPlayer = player.getOriginPlayer();\n var playerClass = constants.PLAYERCLASS.HTML5;\n\n if (originPlayer) {\n return;\n }\n\n if (state.abr) {\n playerClass = constants.PLAYERCLASS.SHAKA;\n }\n\n init();\n initPlayer(originPlayer, {\n playerClass: playerClass,\n videoUrl: false\n });\n }\n\n function registerRemoteEventListener(listener) {\n eventListener = listener;\n\n if (typeof eventListener === 'function') {\n eventListener(remoteController);\n }\n }\n\n function hideMenuOnCast(isAirplay) {\n if (!isAirplay) {\n extension.hideRelatedButton();\n }\n inlinePC.hideMenuOnCast(isAirplay);\n contextMenu.hidePip();\n }\n\n function showMenuOnCast(isAirplay) {\n inlinePC.showMenuOnCast(isAirplay);\n contextMenu.showPip();\n }\n\n function loadRemotePlayer() {\n if (state.abr) {\n // player.setTextTrack(constants.SUBTITLE.STATUS.OFF);\n shaka.reset(player.videoElement);\n state.abr = false;\n isDash = true;\n swapVideoUrl();\n }\n\n var videoInfo = {\n url: state.currentVideo.videoUrl,\n mediaType: constants.MEDIA_TYPE.MP4\n };\n\n hideMenuOnCast();\n load(videoInfo, player.getCurrentTimeRound());\n }\n\n function swapVideoUrl() {\n var videoUrl = state.currentVideo.originVideoUrl;\n state.currentVideo.originVideoUrl = state.currentVideo.videoUrl;\n state.currentVideo.videoUrl = videoUrl;\n }\n\n function loadRemotePlayerForLive() {\n var bean = state.currentVideo;\n var uuid = helpers.uuid.get();\n var params = {\n service: env.service,\n section: env.section,\n uuid: uuid,\n dteType: helpers.device.getDteType(ua),\n profile: constants.PROFILE.MAIN,\n liveLinkId: bean.id,\n contentType: constants.CONTENT_TYPE.HLS\n };\n\n if (env.section2) {\n params.section2 = env.section2;\n }\n\n dataloader.getLiveImpression(bean.id, params, function(result) {\n if (result.status !== 'success') {\n return;\n }\n var data = result.data;\n var videoUrl = data.raw.videoLocation.url;\n var videoInfo = {\n url: videoUrl,\n mediaType: constants.MEDIA_TYPE.HLS\n };\n hideMenuOnCast();\n load(videoInfo, 0);\n });\n }\n\n function cancelRemotePlayer(currentTime) {\n var playerClass = constants.PLAYERCLASS.HTML5;\n var loadedCallback = {};\n\n if (isDash) {\n swapVideoUrl();\n state.abr = true;\n playerClass = constants.PLAYERCLASS.SHAKA;\n loadedCallback = function() {\n if (currentTime > 0) {\n player.seekTo(currentTime);\n player.play();\n }\n };\n }\n\n var loadData = {\n playerClass: playerClass,\n videoUrl: state.currentVideo.videoUrl,\n callback: loadedCallback\n };\n\n showMenuOnCast();\n unload(loadData, currentTime);\n }\n\n function cancelRemotePlayerForLive() {\n var loadData = {\n playerClass: constants.PLAYERCLASS.KAMP,\n videoUrl: state.currentVideo.videoUrl\n };\n\n showMenuOnCast();\n unload(loadData, 0);\n }\n\n function load(videoInfo, start) {\n player.pause();\n player.load({\n playerClass: constants.PLAYERCLASS.CAST,\n remote: {\n player: remotePlayer,\n controller: remoteController,\n videoInfo: videoInfo,\n start: start\n },\n callback: function() {\n var playerInstance = player.getPlayerInstance();\n var castSession = playerInstance.getSession ? playerInstance.getSession() : {};\n\n if (castSession.getCastDevice) {\n var device = castSession.getCastDevice();\n cast.setConnectedDeviceText(device.friendlyName);\n inlinePC.showLoadedMenuOnCast();\n }\n }\n });\n }\n\n function unload(loadData, start) {\n var originPlayer = player.getOriginPlayer();\n\n player.stop();\n\n if (!originPlayer) {\n return;\n }\n\n inlinePC.hideLoadedMenuOnCast();\n initPlayer(originPlayer, loadData);\n\n if (state.ended) {\n return;\n }\n if (start > 0) {\n player.seekTo(start);\n }\n\n player.play();\n }\n\n function initPlayer(playerInstance, loadData) {\n player.init(playerInstance);\n if (!state.ended) {\n player.load(loadData);\n }\n }\n\n function convertSrcMode() {\n if (state.currentVideo.profile === constants.PROFILE.AUTO) {\n state.currentVideo.profile = state.currentVideo.originProfile;\n }\n\n var outputList = state.currentVideo.originOutputList;\n\n state.currentVideo.originOutputList = state.currentVideo.outputList;\n state.currentVideo.outputList = outputList;\n state.abr = false;\n state.playerClass = constants.PLAYERCLASS.HTML5;\n\n swapVideoUrl();\n inlinePC.onLoadStart();\n\n shaka.detach().then(function() {\n player.load({\n videoUrl: state.currentVideo.videoUrl\n });\n });\n }\n\n function CastController() {}\n\n CastController.prototype.init = function() {};\n\n CastController.prototype.create = function() {\n create();\n };\n\n CastController.prototype.loadRemotePlayer = function() {\n loadRemotePlayer();\n };\n\n CastController.prototype.loadRemotePlayerForLive = function() {\n loadRemotePlayerForLive();\n };\n\n CastController.prototype.cancelRemotePlayer = function(currentTime) {\n cancelRemotePlayer(currentTime);\n };\n\n CastController.prototype.cancelRemotePlayerForLive = function() {\n cancelRemotePlayerForLive();\n };\n\n CastController.prototype.resetCastPlayer = function() {\n resetCastPlayer();\n };\n\n CastController.prototype.registerRemoteEventListener = function(eventListener) {\n registerRemoteEventListener(eventListener);\n };\n\n CastController.prototype.getRemoteEventType = function() {\n return castFramework.RemotePlayerEventType;\n };\n\n CastController.prototype.getMediaState = function() {\n return chrome.cast.media.PlayerState;\n };\n\n CastController.prototype.convertSrcMode = function() {\n convertSrcMode();\n };\n\n CastController.prototype.showMenuOnCast = function(isAirplay) {\n showMenuOnCast(isAirplay);\n };\n\n CastController.prototype.hideMenuOnCast = function(isAirplay) {\n hideMenuOnCast(isAirplay);\n };\n\n CastController.prototype.tte = function() {\n return remoteController;\n };\n\n CastController.prototype.ttt = function() {\n return remotePlayer;\n };\n\n return CastController;\n })();\n\n exports.addModule('controller.cast', new CastController());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var error = exports.loadModule('view.error');\n var queue = exports.loadModule('playlist.queue');\n var tracker = exports.loadModule('etc.tracker');\n var vastTracker = exports.loadModule('vast.tracker');\n var pvtTracker = exports.loadModule('pvt.tracker');\n var qoeTracker = exports.loadModule('qoe.tracker');\n var state = exports.loadModule('controller.state');\n var player = exports.loadModule('player.adapter');\n var shaka = exports.loadModule('player.shaka');\n var inline = exports.loadModule('view.inline');\n var inlinePC = exports.loadModule('view.inline.pc');\n var adController = exports.loadModule('controller.ad');\n var controller = exports.loadModule('controller.video');\n var completion = exports.loadModule('view.completion');\n var retry = exports.loadModule('view.retry');\n var analytics = exports.loadModule('view.analytics');\n var mediaSession = exports.loadModule('media.session');\n var extension = exports.loadModule('view.extension');\n\n var EventVideo;\n\n EventVideo = (function() {\n var $ = dt.$;\n var event = dt.event;\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n var ERROR_STATUS = constants.ERROR.STATUS;\n var currentTime = 0;\n var pastTime = 0;\n var supposedCurrentTime = 0;\n var isSupportCustomController = helpers.device.isSupportCustomController(ua);\n var requestAnimateId = null;\n var qoeEvent = constants.QOE.EVENT;\n var timeupdateTimeout = null;\n\n function onLoadVideoSize() {\n var docBody = document.body;\n\n var playerWidth = docBody.clientWidth;\n var scale = playerWidth / player.videoElement.videoWidth;\n var toHeight = player.videoElement.videoHeight * scale;\n\n var video = queue.front;\n\n if (video && player.videoElement.videoWidth > 1) {\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onMeasureHeight, [\n toHeight,\n playerWidth,\n video.id\n ]);\n }\n }\n\n function togglePlayPause(isPaused) {\n var video = queue.front;\n\n if (ua.platform === 'pc') {\n inlinePC.togglePlayPause(isPaused);\n } else {\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n inline.toggleAdPlayPause(isPaused);\n } else {\n inline.togglePlayPause(isPaused);\n }\n }\n }\n\n function showControl(isFreeze) {\n var video = queue.front;\n var currentVideo = state.currentVideo;\n\n if (!state.modalContentActivated && video && video.type !== constants.VIDEO_TYPE.AD && !state.isFirstPlay) {\n inline.showControl(isFreeze);\n } else if (video && video.type === constants.VIDEO_TYPE.AD && queue.front.breakId === 'midroll') {\n inline.showAdControl(isFreeze);\n }\n\n if (video && video.type !== constants.VIDEO_TYPE.AD && state.isFirstPlay && !currentVideo.resumeOffset) {\n inline.showRating();\n }\n }\n\n function isFullScreen() {\n return inline.isFullScreen();\n }\n\n function onAbort() {\n debug.info('%c%s', 'color: #2074c0;', '[video event] abort');\n }\n\n function onDurationChange() {\n var video = queue.front;\n\n debug.info('%c%s', 'color: #2074c0;', '[video event] durationchange - ', video && video.type);\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n adController.setupAdControl();\n adController.showLinearAdContainer();\n } else {\n controller.setupControl();\n\n if (!state.isNonLinearAdShown) {\n adController.setupNonLinearAd();\n }\n\n if (state.currentVideo.midrollReq) {\n adController.setupMidrollAd();\n }\n\n if (env.isAdType) {\n showControl(true);\n }\n }\n onLoadVideoSize();\n }\n\n function onCanPlay() {\n var video = queue.front;\n currentTime = 0;\n pastTime = 0;\n\n debug.info('%c%s', 'color: #2074c0;', '[video event] canplay - ', video && video.type, state.ended);\n togglePlayPause(player.isPaused());\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n adController.activateAdControl();\n }\n }\n\n function onTimeUpDate() {\n var video = queue.front;\n var isCheckableNonLinearAd =\n !player.isPaused() && !state.seeking && queue.overlayAds && queue.overlayAds.length > 0;\n var isShowLiveAgentInstallView = !dt.classList.has($('alertLiveAgent'), 'hide');\n\n if (!player.videoElement.seeking) {\n supposedCurrentTime = player.getCurrentTime();\n }\n\n // timeupdate event가 random하게 발생하는 부분을 보완하기 위해 1초단위로 파싱\n currentTime = player.getCurrentTimeRound();\n\n // throttle function 호출은 full seconds가 바뀌었을 때 (e.g 1, 2, 3 ..)\n if (currentTime > pastTime) {\n debug.log('%c%s', 'color: #2074c0;', '[video event] timeupdate - currentTime', currentTime);\n\n clearTimeupdateTimeout();\n sendOffsetPointUpdate();\n inline.onTimeUpdate(currentTime, player.getDurationRound());\n inline.endSpinner();\n\n if (!isShowLiveAgentInstallView && ua.platform === 'pc') {\n error.hideError();\n }\n\n if (currentTime === pastTime + 1) {\n retry.resetTimer();\n }\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n vastTracker.setDuration(player.getDurationRound());\n vastTracker.setProgress(currentTime);\n\n inline.setDuration(player.getDurationRound());\n if (player.getDurationRound() < currentTime) {\n excuteEnded(false);\n }\n } else {\n pvtTracker.setDuration(player.getDurationRound());\n pvtTracker.setProgress(currentTime);\n\n if (player.getDurationRound() > 1) {\n tracker.checkBeaconData(currentTime / player.getDurationRound());\n }\n\n if (isCheckableNonLinearAd) {\n adController.checkNonLinearAd(currentTime, player.getDurationRound());\n }\n\n if (video && video.type !== constants.VIDEO_TYPE.LIVE && !state.seeking) {\n if (player.isPaused()) {\n state.needMidrollRequest = true;\n } else {\n adController.checkMidrollAd(false, controller.startNextQueue);\n }\n }\n }\n\n if (ua.os.android && video && video.type === constants.VIDEO_TYPE.LIVE) {\n timeupdateTimeout = setTimeout(function() {\n if (!player.isPaused()) {\n var info = {\n code: 'LiveException',\n message: '라이브가 종료되었거나, 재생이 원활하지 않습니다.',\n needCheck: false\n };\n\n state.ended = true;\n error.showError(info.code, info, null);\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onVideoStateChange, [\n constants.PLAYER_VIDEO_STATE.ENDED,\n state.currentVideo.id,\n player.getCurrentTimeRound(),\n video && video.type\n ]);\n }\n }, 10 * 1000);\n } else if (ua.os.ios) {\n if (state.hls) {\n inline.setProfile(state.currentVideo.profile);\n }\n\n timeupdateTimeout = setTimeout(function() {\n if (!window.navigator.onLine) {\n retry.clearTimer();\n\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.NETWORK_OFFLINE.NAME\n }\n });\n inline.endSpinner();\n } else if (!player.isPaused()) {\n player.pause();\n }\n }, 5 * 1000);\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onTimeUpdate, [\n state.currentVideo.id,\n video && video.type,\n player.getCurrentTimeRound(),\n player.getDurationRound()\n ]);\n }\n\n pastTime = currentTime;\n }\n\n function onSeeking() {\n var video = queue.front;\n debug.info('%c%s', 'color: #2074c0;', '[video event] seeking');\n\n if (!state.seeking) {\n inline.startSpinner();\n }\n\n if (player.getCurrentTimeRound() < player.getDurationRound()) {\n completion.hideCompletion();\n }\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n var delta = player.getCurrentTime() - supposedCurrentTime;\n\n if (Math.abs(delta) > 0.01) {\n player.videoElement.currentTime = supposedCurrentTime;\n }\n }\n }\n\n function onSeeked() {\n if (dt.StopWatch.has('seek')) {\n qoeTracker.track(qoeEvent.SEEK, { n1: dt.StopWatch.stop('seek') });\n }\n\n var video = queue.front;\n\n debug.info(\n '%c%s',\n 'color: #2074c0;',\n '[video event] seeked -',\n video && video.type,\n player.getCurrentTime()\n );\n\n inline.endSpinner();\n inline.onSeeked();\n\n if (video && video.type !== constants.VIDEO_TYPE.AD && isSupportCustomController) {\n if (!state.ended) {\n togglePlayPause(player.isPaused());\n if (!state.seeking) {\n showControl(player.isPaused());\n }\n }\n }\n\n if (video && video.type === constants.VIDEO_TYPE.VOD) {\n if (state.ended) {\n excuteEnded(false);\n } else {\n if (state.pausedBeforeSeek && player.isPaused()) {\n player.pause();\n state.needMidrollRequest = true;\n } else {\n player.play();\n adController.checkMidrollAd(true, controller.startNextQueue);\n player.videoElement.setAttribute('data-time-before-seek', '');\n }\n }\n }\n\n retry.clearTimer();\n }\n\n function updateBufferable() {\n var bufferLen = player.videoElement.buffered.length;\n var buffered = player.videoElement.buffered;\n\n if (player.getDurationRound() > 0 && bufferLen > 0) {\n var range = bufferLen - 1;\n var end = buffered.end(range);\n inline.onProgress(end / player.getDurationRound());\n }\n }\n\n function onProgress() {\n var video = queue.front;\n if (video && video.type !== constants.VIDEO_TYPE.LIVE) {\n updateBufferable.apply(this);\n }\n }\n\n function onPlay() {\n var video = queue.front;\n\n debug.info(\n '%c%s',\n 'color: #2074c0;',\n '[video event] play -',\n video && video.type,\n ', isResume -',\n state.isFirstPlay,\n ', width, height -',\n player.videoElement.videoWidth,\n player.videoElement.videoHeight\n );\n\n controller.resetCustomUI();\n togglePlayPause(player.isPaused());\n inline.checkFullscreenEnabled();\n inline.onPlay();\n state.preventTogglePlayPause = false;\n state.pausedBeforeSeek = false;\n state.ended = false;\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n if (player.getCurrentTime() > 0) {\n vastTracker.pause(false);\n }\n exports.queue.emit('hide:action');\n } else {\n adController.resumeNonLinearAd();\n exports.queue.emit('show:action');\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onVideoStateChange, [\n constants.PLAYER_VIDEO_STATE.PLAY,\n state.currentVideo.id,\n player.getCurrentTimeRound(),\n video && video.type\n ]);\n\n if (ua.platform === 'pc') {\n inlinePC.clearRelatedTimer();\n }\n\n requestAnimateId = window.requestAnimationFrame(updateProgress);\n\n clearTimeupdateTimeout();\n retry.clearTimer();\n\n if (video && video.type !== constants.VIDEO_TYPE.LIVE) {\n inline.endSpinner();\n }\n\n if (state.isFirstPlay) {\n if (state.abr && state.currentVideo.profile !== constants.PROFILE.AUTO) {\n shaka.setTrack(state.currentVideo.profile);\n }\n\n exports.queue.emit('create:cast:connector');\n }\n }\n\n function onPlaying() {\n var video = queue.front;\n var title = video.title;\n var artist = video.channelName;\n\n debug.info(\n '%c%s',\n 'color: #2074c0;',\n '[video event] playing - ',\n player.videoElement.videoWidth,\n player.videoElement.videoHeight\n );\n\n if (state.autoplayFail) {\n return;\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onVideoStateChange, [\n constants.PLAYER_VIDEO_STATE.PLAYING,\n state.currentVideo.id,\n player.getCurrentTimeRound(),\n video && video.type\n ]);\n\n if (video && video.type !== constants.VIDEO_TYPE.AD) {\n var timing = player.videoElement.getAttribute('data-current-time');\n timing = parseInt(timing);\n\n pvtTracker.resume();\n\n if (!dt.StopWatch.has('playingTime')) {\n dt.StopWatch.start('playingTime');\n } else {\n dt.StopWatch.resume('playingTime');\n }\n\n if (!dt.StopWatch.has('midrollPlayingTime')) {\n dt.StopWatch.start('midrollPlayingTime');\n } else {\n dt.StopWatch.resume('midrollPlayingTime');\n }\n\n setTimeout(\n function() {\n if (timing && timing > 0) {\n controller.seekTo(timing);\n player.videoElement.removeAttribute('data-current-time');\n if (player.getDurationRound() <= timing) {\n excuteEnded(false);\n } else {\n if (state.currentVideo.resumeOffset) {\n var relatedData = {\n message: '마지막 시청 지점부터 이어서 재생됩니다.',\n callback: function() {\n exports.queue.emit('hide:modal');\n }\n };\n exports.queue.emit('show:notification', relatedData);\n state.currentVideo.resumeOffset = null;\n }\n\n player.play();\n }\n }\n },\n ua.os.ios || helpers.device.isPCWithSafari(ua) ? 500 : 10\n );\n } else {\n title = '광고 재생 중입니다.';\n artist = '';\n }\n\n mediaSession.updateMetadata(title, artist);\n inline.endSpinner();\n\n if (ua.platform === 'pc') {\n if (video && video.type === constants.VIDEO_TYPE.AD && env.isPrivateIp) {\n analytics.chartHide();\n }\n\n inline.setSize();\n inline.reSize();\n }\n\n if (video && video.type !== constants.VIDEO_TYPE.AD) {\n if (state.isFirstPlay) {\n onLoadVideoSize();\n exports.queue.emit('show:rating');\n state.isFirstPlay = false;\n }\n if (video.purchase) {\n exports.queue.emit('show:preview');\n }\n }\n\n var self = this;\n\n var timer = setInterval(function() {\n if (self.currentTime > 0) {\n if (dt.StopWatch.has('startPlay')) {\n var initialDelay = dt.StopWatch.stop('startPlay');\n qoeTracker.track(qoeEvent.INITIAL_DELAY, { n1: initialDelay });\n debug.tooltip(qoeEvent.INITIAL_DELAY + ': ', initialDelay + 'ms');\n }\n\n if (dt.StopWatch.has('rebuffering')) {\n var reBuffering = dt.StopWatch.stop('rebuffering');\n qoeTracker.track(qoeEvent.REBUFFERING, { n1: reBuffering });\n debug.tooltip(qoeEvent.REBUFFERING + ': ', reBuffering + 'ms');\n }\n clearInterval(timer);\n }\n\n if (video && video.type !== constants.VIDEO_TYPE.AD) {\n if (state.playbackRate !== player.getPlaybackRate()) {\n player.setPlaybackRate(state.playbackRate, false);\n }\n }\n }, 150);\n }\n\n function onPause() {\n var video = queue.front;\n debug.info(\n '%c%s',\n 'color: #2074c0;',\n '[video event] pause - ',\n video && video.type,\n player.videoElement.ended\n );\n togglePlayPause(player.isPaused());\n mediaSession.setPlaybackState(player.isPaused());\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n vastTracker.pause(true);\n } else {\n if (!state.seeking) {\n adController.pauseNonLinearAd();\n }\n pvtTracker.pause();\n }\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onVideoStateChange, [\n constants.PLAYER_VIDEO_STATE.PAUSE,\n state.currentVideo.id,\n player.getCurrentTimeRound(),\n video && video.type\n ]);\n\n if (ua.platform === 'pc') {\n if (video && video.type === constants.VIDEO_TYPE.VOD) {\n if (player.videoElement.ended) {\n if (state.isMenuOpened) {\n inlinePC.closeMenuBox();\n }\n }\n }\n }\n\n if (\n !player.videoElement.ended &&\n !state.modalContentActivated &&\n (video && video.type) !== constants.VIDEO_TYPE.AD &&\n !state.isShowError &&\n supposedCurrentTime > 0\n ) {\n showControl(true);\n }\n\n cancelAnimationFrame(requestAnimateId);\n retry.clearTimer();\n\n if (video && video.type !== constants.VIDEO_TYPE.AD) {\n dt.StopWatch.pause('playingTime');\n dt.StopWatch.pause('midrollPlayingTime');\n }\n }\n\n function onWaiting() {\n if (!state.seeking) {\n inline.startSpinner();\n if (!dt.StopWatch.has('seek') && !dt.StopWatch.has('startPlay')) {\n dt.StopWatch.start('rebuffering');\n }\n }\n }\n\n function onVolumeChange() {\n var video = queue.front;\n var muteOn = player.getMute();\n var volume = player.getVolume();\n\n debug.info('%c%s', 'color: #2074c0;', '[video event] volumechange -', 'mute:', muteOn, 'volume:', volume);\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n vastTracker.setMute(muteOn);\n }\n\n if (ua.platform === 'pc') {\n inlinePC.toggleMuteUI(volume, muteOn);\n } else {\n inline.toggleMuteUI(muteOn);\n }\n }\n\n // 포스트롤 광고가 끝나거나 컨텐츠 영상이 끝난 경우에만 호출\n function onEndVideo() {\n var currentVideo = state.currentVideo;\n var videoType = queue.front && queue.front.type;\n\n state.ended = true;\n\n togglePlayPause(true);\n\n if (env.loop && videoType !== constants.VIDEO_TYPE.LIVE) {\n var profile = currentVideo.profile;\n\n if (state.abr) {\n profile = constants.DASH_PROFILE[profile];\n }\n\n exports.queue.emit('loadAndPlay:videoById', currentVideo.id, profile, 0);\n return;\n }\n\n if (ua.platform === 'pc') {\n // 자동재생이 활성화 되어있고, 다음영상정보가 있는경우\n if (state.autoplay && completion.hasNextVideo()) {\n inline.hideActivatedControl();\n completion.showWaiting(function() {\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onEndAutoPlayTimer);\n });\n } else if (state.continuousPlay && completion.hasNextVideo()) {\n inline.hideActivatedControl();\n } else {\n inlinePC.onEndVideo();\n }\n } else {\n if (isFullScreen()) {\n inline.hideDefaultControl();\n inline.cancelFullscreen(player.videoElement);\n }\n\n clearTimeupdateTimeout();\n inline.hideActivatedControl();\n inline.onEndVideo();\n }\n\n tracker.sendLeftBeaconData();\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onPlayEnd);\n\n qoeTracker.clear();\n }\n\n var endVideo = {\n checkAdsComplete: function(video, isAdType, error) {\n if (isAdType) {\n if (video.breakId === 'preroll') {\n state.isPrerollEnded = true;\n dt.StopWatch.start('startPlay');\n } else if (video.breakId === 'midroll') {\n state.currentVideo.midrollReq[state.midrollIndex].isStarted = true;\n inline.setupMidrollAd(state.midrollIndex, true);\n } else if (video.breakId === 'postroll') {\n state.isPostrollEnded = true;\n }\n\n adController.inactivateAdControl();\n if (!error) {\n vastTracker.complete();\n }\n } else {\n state.isPrerollEnded = true;\n\n pvtTracker.complete();\n }\n },\n loadPostroll: function(isMediaError) {\n if (state.isPrerollEnded && !state.isPostrollEnded) {\n if (isMediaError) {\n this.startQueueBeforeEnded();\n state.isPostrollEnded = true;\n return;\n }\n\n var self = this;\n\n if (!state.isVastRequesting) {\n adController.fetchPostroll().then(function() {\n self.startQueueBeforeEnded();\n });\n }\n } else {\n state.allAdsCompleted = true;\n onEndVideo();\n }\n },\n startQueueBeforeEnded: function() {\n controller.startNextQueue(function() {\n queue.contents.push(state.currentVideo);\n onEndVideo();\n });\n },\n resolveCustomUI: function(video) {\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n adController.hideLinearAdContainer();\n } else if (video && video.type === constants.VIDEO_TYPE.VOD) {\n adController.hideNonLinearAd();\n }\n\n inline.showVideoCursor();\n inline.updateProgressTime(player.getCurrentTimeRound(), player.getDurationRound());\n },\n complete: function(isMediaError) {\n var video = queue.front;\n\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onVideoStateChange, [\n constants.PLAYER_VIDEO_STATE.ENDED,\n state.currentVideo.id,\n player.getCurrentTimeRound(),\n video && video.type\n ]);\n\n if (!isSupportCustomController) {\n onEndVideo();\n return;\n }\n\n endVideo.loadPostroll(isMediaError);\n }\n };\n\n function excuteEnded(isMediaError) {\n var video = queue.front;\n var isAdType = video && video.type === constants.VIDEO_TYPE.AD;\n\n supposedCurrentTime = 0;\n\n exports.queue.emit('hide:customUI');\n retry.clearTimer();\n\n debug.info('%c%s', 'color: #2074c0;', '[video event] ended', video && video.type, state.ended);\n\n endVideo.checkAdsComplete(video, isAdType, isMediaError);\n endVideo.resolveCustomUI(video);\n\n if (video && video.breakId === 'midroll' && isAdType) {\n queue.contents.push(state.currentVideo);\n\n if (state.abr) {\n shaka.attach(player.videoElement).then(controller.startNextQueue);\n } else {\n controller.startNextQueue();\n }\n } else if (!isAdType || (isAdType && video.breakId === 'postroll')) {\n endVideo.complete(isMediaError);\n } else {\n controller.startNextQueue();\n }\n\n exports.queue.emit('hide:action');\n }\n\n function onEnded() {\n if (state.playerClass === constants.PLAYERCLASS.KAMP) {\n return;\n }\n\n excuteEnded(false);\n inline.resetAriaAttr();\n mediaSession.resetMediaSession();\n }\n\n function onLoadedData() {\n var video = queue.front;\n var videoElement = player.videoElement;\n var callbackParameters = helpers.sdk.getDefaultCallbackParams(state.currentVideo);\n\n debug.info('%c%s', 'color: #2074c0;', '[video event] loadeddata -', video && video.type, state.ended);\n\n if (!state.ended) {\n inline.updateProgressTime(player.getCurrentTimeRound(), player.getDurationRound());\n }\n\n if (video && video.type !== constants.VIDEO_TYPE.LIVE && !helpers.tv.isConnected()) {\n updateBufferable.apply(videoElement);\n }\n\n if (video && video.type !== constants.VIDEO_TYPE.AD) {\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onLoadedContentVideo, callbackParameters);\n }\n\n if (vastTracker && video && video.type === constants.VIDEO_TYPE.AD) {\n vastTracker.load();\n\n if (vastTracker.extension && video.timeOffset === 'end') {\n vastTracker.extension.load();\n }\n }\n inline.setAriaAttr();\n\n clearTimeupdateTimeout();\n retry.clearTimer();\n\n if (ua.platform === 'pc') {\n inlinePC.onLoadedData();\n } else {\n extension.onLoadedData();\n }\n }\n\n function onLoadedMetaData() {\n debug.info(\n '%c%s',\n 'color: #2074c0;',\n '[video event] loadedmetadata -',\n player.videoElement.videoWidth,\n player.videoElement.videoHeight\n );\n }\n\n function onError() {\n var video = queue.front;\n var error = this.error;\n var messageData;\n\n debug.info('%c%s', 'color: #2074c0;', '[video event] error - ', video && video.type, error);\n\n inline.endSpinner();\n\n if (state.lockAirplayChangeEvent) {\n return;\n }\n\n if (error) {\n switch (error.code) {\n case MediaError.MEDIA_ERR_ABORTED:\n case MediaError.MEDIA_ERR_DECODE:\n case MediaError.MEDIA_ERR_NETWORK:\n retry.clearTimer();\n\n exports.queue.emit('show:error', {\n info: {\n code: state.drm ? ERROR_STATUS.UNAVAILABLE_DRM.NAME : ERROR_STATUS.UNAVAILABLE.NAME\n }\n });\n messageData = {\n title: 'videoMediaError',\n code: error.code\n };\n\n helpers.sentry.captureMessage(JSON.stringify(messageData));\n break;\n case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:\n var currentVideo = state.currentVideo;\n var isMediaError = true;\n var videoType = queue.front && queue.front.type;\n\n var errorCode =\n videoType === 'AD'\n ? ERROR_STATUS.UNAVAILABLE_ADCONTENTS.NAME\n : state.drm\n ? ERROR_STATUS.UNAVAILABLE_DRM.NAME\n : ERROR_STATUS.UNAVAILABLE.NAME;\n\n if (videoType === constants.VIDEO_TYPE.AD && currentVideo.skipOnErrorOfAdContents) {\n excuteEnded(isMediaError);\n } else if (\n videoType === constants.VIDEO_TYPE.VOD &&\n state.hls &&\n !state.abrError &&\n currentVideo.videoUrl &&\n helpers.validator.isHlsVideo(currentVideo.videoUrl)\n ) {\n state.hls = false;\n state.abrError = true;\n exports.queue.emit(\n 'loadAndPlay:videoById',\n currentVideo.id,\n currentVideo.profile,\n 0,\n null,\n Object.assign({}, state)\n );\n } else if (!state.abr) {\n exports.queue.emit('show:error', {\n info: {\n code: errorCode\n }\n });\n }\n messageData = {\n title: 'videoMediaErrorSrcNotSupported',\n code: error.code,\n id: currentVideo.id,\n type: videoType,\n videoUrl: currentVideo.videoUrl\n };\n helpers.sentry.captureMessage(JSON.stringify(messageData));\n break;\n }\n } else if (window.navigator.onLine) {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.UNAVAILABLE.NAME\n }\n });\n } else {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.NETWORK_OFFLINE.NAME\n }\n });\n }\n\n if (queue.front && queue.front.type === 'AD') {\n vastTracker.error('403');\n }\n inline.resetAriaAttr();\n }\n\n function onLoadStart() {\n var video = queue.front;\n\n if (!video) {\n return;\n }\n\n if (video.type === constants.VIDEO_TYPE.AD) {\n adController.hideNonLinearAd();\n } else {\n adController.hideLinearAdContainer();\n }\n\n if (ua.platform === 'pc') {\n inlinePC.onLoadStart();\n } else {\n inline.onLoadStart();\n }\n\n debug.info('%c%s', 'color: #2074c0;', '[video event] loadstart');\n }\n\n function onSuspend() {\n debug.info('%c%s', 'color: #2074c0;', '[video event] suspend');\n }\n\n function onEmptied() {\n debug.info('%c%s', 'color: #2074c0;', '[video event] emptied');\n }\n\n function updateProgress() {\n inline.onTimeUpdate(player.getCurrentTime(), player.getDurationRound());\n requestAnimateId = window.requestAnimationFrame(updateProgress);\n }\n\n function clearTimeupdateTimeout() {\n if (timeupdateTimeout) {\n clearTimeout(timeupdateTimeout);\n timeupdateTimeout = null;\n }\n }\n\n function sendOffsetPointUpdate() {\n var currentTime = player.getCurrentTimeRound();\n var offsetPoints = env.offsetPoints;\n var video = queue.front;\n\n if (offsetPoints && offsetPoints[currentTime] && video.type !== constants.VIDEO_TYPE.AD) {\n helpers.sdk.sendEventCallback(constants.PLAYER_CALLBACK_NAME.onOffsetPointUpdate, [currentTime]);\n }\n }\n\n function onBeforeunload() {\n if (queue.front && queue.front.type === 'AD') {\n vastTracker.close();\n }\n }\n\n var listener = {\n addVideoEvent: function(videoEl) {\n event.on(videoEl, 'abort', onAbort);\n event.on(videoEl, 'canplay', onCanPlay);\n event.on(videoEl, 'durationchange', onDurationChange);\n event.on(videoEl, 'emptied', onEmptied);\n event.on(videoEl, 'ended', onEnded);\n event.on(videoEl, 'error', onError);\n event.on(videoEl, 'loadeddata', onLoadedData);\n event.on(videoEl, 'loadedmetadata', onLoadedMetaData);\n event.on(videoEl, 'loadstart', onLoadStart);\n event.on(videoEl, 'pause', onPause);\n event.on(videoEl, 'play', onPlay);\n event.on(videoEl, 'playing', onPlaying);\n event.on(videoEl, 'progress', onProgress);\n event.on(videoEl, 'seeking', onSeeking);\n event.on(videoEl, 'seeked', onSeeked);\n event.on(videoEl, 'suspend', onSuspend);\n event.on(videoEl, 'timeupdate', onTimeUpDate);\n event.on(videoEl, 'volumechange', onVolumeChange);\n event.on(videoEl, 'waiting', onWaiting);\n event.on(window, 'beforeunload', onBeforeunload);\n },\n removeEventListener: function(videoEl) {\n event.off(videoEl, 'abort', onAbort);\n event.off(videoEl, 'canplay', onCanPlay);\n event.off(videoEl, 'durationchange', onDurationChange);\n event.off(videoEl, 'emptied', onEmptied);\n event.off(videoEl, 'ended', onEnded);\n event.off(videoEl, 'error', onError);\n event.off(videoEl, 'loadeddata', onLoadedData);\n event.off(videoEl, 'loadedmetadata', onLoadedMetaData);\n event.off(videoEl, 'loadstart', onLoadStart);\n event.off(videoEl, 'pause', onPause);\n event.off(videoEl, 'play', onPlay);\n event.off(videoEl, 'playing', onPlaying);\n event.off(videoEl, 'progress', onProgress);\n event.off(videoEl, 'seeking', onSeeking);\n event.off(videoEl, 'seeked', onSeeked);\n event.off(videoEl, 'suspend', onSuspend);\n event.off(videoEl, 'timeupdate', onTimeUpDate);\n event.off(videoEl, 'volumechange', onVolumeChange);\n event.off(videoEl, 'waiting', onWaiting);\n\n event.off(window, 'beforeunload', onBeforeunload);\n },\n customEvent: function(sandbox) {\n sandbox.on('video:abort', onAbort);\n sandbox.on('video:canplay', onCanPlay);\n sandbox.on('video:durationchange', onDurationChange);\n sandbox.on('video:emptied', onEmptied);\n sandbox.on('video:ended', onEnded);\n sandbox.on('video:error', onError);\n sandbox.on('video:loadeddata', onLoadedData);\n sandbox.on('video:loadedmetadata', onLoadedMetaData);\n sandbox.on('video:loadstart', onLoadStart);\n sandbox.on('video:pause', onPause);\n sandbox.on('video:play', onPlay);\n sandbox.on('video:playing', onPlaying);\n sandbox.on('video:progress', onProgress);\n sandbox.on('video:seeking', onSeeking);\n sandbox.on('video:seeked', onSeeked);\n sandbox.on('video:suspend', onSuspend);\n sandbox.on('video:timeupdate', onTimeUpDate);\n sandbox.on('video:volumechange', onVolumeChange);\n sandbox.on('video:waiting', onWaiting);\n }\n };\n\n function EventVideo() {}\n\n EventVideo.prototype.init = function(player, sandbox) {\n this.videoEl = player.videoElement;\n listener.addVideoEvent(this.videoEl, sandbox);\n listener.customEvent(sandbox);\n };\n\n EventVideo.prototype.addEventListener = function(videoElement) {\n this.videoEl = videoElement;\n listener.addVideoEvent(this.videoEl);\n };\n\n EventVideo.prototype.removeEventListener = function(videoElement) {\n this.videoEl = videoElement;\n listener.removeEventListener(this.videoEl);\n };\n\n EventVideo.prototype.onEnded = function() {\n excuteEnded(false);\n inline.resetAriaAttr();\n };\n\n return EventVideo;\n })();\n\n exports.addModule('event.video', new EventVideo());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var queue = exports.loadModule('playlist.queue');\n var state = exports.loadModule('controller.state');\n var qoeTracker = exports.loadModule('qoe.tracker');\n var shaka = exports.loadModule('player.shaka');\n var player = exports.loadModule('player.adapter');\n var inlinePC = exports.loadModule('view.inline.pc');\n var inline = exports.loadModule('view.inline');\n var cover = exports.loadModule('view.cover');\n var extension = exports.loadModule('view.extension');\n var completion = exports.loadModule('view.completion');\n var controller = exports.loadModule('controller.video');\n var liveController = exports.loadModule('controller.live');\n var adController = exports.loadModule('controller.ad');\n var eventVideo = exports.loadModule('event.video');\n var action = exports.loadModule('view.action');\n\n var CustomEvent;\n\n CustomEvent = (function() {\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n var ua = exports.ua;\n var ERROR_STATUS = constants.ERROR.STATUS;\n var qoeEvent = constants.QOE.EVENT;\n\n var addListener = function(sandbox) {\n sandbox.on('skip:ad', function() {\n adController.inactivateAdControl();\n\n if (queue.front.type === 'AD' && queue.front.breakId === 'preroll') {\n state.isPrerollEnded = true;\n controller.startNextQueue();\n } else if (queue.front.type === 'AD' && queue.front.breakId === 'midroll') {\n controller.startNextQueue(function() {\n adController.updateMidrollState();\n queue.contents.push(state.currentVideo);\n\n if (state.abr) {\n shaka.attach(player.videoElement).then(controller.startNextQueue);\n } else {\n controller.startNextQueue();\n }\n });\n }\n });\n\n sandbox.on('play:live', function(profile) {\n liveController.preStartVideo(profile);\n debug.log('play:live', profile);\n });\n\n sandbox.on('play:vod', function(profile) {\n controller.preStartVideo(profile);\n debug.log('play:vod', profile);\n });\n\n sandbox.on('load:videoUrl', function(clip, callback) {\n controller.loadVideoResource(clip);\n\n if (callback && typeof callback === 'function') {\n callback();\n }\n debug.log('load:videoUrl', clip);\n });\n\n sandbox.on('load:videoById', function(start, isAutoPlay, password) {\n var id = state.currentVideo.id || env.id;\n var profile = state.abr\n ? constants.DASH_PROFILE[state.currentVideo.profile]\n : state.currentVideo.profile || env.profile;\n\n exports.queue\n .emit('unload:player')\n .then(function() {\n if (player.type === 'VOD') {\n controller.load(id, profile, start, isAutoPlay);\n } else if (player.type === 'LIVE') {\n liveController.load(id, profile, isAutoPlay, password);\n }\n })\n .catch(function(e) {\n debug.error('failed to load video', e);\n });\n\n helpers.debug.tooltip('load:videoById', id, profile, start, isAutoPlay);\n });\n\n sandbox.on('loadAndPlay:videoById', function(id, profile, start, feedbackData, preserveState, isReplay) {\n exports.queue\n .emit('unload:player')\n .then(function() {\n if (player.type === 'VOD') {\n controller.loadAndPlay(id, profile, start, feedbackData, preserveState, isReplay);\n }\n })\n .catch(function(e) {\n debug.error('failed to load&play video', e);\n });\n\n helpers.debug.tooltip('loadAndPlay:videoById', id, profile, start, preserveState, isReplay);\n });\n\n sandbox.on('load:meta', function(info) {\n var metaUrl = info.metaUrl;\n var callback = info.callback;\n\n state.currentVideo.set({ metaUrl: metaUrl });\n controller.fetchMeta().then(callback);\n });\n\n sandbox.on('complete:readyAndPlay', function(result) {\n exports.queue.emit('complete:ready', result);\n exports.queue.emit('complete:play', result);\n debug.info('%c%s', 'color: #20b408', '[custom event] complete readyAndPlay', result);\n });\n\n sandbox.on('complete:ready', function(result) {\n debug.info('%c%s', 'color: #20b408', '[custom event] complete ready', result);\n });\n\n sandbox.on('complete:play', function(result) {\n var data, videoLocation;\n\n if (result.status === 'success') {\n data = result.data;\n videoLocation = data.videoLocation;\n\n if (!videoLocation || !videoLocation.url) {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.UNAVAILABLE.NAME\n }\n });\n }\n }\n debug.info('%c%s', 'color: #20b408', '[custom event] complete play', result);\n });\n\n sandbox.on('complete:meta', function(result) {\n if (result.status === 'success') {\n if (cover) {\n cover.onCompleteMeta();\n }\n\n if (extension) {\n extension.onCompleteMeta();\n }\n\n if (ua.platform === 'pc') {\n inlinePC.onCompleteMeta();\n } else {\n inline.onCompleteMeta();\n }\n\n if (env.rel) {\n exports.queue.emit('create:completion');\n }\n exports.queue.emit('create:contextmenu');\n }\n debug.info('%c%s', 'color: #20b408', '[custom event] complete meta', result);\n });\n sandbox.on('complete:vmap', function(result) {\n var skipOnErrorOfAdApi = state.currentVideo.skipOnErrorOfAdApi;\n var isLive = state.currentVideo.type === constants.VIDEO_TYPE.LIVE;\n var response = result.res;\n\n debug.info('%c%s', 'color: #20b408', '[custom event] complete:vmap', result);\n\n if (result.status === 'success') {\n if (response) {\n adController.resolveVmap(response);\n }\n } else if (result.status === 'error') {\n if (skipOnErrorOfAdApi) {\n adController.inactivateAdControl();\n if (!isLive) {\n controller.readyClipVideo();\n } else {\n liveController.readyLiveVideo();\n }\n } else {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.UNAVAILABLE_ADBLOCK.NAME\n }\n });\n }\n }\n debug.info('%c%s', 'color: #20b408', '[custom event] complete:parse:vmap', result);\n });\n\n sandbox.on('complete:vast', function(result) {\n var response = result.res;\n var request = result.req;\n var skipOnErrorOfAdApi = state.currentVideo.skipOnErrorOfAdApi;\n var isLive = state.currentVideo.type === constants.VIDEO_TYPE.LIVE;\n state.isVastRequesting = false;\n\n if (result.status === 'success') {\n if (response) {\n adController.resolveVast(request, response);\n }\n } else if (result.status === 'error') {\n if (skipOnErrorOfAdApi) {\n adController.inactivateAdControl();\n if (!isLive) {\n controller.readyClipVideo();\n } else {\n liveController.readyLiveVideo();\n }\n } else {\n exports.queue.emit('show:error', {\n info: {\n code: ERROR_STATUS.UNAVAILABLE_ADBLOCK.NAME\n }\n });\n }\n }\n debug.info('%c%s', 'color: #20b408', '[custom event] complete:vast', result);\n });\n\n sandbox.on('complete:location', function(data) {\n debug.info('complete:location', data);\n\n if (data.status === 'success') {\n if (ua.platform === 'pc') {\n inlinePC.changeProfileLabel();\n inlinePC.hideProfileList();\n }\n controller.changeVideoResource();\n }\n\n if (!state.isFirstPlay) {\n player.play();\n }\n\n if (data.callback && typeof data.callback === 'function') {\n data.callback();\n }\n });\n\n sandbox.on('set:videosource', function() {\n debug.info('set:videosource');\n });\n\n sandbox.on('request:fullscreen', function() {\n if (ua.platform === 'pc') {\n inlinePC.hideWide();\n }\n });\n\n sandbox.on('cancel:fullscreen', function() {\n if (env.isInternal && !env.popup && ua.platform === 'pc') {\n inlinePC.showWide();\n }\n });\n\n sandbox.on('layerStatus:check', function() {\n if (inline.isFullScreen()) {\n inline.cancelFullscreen();\n }\n\n inline.hideActivatedControl();\n extension.hideModal();\n });\n\n sandbox.on('show:cover', function() {\n cover.showCover();\n });\n\n sandbox.on('hide:cover', function() {\n cover.hideCover();\n });\n\n sandbox.on('unload:player', function() {\n controller.unload();\n debug.info('[custom event] unload:player');\n });\n\n sandbox.on('window:unload', function() {\n controller.unload();\n debug.info('[custom event] window:unload');\n });\n\n sandbox.on('change:stream', function() {\n var prevProfile = '';\n var currentProfile = '';\n\n if (state.needSetTrack) {\n state.needSetTrack = false;\n shaka.getOutputs(function() {\n shaka.setTrack(state.currentVideo.profile);\n if (ua.platform !== 'pc') {\n extension.setProfile(state.currentVideo.profile);\n inline.setProfile(state.currentVideo.profile);\n }\n });\n } else {\n prevProfile = shaka.getPrevProfile();\n currentProfile = shaka.getCurrentProfile();\n\n if (prevProfile !== currentProfile) {\n qoeTracker.track(qoeEvent.RESOLUTION_CHANGE, {\n l1: prevProfile,\n l2: 'auto',\n rslu: currentProfile\n });\n shaka.setPrevProfile(currentProfile);\n }\n\n if (ua.platform === 'pc') {\n inlinePC.changeProfileLabel();\n } else {\n inline.setProfile(state.currentVideo.profile);\n }\n }\n });\n\n sandbox.on('shaka:buffering', function(buffering) {\n if (buffering) {\n inline.startSpinner();\n if (!dt.StopWatch.has('seek') && !dt.StopWatch.has('startPlay')) {\n dt.StopWatch.start('rebuffering');\n }\n } else {\n inline.endSpinner();\n if (dt.StopWatch.has('rebuffering')) {\n qoeTracker.track(qoeEvent.REBUFFERING, { n1: dt.StopWatch.stop('rebuffering') });\n }\n }\n });\n\n sandbox.on('shaka:error', function() {\n var currentTime = player.getCurrentTime();\n qoeTracker.track(qoeEvent.PLAYBACK_FAIL, { l1: currentTime ? 'middle' : 'initail' });\n qoeTracker.clear();\n });\n\n sandbox.on('addlistener:videoEvent', function(videoElement) {\n eventVideo.addEventListener(videoElement);\n });\n\n sandbox.on('removelistener:videoEvent', function(videoElement) {\n eventVideo.removeEventListener(videoElement);\n });\n\n sandbox.on('onClosed:videoEvent', function() {\n eventVideo.onEnded();\n });\n\n sandbox.on('hide:modal', function() {\n if (!state.ended) {\n completion.hideCompletion();\n }\n });\n\n sandbox.on('spinner:end', function() {\n inline.endSpinner();\n });\n\n sandbox.on('ad:checkMidrollAd', function() {\n adController.checkMidrollAd(true, controller.startNextQueue);\n });\n\n sandbox.on('live:getLocation', function(profile) {\n state.currentVideo.contentType = constants.CONTENT_TYPE.NPP;\n inline.startSpinner();\n inline.getLiveLocation(profile);\n });\n\n sandbox.on('live:updateSetupView', function(profile) {\n inlinePC.updateSetupView(profile);\n });\n\n sandbox.on('load:videoById:withPlayerUnload', function(start, isAutoPlay) {\n exports.queue.emit('load:videoById', start, isAutoPlay);\n });\n\n sandbox.on('loadAndPlay:videoById:withPlayerUnload', function(id, profile, start, feedbackData) {\n exports.queue.emit('loadAndPlay:videoById', id, profile, start, feedbackData);\n });\n\n sandbox.on('loadAndPlay:videoById:replay', function(id, profile, start, preserveState) {\n exports.queue.emit('loadAndPlay:videoById', id, profile, start, null, preserveState, true);\n });\n\n sandbox.on('show:action', function() {\n var video = queue.front;\n\n if (video && video.type !== constants.VIDEO_TYPE.AD) {\n if (!player.isPaused() && state.hasAction && state.isPrerollEnded && !state.modalContentActivated) {\n action.showButton();\n }\n }\n });\n\n sandbox.on('hide:action', function() {\n action.hideButton();\n });\n\n sandbox.on('show:preview', function() {\n inline.showTvod();\n });\n\n sandbox.on('hide:preview', function() {\n inline.hideTvod();\n });\n\n sandbox.on('reset:playList', function() {\n queue.set([]);\n });\n\n sandbox.on('set:defaultOptions', function() {\n controller.setDefaultOptions();\n });\n\n sandbox.on('reset:env:mute', function() {\n env.mute = false;\n });\n };\n\n function CustomEvent() {}\n\n CustomEvent.prototype.init = function(player, sandbox) {\n addListener(sandbox);\n };\n\n return CustomEvent;\n })();\n\n exports.addModule('event.custom', new CustomEvent());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports, dt) {\n 'use strict';\n\n var state = exports.loadModule('controller.state');\n var player = exports.loadModule('player.adapter');\n var adController = exports.loadModule('controller.ad');\n var controller = exports.loadModule('controller.video');\n var castController = exports.loadModule('controller.cast');\n var queue = exports.loadModule('playlist.queue');\n var inline = exports.loadModule('view.inline');\n var cast = exports.loadModule('view.cast');\n var retry = exports.loadModule('view.retry');\n\n var EventCastVideo;\n\n EventCastVideo = (function() {\n var ua = exports.ua;\n var event = dt.event;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var constants = exports.constants;\n\n var currentTime = 0;\n\n var airplayTimer = null;\n\n var airplay = {\n timer: null,\n play: function() {\n if (this.timer) {\n return;\n }\n\n var airplay = this;\n\n this.timer = setInterval(function() {\n var videoElement = player.videoElement;\n var isOnTv = videoElement.webkitCurrentPlaybackTargetIsWireless;\n\n if (isOnTv) {\n setTimeout(function() {\n if (player.isPaused()) {\n player.play();\n if (currentTime > 0) {\n player.seekTo(currentTime);\n }\n } else {\n clearInterval(airplay.timer);\n airplay.timer = null;\n }\n }, 1000);\n }\n }, 1500);\n }\n };\n\n function onConnectedChange(e) {\n var videoType = state.currentVideo && state.currentVideo.type;\n var isConnected = e.value;\n\n debug.log('[Remote Event] IS_CONNECTED_CHANGED: ', videoType, e);\n\n if (!state.currentVideo) {\n castController.resetCastPlayer();\n castController.registerRemoteEventListener(removeRemoteEventListener);\n return;\n }\n\n if (videoType === constants.VIDEO_TYPE.LIVE && isConnected) {\n castController.loadRemotePlayerForLive();\n return;\n } else if (videoType === constants.VIDEO_TYPE.LIVE) {\n castController.cancelRemotePlayerForLive();\n return;\n }\n\n if (isConnected) {\n castController.loadRemotePlayer();\n return;\n }\n\n castController.cancelRemotePlayer(currentTime);\n }\n\n function onPlayerStateChange(e) {\n debug.log('[Remote Event] PLAYER_STATE_CHANGED: ', e);\n\n var remoteState = e.value;\n var mediaState = castController.getMediaState();\n\n if (remoteState === mediaState.PLAYING) {\n inline.endSpinner();\n exports.queue.emit('video:playing');\n exports.queue.emit('video:play');\n }\n }\n\n function onIsPausedChange(e) {\n debug.log('[Remote Event] IS_PAUSED_CHANGED: ', e);\n var isPaused = e.value;\n\n if (isPaused) {\n exports.queue.emit('video:pause');\n } else {\n exports.queue.emit('video:play');\n }\n }\n\n function onCurrentTimeChange(e) {\n debug.log('[Remote Event] CURRENT_TIME_CHANGED: ', e);\n\n var video = queue.front;\n var remoteCurrentTime = e.value;\n var playerCurrentTime = player.getCurrentTimeRound();\n var playerDuration = player.getDurationRound();\n var isEnded = playerDuration && playerCurrentTime === playerDuration;\n var isSeeked = false;\n\n if (playerCurrentTime !== 0 && playerCurrentTime !== currentTime + 1) {\n isSeeked = true;\n }\n\n inline.endSpinner();\n\n if (isEnded) {\n debug.log('[Remote Event] IS_MEDIA_LOADED_CHANGED - ENDED: ', video.type, currentTime, playerDuration);\n var ended = exports.queue.emit('onClosed:videoEvent');\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n exports.queue.emit('video:timeupdate');\n } else {\n currentTime = 0;\n ended.then(function() {\n player.stop();\n\n if (state.currentVideo.type === constants.VIDEO_TYPE.VOD) {\n state.ended = true;\n castController.registerRemoteEventListener(removeRemoteEventListener);\n castController.cancelRemotePlayer();\n } else if (state.currentVideo.type === constants.VIDEO_TYPE.LIVE) {\n castController.cancelRemotePlayerForLive();\n }\n });\n }\n }\n\n if (isSeeked && video.type === constants.VIDEO_TYPE.VOD) {\n if (playerCurrentTime === 0 || playerCurrentTime === currentTime) {\n return;\n }\n\n debug.log('[Remote Event] SEEKED: ', playerCurrentTime, currentTime);\n\n currentTime = playerCurrentTime;\n\n if (!state.ended) {\n if (!state.pausedBeforeSeek) {\n player.play();\n if (player.isPaused()) {\n state.needMidrollRequest = true;\n } else {\n adController.checkMidrollAd(true, controller.startNextQueue);\n }\n } else {\n state.needMidrollRequest = true;\n }\n }\n return;\n }\n\n if (remoteCurrentTime > 0 && video.type !== constants.VIDEO_TYPE.AD) {\n currentTime = playerCurrentTime;\n exports.queue.emit('video:timeupdate');\n }\n\n if (player.isPaused()) {\n retry.clearTimer();\n }\n }\n\n function onIsMedeaLoadedChange(e) {\n debug.log('[Remote Event] IS_MEDIA_LOADED_CHANGED: ', e, currentTime);\n var isLoaded = e.value;\n\n if (isLoaded) {\n exports.queue.emit('video:loadstart');\n exports.queue.emit('video:loadeddata');\n exports.queue.emit('video:canplay');\n }\n }\n\n function onDurationChange(e) {\n debug.log('[Remote Event] DURATION_CHANGED: ', e);\n exports.queue.emit('video:durationchange');\n }\n\n function onVolumeChange(e) {\n debug.log('[Remote Event] VOLUME_LEVEL_CHANGED: ', e);\n }\n\n function onMutedChange(e) {\n debug.log('[Remote Event] IS_MUTED_CHANGED: ', e);\n }\n\n function registerRemoteEventListener(remoteController) {\n setRemoteEventListener(remoteController);\n }\n\n function removeRemoteEventListener(remoteController) {\n setRemoteEventListener(remoteController, true);\n }\n\n function setRemoteEventListener(remoteController, isRemoving) {\n var remoteEventType = castController.getRemoteEventType();\n var eventListenerMethod = event.on;\n\n if (isRemoving) {\n eventListenerMethod = event.off;\n }\n\n eventListenerMethod(remoteController, remoteEventType.IS_CONNECTED_CHANGED, onConnectedChange);\n eventListenerMethod(remoteController, remoteEventType.PLAYER_STATE_CHANGED, onPlayerStateChange);\n eventListenerMethod(remoteController, remoteEventType.IS_PAUSED_CHANGED, onIsPausedChange);\n eventListenerMethod(remoteController, remoteEventType.CURRENT_TIME_CHANGED, onCurrentTimeChange);\n eventListenerMethod(remoteController, remoteEventType.IS_MEDIA_LOADED_CHANGED, onIsMedeaLoadedChange);\n eventListenerMethod(remoteController, remoteEventType.DURATION_CHANGED, onDurationChange);\n eventListenerMethod(remoteController, remoteEventType.VOLUME_LEVEL_CHANGED, onVolumeChange);\n eventListenerMethod(remoteController, remoteEventType.IS_MUTED_CHANGED, onMutedChange);\n }\n\n function onChangeAirplayDisplay() {\n var video = queue.front;\n var videoElement = player.videoElement;\n var isOnTv = videoElement.webkitCurrentPlaybackTargetIsWireless;\n\n debug.log(\n '[AirPlay Event] Change Display',\n ', isDash: ',\n state.abr,\n ', isTv: ',\n isOnTv,\n ', lockAirplayChangeEvent: ',\n state.lockAirplayChangeEvent\n );\n\n if (isOnTv) {\n cast.showConnected();\n } else {\n cast.showDisconnected();\n }\n\n castController.hideMenuOnCast(true);\n\n if (state.lockAirplayChangeEvent) {\n return;\n } else {\n state.lockAirplayChangeEvent = true;\n }\n\n player.pause();\n\n if (video && video.type === constants.VIDEO_TYPE.AD) {\n return;\n } else {\n currentTime = player.getCurrentTimeRound();\n }\n\n if (!state.abr || airplayTimer || state.isFirstPlay) {\n return;\n }\n\n castController.convertSrcMode();\n }\n\n function registerAirplayEventListener() {\n var videoElement = player.videoElement;\n var airPlayDisplayChangeEvent = 'webkitcurrentplaybacktargetiswirelesschanged';\n\n event.on(videoElement, airPlayDisplayChangeEvent, onChangeAirplayDisplay);\n }\n\n var listener = {\n videoEvent: function() {\n if (ua.platform !== 'pc') {\n return;\n }\n\n window['__onGCastApiAvailable'] = function(isAvailable) {\n try {\n if (isAvailable) {\n cast.showBox();\n cast.showChromecastBox();\n } else {\n cast.hideBox();\n cast.hideChromecastBox();\n }\n } catch (e) {\n debug.warn('Chromecast failed to load: ', e);\n }\n };\n\n if (window.WebKitPlaybackTargetAvailabilityEvent) {\n registerAirplayEventListener();\n var videoElement = player.videoElement;\n\n videoElement.addEventListener('canplay', function() {\n var isOnTv = videoElement.webkitCurrentPlaybackTargetIsWireless;\n state.lockAirplayChangeEvent = false;\n\n if (isOnTv) {\n inline.endSpinner();\n airplay.play();\n }\n });\n }\n },\n customEvent: function(sandbox) {\n sandbox.on('create:cast:connector', function() {\n try {\n castController.create();\n castController.registerRemoteEventListener(registerRemoteEventListener);\n } catch (e) {\n debug.log('Failed create cast connector: ', e);\n }\n });\n }\n };\n\n function EventCastVideo() {}\n\n EventCastVideo.prototype.init = function(player, sandbox) {\n this.videoEl = player.videoElement;\n listener.videoEvent(this.videoEl, sandbox);\n listener.customEvent(sandbox);\n };\n\n return EventCastVideo;\n })();\n\n exports.addModule('event.video.cast', new EventCastVideo());\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet), window.daumtools);\n\n(function(exports) {\n 'use strict';\n\n var helpers = exports.helpers;\n\n function sendEventCallback(eventName, args) {\n helpers.sdk.sendEventCallback(eventName, args);\n }\n\n function BaseApiAdapter() {}\n\n BaseApiAdapter.prototype = {\n load: function() {},\n loadAndPlay: function() {},\n play: function() {},\n pause: function() {},\n stop: function() {},\n seekTo: function() {},\n mute: function() {},\n unMute: function() {},\n setVolume: function() {},\n getDuration: function() {},\n increaseUpCnt: function() {},\n setListPlayMode: function() {},\n setRepeatMode: function() {},\n setVerticalMode: function() {},\n setAutoplayVisible: function() {},\n setContinuousPlay: function() {},\n unsetVerticalMode: function() {},\n popupUrl: function() {},\n setBeaconData: function() {},\n changeScreenType: function() {},\n setAutoPlayMode: function() {},\n setWideScreenMode: function() {},\n requestFullScreen: function() {},\n cancelFullScreen: function() {},\n changeOrientation: function() {},\n setCallback: function() {},\n fireEvent: function(eventName, args) {\n sendEventCallback(eventName, args);\n },\n checkInited: function() {\n helpers.sendOnAlreadyInited();\n }\n };\n\n function FlashVodApiAdapter() {}\n\n FlashVodApiAdapter.prototype = new BaseApiAdapter();\n FlashVodApiAdapter.prototype.loadAndPlay = function(id) {\n window.daumVodPlayerPlay(id);\n };\n FlashVodApiAdapter.prototype.play = function() {\n window.daumVodPlayerVideoPlay(true);\n };\n FlashVodApiAdapter.prototype.pause = function() {\n window.daumVodPlayerVideoPause(true);\n };\n FlashVodApiAdapter.prototype.seekTo = function(sec) {\n window.daumVodPlayerSeek(sec);\n };\n FlashVodApiAdapter.prototype.setVolume = function(number) {\n window.daumVodPlayerSetVolume(number * 100);\n };\n FlashVodApiAdapter.prototype.getDuration = function() {\n return window.daumVodPlayerPlayDuration();\n };\n /**\n * @deprecated\n */\n FlashVodApiAdapter.prototype.increaseUpCnt = function() {\n window.daumVodPlayerIncreaseUpCnt();\n };\n FlashVodApiAdapter.prototype.setListPlayMode = function(isListPlay) {\n window.daumVodPlayerListPlayMode(isListPlay);\n };\n FlashVodApiAdapter.prototype.setRepeatMode = function(type) {\n window.daumVodPlayerRepeatMode(type);\n };\n FlashVodApiAdapter.prototype.setVerticalMode = function() {\n window.daumVodPlayerSetVerticalMode();\n };\n FlashVodApiAdapter.prototype.unsetVerticalMode = function() {\n window.daumVodPlayerUnsetVerticalMode();\n };\n FlashVodApiAdapter.prototype.popupUrl = function(url) {\n window.popupBydaumVodPlayer(url);\n };\n FlashVodApiAdapter.prototype.changeScreenType = function(screenType) {\n window.changeScreenType(screenType);\n };\n FlashVodApiAdapter.prototype.setCallback = function(callbacks) {\n if (window.apiMessenger) {\n window.apiMessenger.setCallback(callbacks);\n }\n };\n\n function Html5PlayerAdapter(player) {\n this.player = player;\n }\n\n Html5PlayerAdapter.prototype = new BaseApiAdapter();\n\n Html5PlayerAdapter.prototype.load = function(id, profile, start) {\n this.player.load(id, profile, start);\n };\n Html5PlayerAdapter.prototype.loadAndPlay = function(id, profile, start) {\n this.player.loadAndPlay(id, profile, start);\n };\n Html5PlayerAdapter.prototype.play = function(profile) {\n this.player.play(profile);\n };\n Html5PlayerAdapter.prototype.pause = function() {\n this.player.pause();\n };\n Html5PlayerAdapter.prototype.stop = function() {\n this.player.stop();\n };\n Html5PlayerAdapter.prototype.seekTo = function(sec) {\n this.player.seekTo(sec);\n };\n Html5PlayerAdapter.prototype.setVolume = function(number) {\n this.player.setVolume(number);\n };\n Html5PlayerAdapter.prototype.mute = function() {\n this.player.setMute(true);\n };\n Html5PlayerAdapter.prototype.unMute = function() {\n this.player.setMute(false);\n };\n Html5PlayerAdapter.prototype.getDuration = function() {\n this.player.getDuration();\n };\n Html5PlayerAdapter.prototype.setBeaconData = function(beaconData) {\n this.player.setBeaconData(beaconData);\n };\n Html5PlayerAdapter.prototype.setAutoPlayMode = function(isAutoPlay) {\n this.player.setAutoPlayMode(isAutoPlay);\n };\n Html5PlayerAdapter.prototype.setNextVideo = function(clipLinkId) {\n this.player.setNextVideo(clipLinkId);\n };\n Html5PlayerAdapter.prototype.setContinuousPlay = function(isContinuousPlay) {\n this.player.setContinuousPlay(isContinuousPlay);\n };\n Html5PlayerAdapter.prototype.setAutoplayVisible = function(visibility) {\n this.player.setAutoplayVisible(visibility);\n };\n\n Html5PlayerAdapter.prototype.setPlaybackRate = function(rate) {\n this.player.setPlaybackRate(rate);\n };\n\n Html5PlayerAdapter.prototype.setWideScreenMode = function(isWideScreen) {\n this.player.setWideScreenMode(isWideScreen);\n };\n\n Html5PlayerAdapter.prototype.requestFullScreen = function() {\n this.player.requestFullScreen();\n };\n\n Html5PlayerAdapter.prototype.cancelFullScreen = function() {\n this.player.cancelFullScreen();\n };\n\n Html5PlayerAdapter.prototype.changeOrientation = function(data) {\n this.player.changeOrientation(data);\n };\n\n Html5PlayerAdapter.prototype.setCallback = function(callbacks) {\n if (window.apiMessenger) {\n window.apiMessenger.setCallback(callbacks);\n }\n };\n\n function registerApiAdapter(apiAdapter) {\n window.API = apiAdapter;\n }\n\n function registerApiMessenger(usePostMessage) {\n window.apiMessenger = (function() {\n var _callbacks = null;\n\n function sendMessage(message) {\n try {\n if (window.postMessage && usePostMessage && window !== parent) {\n parent.postMessage(JSON.stringify(message), '*');\n }\n } catch (e) {}\n }\n\n function receiveMessage(e) {\n var data = e.data;\n try {\n data = JSON.parse(data);\n } catch (e) {\n return;\n }\n\n var action = data.action;\n var args = data.args;\n\n if (window.API && typeof window.API[action] === 'function') {\n if (Array.isArray(args)) {\n window.API[action].apply(window.API, args);\n } else {\n window.API[action].call(window.API, args);\n }\n }\n }\n\n if (window.addEventListener) {\n window.addEventListener('message', receiveMessage);\n } else if (window.attachEvent) {\n window.attachEvent('onmessage', receiveMessage);\n }\n\n return {\n setCallback: function(callbacks) {\n _callbacks = callbacks;\n },\n sendCallback: function(callbackName, args) {\n var name = null;\n\n if (typeof callbackName === 'function') {\n name = callbackName.name;\n } else {\n name = callbackName;\n }\n\n if (_callbacks) {\n if (typeof _callbacks[name] === 'function') {\n if (typeof args !== 'undefined') {\n _callbacks[name].apply(window, args);\n } else {\n _callbacks[name].apply(window);\n }\n }\n } else {\n sendMessage({\n action: name,\n args: args\n });\n }\n }\n };\n })();\n }\n\n window.FlashVodApiAdapter = FlashVodApiAdapter;\n window.Html5PlayerAdapter = Html5PlayerAdapter;\n window.registerApiAdapter = registerApiAdapter;\n window.registerApiMessenger = registerApiMessenger;\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n\n(function(exports) {\n 'use strict';\n\n var Player = (window.Player = function(videoElement, playerSetting) {\n this.init(videoElement, playerSetting);\n });\n\n Player.prototype = (function() {\n var html5 = exports.loadModule('player.html5');\n var controller = exports.loadModule('controller.video');\n var liveController = exports.loadModule('controller.live');\n var queue = exports.loadModule('playlist.queue');\n\n var ua = exports.ua;\n var constants = exports.constants;\n var helpers = exports.helpers;\n var debug = helpers.debug;\n var env = exports.ENV;\n\n var PROFILE_KEY = constants.STORAGE.PROFILE;\n var ABR_KEY = constants.STORAGE.ABR;\n\n function createPlayer() {\n debug.info('video type:', this.type);\n\n if (ua.platform === 'pc') {\n if ((ua.browser.msie && ua.browser.version.major < 9) || this.type === 'LIVE') {\n // player = controller.getFlashPlayer();\n } else {\n return html5;\n }\n } else {\n return html5;\n }\n }\n\n function initModules(player) {\n exports.init(player);\n }\n\n function profileCheck(config, paramProfile) {\n var defaultProfile = config.profile;\n var forceProfile = config.forceProfile;\n var storeProfile = helpers.store.get(PROFILE_KEY);\n var storeABR = helpers.store.get(ABR_KEY);\n var profile = '';\n\n if (defaultProfile === constants.PROFILE.AUTO && storeABR !== 'false' && !forceProfile) {\n return defaultProfile;\n } else {\n profile = forceProfile || storeProfile || defaultProfile || paramProfile || constants.PROFILE.BASE;\n if (!helpers.feature.supportsVideoProfile(profile)) {\n helpers.sentry.captureMessage('This profile is not available. profile = ' + profile);\n profile = constants.PROFILE.BASE;\n }\n }\n\n return profile;\n }\n\n function initInstanceDomain() {\n if (document.domain) {\n if (document.domain.indexOf('kakao.com') > -1) {\n document.domain = 'kakao.com';\n } else if (document.domain.indexOf('daum.net') > -1) {\n document.domain = 'daum.net';\n }\n }\n }\n\n return {\n init: function(videoElement, setting) {\n if (!(videoElement.tagName && videoElement.tagName.toLowerCase() === 'video')) {\n debug.log('video element is not exists, please check parameter for video element ');\n return;\n }\n\n this.videoElement = videoElement;\n this.env = setting.env || {};\n this.type = setting.type || constants.VIDEO_TYPE.VOD;\n this.html5 = createPlayer.bind(this)();\n\n initModules(this);\n initInstanceDomain();\n\n if (env.offsetPoints && typeof env.offsetPoints === 'string') {\n var offsetPoints = {};\n\n env.offsetPoints.split(',').forEach(function(point) {\n offsetPoints[point] = true;\n });\n\n env.offsetPoints = offsetPoints;\n }\n\n window.registerApiAdapter(new window.Html5PlayerAdapter(this));\n\n debug.info('player type:', this.type);\n debug.info('player platform:', ua.platform);\n\n return this;\n },\n loadAndPlay: function(id, profile, start) {\n this.profile = profileCheck(this.env, profile);\n\n if (this.type === 'VOD') {\n controller.loadAndPlay(id, this.profile, start);\n } else if (this.type === 'LIVE') {\n liveController.loadAndPlay(id, this.profile);\n }\n },\n load: function(id, profile, start) {\n this.profile = profileCheck(this.env, profile);\n\n if (this.type === 'VOD') {\n controller.load(id, this.profile, start);\n } else if (this.type === 'LIVE') {\n liveController.load(id, this.profile);\n }\n },\n play: function(profile) {\n this.profile = this.env.profile || profile || constants.PROFILE.BASE;\n\n if (this.type === 'VOD') {\n controller.play(this.profile);\n } else if (this.type === 'LIVE') {\n liveController.play(this.profile);\n }\n },\n pause: function() {\n controller.pause();\n },\n stop: function() {\n controller.stop();\n },\n seekTo: function(sec) {\n if (!queue.front) {\n debug.warn('seekTo function only working after play');\n return;\n }\n\n if (queue.front.type === constants.VIDEO_TYPE.AD && helpers.env.isProd()) {\n debug.warn('seekTo function only working on vod or live', helpers.env.isProd());\n return;\n }\n controller.seekTo(sec);\n },\n getDuration: function() {\n return controller.getDuration();\n },\n setVolume: function(number) {\n if (!queue.front) {\n debug.warn('setVolume function only working after play');\n return;\n }\n\n if (queue.front.type === constants.VIDEO_TYPE.AD) {\n debug.warn('setVolume function only working on vod or live');\n return;\n }\n\n if (ua.platform !== 'pc') {\n debug.warn('setVolume function only working on PC');\n return;\n }\n\n this.setMute(false);\n controller.setVolume(number);\n },\n setMute: function(muteOn) {\n controller.setMute(muteOn);\n },\n setAutoPlayMode: function(isAutoPlay) {\n controller.setAutoPlayMode(isAutoPlay);\n },\n setNextVideo: function(clipLinkId) {\n controller.setNextVideo(clipLinkId);\n },\n setContinuousPlay: function(isContinuousPlay) {\n controller.setContinuousPlay(isContinuousPlay);\n },\n setAutoplayVisible: function(visiblility) {\n controller.setAutoplayVisible(visiblility);\n },\n setBeaconData: function(beacon) {\n controller.setBeaconData(beacon);\n },\n setPlaybackRate: function(rate) {\n controller.setPlaybackRate(rate);\n },\n setWideScreenMode: function(isWideScreen) {\n controller.setWideScreenMode(isWideScreen);\n },\n cancelFullScreen: function() {\n controller.cancelFullScreen();\n },\n changeOrientation: function(data) {\n exports.queue.emit('change:orientation', data);\n }\n };\n })();\n})((window.monet = typeof window.monet === 'undefined' ? {} : window.monet));\n"],"names":["Function","prototype","bind","oThis","this","TypeError","self","args","Array","slice","call","arguments","apply","concat","classList","window","daumtools","document","documentElement","has","el","cname","assertElement","contains","add","remove","toggle","className","lastIndexOf","replace","method","Error","exports","initializing","fnTest","test","xyz","Class","extend","prop","name","_super","fn","tmp","ret","init","constructor","callee","createElement","createElementNS","view","classListProp","protoProp","elemCtrProto","Element","objCtr","Object","strTrim","String","trim","arrIndexOf","indexOf","item","i","len","length","DOMEx","type","message","code","DOMException","checkTokenAndGetIndex","token","ClassList","elem","trimmedClasses","getAttribute","classes","split","push","_updateClassName","setAttribute","toString","classListProto","classListGetter","tokens","l","updated","index","splice","force","result","replacement_token","join","defineProperty","classListPropDesc","get","enumerable","configurable","ex","undefined","number","__defineGetter__","createMethod","_toggle","testElement","original","DOMTokenList","matches","msMatchesSelector","webkitMatchesSelector","closest","s","parentElement","parentNode","nodeType","Observable","on","event","listener","events","addListener","getListeners","once","onetimeListener","__onetime_listener","off","emit","_emit","cloneListeners","e","console","error","listeners","removeListener","__original__","destroy","offset","x","offsetLeft","y","offsetTop","offsetNode","offsetParent","body","setVersion","versionString","version","versions","info","major","minor","patch","checkPlatform","ua","match","navigator","maxTouchPoints","isTablet","isArray","arg","baseAppList","userAgent","customAppList","browser","lowerUa","toLowerCase","exec","platform","os","app","checkAppList","appname","RegExp","isApp","checkApp","ua_result","util","dest","src","overwrite","key","hasOwnProperty","addEventListener","attachEvent","removeEventListener","detachEvent","preventDefault","ev","returnValue","stopPropagation","cancelBubble","getTarget","target","srcElement","$","id","getElementById","Sizzle","$$","jQuery","find","select","start","querySelectorAll","delegate","selector","assert","currentTarget","targets","EventUtil","point","minus","aPoint","GestureSession","lastSession","startPosX","startPosY","gestureThreshold","flickThreshold","direction","startPos","delta","targetEvent","term","startTime","Date","isSwipe","isScroll","isLeft","isRight","isUp","isDown","isFlick","getTerm","isTab","isDoubleTab","checkDoubleTab","getTime","recognizeGesture","Math","abs","checkFlick","START","MOVE","END","listen","unListen","getX","touches","pageX","clientX","getY","pageY","clientY","GestureListener","session","gestureHandlers","onGestureStart","onGestureMove","onGetstureEnd","onMoveGesture","onEndGesture","onGestureEnd","onStartGesture","gesture","emptyFn","hasUserAgent","uaString","OrientationManager","availOrientationChange","availResize","orientationManager","orientList","state","getOrientation","bindEvent","resize","onOrientationChange","setInterval","currentState","emitOrientation","screen","width","height","clientWidth","clientHeight","addOrientationCallback","callback","Orientation","onPortraitCallback","onLandscapeCallback","onOrientationCallback","orientation","updateOrientation","onPortrait","onLandscape","methods","buffer","realMethod","log","namespace","__CONSOLE_NAMESPACE","__CONSOLE_QUIET","dumpLog","replayLog","forEach","factory","module","define","amd","applyFocusVisiblePolyfill","scope","hadKeyboardEvent","hadFocusVisibleRecently","hadFocusVisibleRecentlyTimeout","inputTypesWhitelist","text","search","url","tel","email","password","date","month","week","time","datetime","datetime-local","isValidFocusTarget","nodeName","addFocusVisibleClass","onPointerDown","addInitialPointerMoveListeners","onInitialPointerMove","metaKey","altKey","ctrlKey","activeElement","visibilityState","tagName","readOnly","isContentEditable","hasAttribute","clearTimeout","setTimeout","removeAttribute","Node","DOCUMENT_FRAGMENT_NODE","host","DOCUMENT_NODE","CustomEvent","createEvent","initCustomEvent","dispatchEvent","nowOffset","performance","now","timing","navigationStart","lastTime","vendors","requestAnimationFrame","cancelAnimationFrame","currTime","timeToCall","max","moveToStore","storeURL","location","href","deferFallback","timeout","fallback","clickedAt","isPageVisible","INTERVAL","attrNames","launchAppViaHiddenIframe","urlScheme","iframe","style","border","display","overflow","appendChild","TIMEOUT_IOS","TIMEOUT_ANDROID","intentNotSupportedBrowserList","web2app","context","launchURI","blackListRegexp","willInvokeApp","onAppMissing","onUnsupportedEnvironment","move","top","android","supportsIntent","chrome","intentURI","useUrlScheme","ios","universalLink","tid","parseInt","clear","classListAll","dataset","node","attr","value","set","root","installedModules","__webpack_require__","m","modules","_typeof","Symbol","iterator","obj","_createClass","Constructor","protoProps","staticProps","defineProperties","props","descriptor","writable","_clipboardAction2","_interopRequireDefault","_tinyEmitter2","_goodListener2","__esModule","default","Clipboard","_Emitter","_inherits","subClass","superClass","trigger","options","_this","ReferenceError","_possibleConstructorReturn","__proto__","getPrototypeOf","resolveOptions","listenClick","create","setPrototypeOf","action","defaultAction","defaultTarget","defaultText","container","_this2","onClick","delegateTarget","clipboardAction","emitter","getAttributeValue","querySelector","actions","support","queryCommandSupported","suffix","element","attribute","_select","_select2","ClipboardAction","selectedText","selectFake","selectTarget","isRTL","yPosition","removeFake","fakeHandlerCallback","fakeHandler","fakeElem","fontSize","padding","margin","position","pageYOffset","scrollTop","copyText","removeChild","succeeded","execCommand","err","handleResult","clearSelection","focus","getSelection","removeAllRanges","_action","_target","initSelection","selection","range","isReadOnly","setSelectionRange","createRange","selectNodeContents","addRange","E","ctx","_","data","evtArr","evts","liveEvents","is","string","nodeList","HTMLElement","_delegate","useCapture","listenerFn","elements","map","proto","matchesSelector","mozMatchesSelector","oMatchesSelector","c","d","getter","o","r","toStringTag","t","mode","ns","n","object","property","p","moduleId","getDevicePixelRatio","ratio","systemXDPI","logicalXDPI","devicePixelRatio","isNotFiredLoadEvent","monet","fireLoadEvent","queue","group","groupEnd","warn","disableLoadEvent","persisted","me","_elementStyle","_vendor","appVersion","_transform","rAF","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","utils","substr","addEvent","capture","removeEvent","prefixPointerEvent","pointerEvent","MSPointerEvent","charAt","toUpperCase","momentum","current","lowerMargin","wrapperSize","deceleration","distance","speed","duration","destination","round","_prefixStyle","hasTransform","hasPerspective","hasTouch","hasPointer","PointerEvent","hasTransition","isBadAndroid","safariVersion","parseFloat","transform","transitionTimingFunction","transitionDuration","transitionDelay","transformOrigin","touchAction","hasClass","addClass","newclass","removeClass","re","left","preventDefaultException","exceptions","eventType","touchstart","touchmove","touchend","mousedown","mousemove","mouseup","pointerdown","pointermove","pointerup","MSPointerDown","MSPointerMove","MSPointerUp","ease","quadratic","k","circular","sqrt","back","bounce","elastic","pow","sin","f","PI","tap","eventName","initEvent","click","MouseEvent","detail","screenX","screenY","shiftKey","button","relatedTarget","_constructed","getTouchAction","eventPassthrough","addPinch","getRect","rect","SVGElement","getBoundingClientRect","offsetWidth","offsetHeight","IScroll","wrapper","scroller","children","scrollerStyle","resizeScrollbars","mouseWheelSpeed","snapThreshold","disablePointer","disableTouch","disableMouse","startX","startY","scrollY","directionLockThreshold","bounceTime","bounceEasing","HWCompositing","useTransition","useTransform","bindToWrapper","onmousedown","translateZ","scrollX","freeScroll","resizePolling","shrinkScrollbars","invertWheelDirection","probeType","directionX","directionY","_events","_init","refresh","scrollTo","enable","createDefaultScrollbar","interactive","scrollbar","indicator","cssText","pointerEvents","Indicator","wrapperStyle","indicatorStyle","listenX","listenY","defaultScrollbars","shrink","fade","speedRatioX","speedRatioY","durationProp","sizeRatioX","sizeRatioY","maxPosX","maxPosY","opacity","_initEvents","scrollbars","indicators","_initIndicators","mouseWheel","_initWheel","snap","_initSnap","keyBindings","_initKeys","resizeTimeout","_execEvent","_transitionEnd","isInTransition","_transitionTime","resetPosition","_start","which","enabled","initiated","moved","distX","distY","directionLocked","pos","getComputedPosition","_translate","isAnimating","absStartX","absStartY","pointX","pointY","_move","absDistY","deltaX","deltaY","timestamp","absDistX","endTime","hasHorizontalScroll","hasVerticalScroll","newX","newY","maxScrollX","maxScrollY","_end","changedTouches","distanceX","distanceY","easing","flick","momentumX","wrapperWidth","momentumY","wrapperHeight","_nearestSnap","currentPage","snapSpeed","min","_resize","that","disable","scrollerWidth","scrollerHeight","wrapperOffset","scrollBy","transitionType","_transitionTimingFunction","_animate","scrollToElement","offsetX","offsetY","wrapperRect","elRect","transitionTime","updatePosition","matrix","getComputedStyle","interactiveScrollbars","customStyle","fadeScrollbars","_indicatorsMap","wheelTimeout","_wheel","wheelDeltaX","wheelDeltaY","deltaMode","wheelDelta","goToPage","cx","cy","stepX","snapStepX","stepY","snapStepY","pages","snapThresholdX","snapThresholdY","posX","posY","next","prev","keys","pageUp","pageDown","end","home","up","right","down","charCodeAt","_key","prevTime","keyTime","keyAcceleration","keyCode","destX","destY","easingFn","destTime","step","handleEvent","fadeTimeout","lastPointX","lastPointY","_pos","bottom","indicatorWidth","minBoundaryX","maxBoundaryX","indicatorHeight","minBoundaryY","maxBoundaryY","ignoreBoundaries","val","hold","delay","visible","global","ProgressBar","u","a","require","1","mockTweenable","Tweenable","R_NUMBER_COMPONENT","R_FORMAT_CHUNKS","R_UNFORMATTED_VALUES","R_RGB","R_RGB_PREFIX","R_HEX","VALUE_PLACEHOLDER","hexToRGBArray_returnArray","getValuesList_accumulator","formula","DEFAULT_SCHEDULE_FUNCTION","timeoutHandler_currentTime","timeoutHandler_isEnded","timeoutHandler_offset","_now","SHIFTY_DEBUG_NOW","noop","each","shallowCopy","targetObj","srcObj","defaults","tweenProps","forPosition","originalState","targetState","normalizedPosition","easingObjectProp","tweenProp","easingFunc","applyFilter","tweenable","filterName","filters","filter","_filterArgs","timeoutHandler","schedule","opt_currentTimeOverride","timeoutHandler_endTime","isPlaying","_attachment","stop","_scheduleId","_timeoutHandler","composeEasingObject","fromTweenParams","composedEasing","typeofEasing","opt_initialState","opt_config","_currentState","_configured","_scheduleFunction","setConfig","mozCancelRequestAnimationFrame","tween","_isTweening","_timestamp","resume","config","attachment","_pausedAtTime","_delay","_step","_finish","finish","_duration","from","_originalState","_targetState","to","_easing","pause","_isPaused","seek","millisecond","currentTime","gotoEnd","webkitCancelAnimationFrame","oCancelAnimationFrame","msCancelAnimationFrame","setScheduleFunction","scheduleFunction","dispose","linear","cubicBezierAtTime","p1x","p1y","p2x","p2y","ax","bx","ay","by","sampleCurveX","fabs","epsilon","t0","t1","t2","x2","d2","sampleCurveDerivativeX","solveCurveX","sanitizeObjectForHexProps","stateObject","currentProp","filterStringChunks","convertHexToRGB","hexString","rgbArr","hex","hexToDec","hexToRGBArray","pattern","unfilteredString","pattenMatches","filteredString","currentChunk","pattenMatchesLength","shift","sanitizeRGBChunk","rgbChunk","numbers","numbersLength","sanitizedString","getFormatManifests","manifestAccumulator","rawValues","chunks","getValuesFrom","formatString","formattedString","unshift","chunkNames","prefix","accumulator","rawValuesLength","getFormatChunksFrom","expandFormattedProperties","formatManifests","collapseFormattedProperties","valuesList","chunkNamesLength","getValuesList","currentChunkName","extractedValues","extractPropertyChunks","formattedValueString","toFixed","getFormattedValues","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","cos","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeOutBounce","easeInBack","easeOutBack","easeInOutBack","swingFromTo","swingFrom","swingTo","bouncePast","easeFromTo","easeFrom","easeTo","setBezierFunction","x1","y1","y2","cubicBezierTransition","displayName","unsetBezierFunction","interpolate","opt_delay","easingObject","filterArgs","interpolatedValues","source","tweenCreated","fromState","toState","_tokenData","beforeTween","tokenData","chunkLength","easingChunks","lastEasingChunk","afterTween","firstEasing","composedEasingString","2","Circle","_pathTemplate","containerAspectRatio","Shape","_pathString","opts","widthOfWider","strokeWidth","trailWidth","render","radius","2radius","_trailString","./shape","./utils","3","Line","_initializeSvg","svg","center","4","SemiCircle","Path","./circle","./line","./path","./semicircle","5","path","isString","_opts","_tweenable","getTotalLength","strokeDasharray","EASING_ALIASES","easeIn","easeOut","easeInOut","_getComputedDashOffset","progress","strokeDashoffset","_progressToOffset","isFunction","_calculateTo","shape","_stopTween","animate","cb","passedOpts","defaultOpts","shiftyEasing","values","_resolveFromAndTo","newOffset","reference","computedStyle","getPropertyValue","_calculateFrom","shifty","6","_initializeTextContainer","textContainer","alignToBottom","setStyle","7","color","trailColor","fill","autoStyleContainer","svgStyle","warnings","isObject","svgView","_createSvgView","_container","_warnContainerAspectRatio","setStyles","trail","newOpts","_progressPath","setText","DESTROYED_ERROR","newText","_createTextContainer","removeChildren","innerHTML","trailPath","_createTrail","_createPath","pathString","_createPathElement","textStyle","floatEquals","8","PREFIXES","elStyle","capitalize","forEachObject","recursive","attrName","destVal","sourceVal","template","vars","regExp","rendered","styles","styleValue","styleName","b","firstChild","Hogan","parser","findInScope","doModelGet","Template","codeObj","compiler","partials","subs","buf","indent","v","str","coerceToString","hChars","rAmp","rLt","rGt","rApos","rQuot","ri","ep","symbol","partial","instance","base","compile","stackText","activeSub","stackSubs","stackPartials","PartialTemplate","Substitutions","subsText","createSpecializedPartial","rp","rs","section","tail","pop","inverted","tags","pass","ms","returnFound","found","names","modelGet","mv","ls","func","oldTags","delimiters","ct","disableLambda","fl","textSource","substring","sub","rIsWhitespace","rNewline","rCr","rSlash","rLineSep","rParagraphSep","tagChange","tag","#","^","<","/","!",">","=","_v","{","&","_t","scan","close","closeIndex","tagType","seenTag","lineStart","otag","ctag","addBuf","filterLine","haveSeenTag","noNewLine","isAllWhitespace","j","lineIsWhitespace","allowedInSuper","\n","buildTree","kind","stack","customTags","instructions","opener","isOpener","nodes","open","isCloser","last","stringifyPartials","esc","items","stringifySubstitutions","stringify","wrapMain","serialNo","chooseMethod","createPartial","sym","tripleStache","write","generate","tree","walk","asString","makeTemplate","makePartials","codegen","inPartial","nodelist","parse","sectionTags","cache","cacheKey","Timer","originalDelay","timerId","paused","StopWatch","watches","getMeasuringTime","accumulationTime","isPaused","Interval","isRunning","IntervalId","clearInterval","AmCharts","themes","maps","inheriting","charts","onReadyArray","useUTC","updateRate","uid","lang","translations","mapTranslations","windows","initHandlers","amString","pmString","construct","inherits","createEvents","listenTo","handler","fire","addChart","animationRequested","update","updateInt","removeChart","requestAnimation","NaN","isModern","getIEVersion","appName","$1","applyLang","dayNames","shortDayNames","monthNames","shortMonthNames","langObj","am","pm","IEversion","isIE","dx","dy","opera","isNN","handleMouseUp","handleReleaseOutside","handleMouseMove","handleKeyUp","handleWheel","mouseIsOver","mouseWheelScrollEnabled","mouseWheelZoomEnabled","resetMouseOver","ready","handleLoad","isReady","isNaN","processDelay","addInitHandler","types","callInitHandler","isInArray","getUniqueId","addGlobalListeners","globalListenersAdded","addWheelListeners","wheelIsListened","passive","makeChart","g","theme","AmSerialChart","AmXYChart","AmPieChart","AmRadarChart","AmAngularGauge","AmFunnelChart","AmMap","AmStockChart","AmGanttChart","realWrite","updateCount","validateAt","autoResize","validateSize","premeasure","readyState","toBoolean","removeFromArray","getPath","getElementsByTagName","normalizeUrl","isAbsolute","getDecimals","Number","wordwrap","h","input","wrappedText","getBBox","floor","getStyle","defaultView","currentStyle","removePx","getURL","parent","getElementsByName","closed","ifArray","callMethod","toNumber","toColor","toCoordinate","fitToBounds","isDefined","stripNumbers","roundTo","formatDuration","intervals","decimalSeparator","formatNumber","precision","nextInterval","count","thousandsSeparator","addZeroes","scientificToNormal","toScientific","LOG10E","randomColor","random","hitTest","isInRectangle","isPercents","formatValue","addPrefix","formatDataContextValue","massReplace","cleanFromEmpty","getEffect","getObjById","applyTheme","JSON","copyProperties","processObject","fixNewLines","fixBrakes","deleteObject","easeOutElastic","asin","fixStepE","toExponential","generateNumber","setCN","addClassNames","classNamePrefix","removeCN","parseDefs","SVG_NS","AxisBase","titleDY","axisThickness","axisColor","axisAlpha","gridCount","tickLength","gridAlpha","gridThickness","gridColor","dashLength","labelFrequency","showLastLabel","showFirstLabel","fillColor","fillAlpha","labelsEnabled","labelRotation","autoGridCount","guides","counter","ignoreAxisWidth","inside","minHorizontalGap","minVerticalGap","titleBold","minorGridEnabled","minorGridAlpha","autoWrap","titleAlign","labelOffset","bcn","centerLabels","firstDayOfWeek","centerLabelOnFullPeriod","markPeriodChange","boldPeriodBeginning","titleWidth","periods","period","dateFormats","format","nextPeriod","fff","ss","mm","hh","DD","MM","zoom","dataChanged","draw","fixAxisPosition","createBalloon","chart","prevBY","prevBX","allLabels","setBalloonBounds","labels","gridSet","axesLabelsSet","labelsSet","axisLine","axisRenderer","gridCountR","axisWidth","addTitle","setOrientation","title","titleLabel","titleColor","titleFontSize","fontFamily","positionTitle","VML","q","marginsChanged","translate","tx","ty","titleRotation","rotate","pushAxisItem","graphics","getLabel","handleMouse","mouseover","mouseout","serialDataItem","axis","label","addGuide","Guide","removeGuide","handleGuideOver","hoverInt","lineColor","showBalloon","balloonText","guide","handleGuideOut","hideBalloon","handleGuideClick","addEventListeners","axisSet","grid0","chooseMinorFrequency","parseDatesDraw","w","extractPeriod","minPeriod","getPeriodDuration","z","A","choosePeriod","B","stepWidth","getStepWidth","timeDifference","ceil","D","resetDateToMin","C","cellWidth","firstTime","I","autoRotateCount","autoRotateAngle","labelRotationR","gridPosition","checkPeriodChange","dateFormatsObject","twoLineMode","currentDateFormat","formatDate","labelFunction","boldLabels","axisItemRenderer","startOnAxis","timeZoom","minDuration","generateDFObject","balloon","hide","formatBalloonText","adjustBalloonCoordinate","coordinateToValue","chartCursor","balloonTextFunction","parseDates","setPosition","cursorPosition","stickBalloonToCategory","stickBalloonToStart","cornerRadius","shadowAlpha","borderThickness","borderAlpha","adjustBorderColor","showBullet","mainSet","plotBalloonsSet","pointerWidth","animationDuration","drop","pointerOrientation","setBounds","ValueAxis","stackType","unitPosition","includeAllValues","recalculateToPercents","includeHidden","includeGuidesInMinMax","integersOnly","durationUnits","baseValue","radarCategoriesEnabled","axisFrequency","gridType","useScientificNotation","axisTitleOffset","pointPosition","minMaxMultiplier","logGridLimit","totalTextOffset","treatZeroAs","relativeStart","relativeEnd","updateData","totals","chartData","stackGraphs","recalculate","synchronizationMultiplier","synchronizeWith","getValueAxisById","synchronizeWithAxis","foundGraphs","getMinMax","minZoom","maxZoom","fullMin","fullMax","strictMinMax","minimum","maximum","logarithmic","logMin","minimumDate","minRR","maximumDate","maxRR","reversed","getDateMinMax","getExtremes","minReal","Infinity","minCalc","maxCalc","LN10","maxDecCount","nf","numberFormatter","exponential","maxInterval","getMaxInterval","getMinorGridStep","maxTime","gridCountReal","startCount","H","getCoordinate","zeroGridAlpha","line","axesSet","toBack","Q","above","toValue","guideFillRenderer","baseCoord","axisCreated","toFront","show","axisY","axisX","getDate","dataDateFormat","usePrefixes","prefixesOfBigNumbers","prefixesOfSmallNumbers","unit","graphs","stackGraph","hidden","valueAxis","stackable","newStack","axes","fillToGraph","percents","total","compareFromStart","categoryAxis","recalculateFromDate","getClosestIndex","recalculateValue","dataContext","valueField","recBaseValue","expandMinMax","maxReal","setStep","graphsById","includeInMinMax","minMaxField","zoomOut","zoomToRelativeValues","zoomToValues","startValue","endValue","prevStartValue","prevEndValue","handleSynchronization","RecAxis","RecItem","fa","Ba","Y","Da","ca","M","P","ia","J","aa","ma","na","Pa","Z","da","previousCoord","X","xa","ea","ga","lineAlpha","lineThickness","boldLabel","minorTickLength","V","G","oa","ha","Qa","centerRotatedLabels","polygon","text-anchor","backgroundColor","childNodes","RecFill","reverse","AmChart","svgIcons","tapToActivate","chartCreated","previousWidth","previousHeight","backgroundAlpha","borderColor","autoDisplay","addCodeCredits","accessible","touchStartTime","touchClickDuration","percentPrecision","titles","marginRight","marginLeft","autoMarginOffset","timeOuts","creditsPosition","textAlign","chartDiv","legendDiv","titleHeight","hideBalloonTime","handDrawScatter","cssScale","handDrawThickness","cssAngle","panEventsEnabled","product","animations","AmBalloon","processTimeout","processCount","animatable","drawChart","realWidth","realHeight","drawBackground","redrawLabels","drawTitles","brr","renderFix","boundingRect","makeAccessible","setAttr","background","updateWidth","updateHeight","backgroundImage","image","bgImg","Title","size","alpha","bold","sprite","tabIndex","freeLabelsSet","afterWriteTO","afterWrite","div","legend","measure","divRealHeight","divRealWidth","containerDiv","exportConfig","AmExport","amExport","addLegend","divId","prevLegendPosition","listenersAdded","addListeners","initChart","createLabelsSet","AmCharts_path","pathToImages","initHC","language","percentFormatter","pf","addDefs","AmDraw","extension","SVG","checkDisplay","checkTransform","handDrawn","cursorLineSet","graphsBehindSet","bulletBehindSet","columnSet","graphsSet","trendLinesSet","cursorSet","scrollbarsSet","bulletSet","balloonsSet","zoomButtonSet","zbSet","linkSet","mw","mh","setSize","autoTransform","clearTimeOuts","docfn1","docfn2","chartScrollbar","scrollbarV","scrollbarH","setMouseCursor","cursor","drawLabel","Label","align","rotation","urlTarget","addLabel","clearLabels","ieW","getTitleHeight","handleWheelReal","handleDocTouchStart","tmx","mouseX","tmy","mouseY","handleDocTouchEnd","tapped","panRequired","msTouchAction","resetTouchStyle","checkTouchDuration","isTouchEvent","resetTouchDuration","checkTouchMoved","handleTouchStart","handleTouchEnd","handleMouseDown","handleMouseOver","handleMouseOut","dispDUpd","skipEvents","dispatchDataUpdated","chartRendered","sizeChanged","legendInitTO","invalidateSize","marginsUpdated","initTO","positionCred","resizedTO","invalidateSizeReal","validateTO","validateData","validateNow","showItem","hideItem","balloonTO","hideBalloonReal","cleanChart","showBalloonReal","followCursor","changeColor","fixedPosition","outTO","handleMouseOutReal","mouse2Y","mouse2X","wasTouched","AmLegend","autoMargins","removeLegend","handleResize","getSVG","hasSVG","frame","effect","setLegendData","setData","stopAnim","updateAnimations","animationFinished","inIframe","amLink","marginLeftReal","marginTopReal","plotAreaWidth","plotAreaHeight","Slice","SerialDataItem","GraphDataItem","AmGraph","columnCount","columnIndex","centerCustomBullets","maxBulletSize","minBulletSize","animationPlayed","depthCount","negativeBase","visibleInLegend","showAllValueLabels","showBulletsAt","showBalloonAt","connect","bullet","bulletBorderThickness","bulletBorderAlpha","bulletAlpha","bulletSize","cornerRadiusTop","hideBulletsCount","bulletOffset","cursorBulletAlpha","gradientOrientation","periodValue","clustered","periodSpan","accessibleLabel","accessibleSkipText","switchable","minDistance","tcc","labelAnchor","dateFormat","noRounding","isRolledOverBullet","drawGraphs","behindColumns","bulletAxis","columnsSet","columnsArray","ownColumns","allBullets","animationArray","labelPosition","xAxis","yAxis","createGraph","startAlpha","seqAn","sequencedAnimation","fillAlphas","bulletColorR","bulletColor","lineColorR","bulletColorNegative","negativeLineColor","playedTO","createSerialGraph","positiveClip","createRadarGraph","createXYGraph","setAnimationPlayed","startDuration","pmh","pmw","pmy","pmx","createBullet","labelText","createLabel","positionLabel","drawLineGraph","launchAnimation","rMultiplier","isNegative","labelIsNegative","columnGraphics","columnHeight","columnWidth","getGradRotation","gradientRotation","dashLengthSwitched","fillColorsSwitched","lineColorSwitched","columnWidthReal","useNegativeColorIfDown","columnSpacing","Ka","tb","ub","vb","lb","mb","wb","fillColorsR","Ra","negativeFillColors","Ja","bb","negativeFillAlphas","xb","nb","La","minCoord","resetBullet","Ua","Mb","Nb","nmx","nmy","nmh","nmw","fixedColumnWidth","L","lineColorField","bulletColorSwitched","fillColorsField","fillColors","dashLengthField","T","U","Ma","Ob","noStepRisers","db","eb","ob","Sa","Va","fb","Ta","openField","yb","K","za","ja","F","O","N","qa","ra","sa","ta","ya","Ea","ka","la","W","zb","Ab","va","Na","Wa","Ha","Bb","proCandlesticks","pb","topRadius","Fa","pa","gb","Ia","low","high","Ya","hb","Eb","Gb","Oa","$b","bc","ib","jb","sb","kb","Xa","wa","Ga","Pb","stepDirection","Cb","ignoreCustomColors","gap","drawSmoothedGraph","Db","dc","Qb","Rb","rb","ba","S","R","Aa","Ca","percentWidthValue","Cuboid","d3x","d3y","showOnAxis","showHandOnHover","column","depth","animateColumns","Fb","Hb","Za","$a","ab","Sb","Ib","Tb","Jb","Kb","Ub","Lb","Vb","Wb","Xb","gc","Yb","Zb","totalText","totalTextColor","ac","cc","lastDataItem","bulletsHidden","hideBullets","customBulletsHidden","hideCustomBullets","labelColor","clipRect","negativeClip","negativeLineAlpha","handleGraphEvent","fillToAxis","applyMask","Bezier","animateGraphs","startEffect","animateWidth","animateHeight","legendKeyColor","legendColor","legendKeyAlpha","legendAlpha","customBullet","maxValue","minValue","bulletBorderColorR","useLineColorForBulletBorder","bulletConfig","availableSpace","graph","graphDataItem","bulletY","customBulletGraphics","cset","bulletHitAreaSize","circle","hitBullet","bulletGraphics","showBullets","showCustomBullets","handleRollOver","handleRollOut","handleClick","dblclick","handleDoubleClick","contextmenu","handleRightClick","valueBalloonsEnabled","showGraphBalloon","changeOpacity","fixBulletSize","resizedDItem","doNotScale","currentDataItem","resizeBullet","balloonFunction","getBalloonColor","fixPrevious","ChartCursor","cursorAlpha","selectionAlpha","cursorColor","categoryBalloonAlpha","zoomed","zoomable","pan","categoryBalloonDateFormat","categoryBalloonText","categoryBalloonEnabled","rolledOver","bulletsEnabled","skipZoomDispatch","selectWithoutZooming","oneBalloonOnly","graphBulletSize","zooming","adjustment","avoidBalloonOverlapping","leaveCursor","leaveAfterTouch","valueZoomable","balloonPointerOrientation","hLineEnabled","vLineEnabled","vZoomEnabled","hZoomEnabled","prevLineHeight","prevLineWidth","createElements","limitToGraph","fullWidth","pointer","isHidden","hideLines","valueLineAxis","valueAxes","valueLineAlpha","vvLine","hhLine","vLine","fullLines","keyup","handleKeys","showCursor","blur","hideCursor","prevIndex","startIndex","endIndex","hideGraphBalloons","updateDrawing","fx","fy","dispatchMovedEvent","forceShow","mouse2X0","dispatchPanEvent","updateSelection","drawing","drawingNow","drawingLine","drawStartX","drawStartY","marginTop","fixWidth","fixHeight","fixVLine","prevLineX","prevLineY","fixHLine","hideCursorReal","handleCursorHide","mouseY0","mouseX0","updateFullLine","justReleased","mouseIsDown","fixPosition","prevY","prevX","mouse2Y0","index0","timestamp0","registerInitialMouse","initialX","initialY","finalX","finalY","dispatchZoomEvent","equalSpacing","getEndTime","selectionHeight","selectionWidth","selectionY","selectionX","endX","endY","panning","mostCloseGraph","skip","hideBalloons","finalPosition","handleCursorMove","prevDeltaX","prevDeltaY","prevDelta2X","prevDelta2Y","delta2X","delta2Y","syncTO","setTimestamp","setIndex","showCursorAt","categoryToCoordinate","enableDrawing","syncWithCursor","syncWithCursorReal","isZooming","SimpleChartScrollbar","selectedBackgroundColor","scrollDuration","selectedBackgroundAlpha","resizeEnabled","hideResizeGrips","scrollbarHeight","updateOnReleaseOnly","documentMode","dragIconHeight","dragIconWidth","dragIcon","dragCursorHover","dragCursorDown","vResizeCursor","hResizeCursor","percentStart","percentEnd","getPercents","getDBox","bg","invisibleBg","handleBgClick","selectedBG","dragger","handleDragStart","handleDragStop","handleDraggerOver","iconLeft","iconRight","updateGripCursor","leftDragStart","leftDragStop","iconRollOver","iconRollOut","rightDragStart","rightDragStop","hideDragIcons","clipDragger","percentZoom","updateScrollbarSize","clipAndUpdate","initialMouse","forceClip","dragging","initialCoord","resizingRight","maxHeight","resizingLeft","maxWidth","stopForceClip","animating","clipY","clipH","clipX","clipW","dispatchScrollbarEvent","maskGraphs","updateDragIconPositions","skipEvent","multiplier","prevPercentStart","prevPercentEnd","prevMultiplier","showDragIcons","removeCursors","fireZoomEvent","vResizeCursorDown","vResizeCursorHover","hResizeCursorDown","hResizeCursorHover","updateOnRelease","forceTO","ChartScrollbar","graphLineColor","graphLineAlpha","graphFillColor","graphFillAlpha","selectedGraphLineColor","selectedGraphLineAlpha","selectedGraphFillColor","selectedGraphFillAlpha","scrollbarCreated","oppositeAxis","gridAxis","catScrollbar","CategoryAxis","unselectedGraph","selectedGraph","dataProvider","closeField","highField","lowField","graphType","handleBackgroundClick","zoomScrollbar","minSelectedTime","maxSelectedTime","startDate","endDate","xToIndex","difference","horizontalPadding","verticalPadding","follow","shadowColor","fadeOutDuration","disableMouseEvents","deltaSignX","deltaSignY","sdy","sdx","pointToX","pointToY","xAnim","yAnim","removeDiv","balloonColor","minWidth","textDiv","yPos","prevTX","prevTY","rPrevX","rPrevY","rPrevTX","rPrevTY","restorePrevious","followMouse","previousX","previousY","destroyTO","positionChanged","isHiding","fadeAnim1","fadeAnim2","interval","AmCoordinateChart","colors","balloonDateFormat","gridAboveGraphs","processValueAxes","createValueAxes","processGraphs","processGuides","addValueAxis","parseData","parseSerialData","parseCount","delayParseSerialData","parsePartSerialData","onDataUpdated","seriesIdField","categoryField","forceShowField","classNameField","labelColorField","categoryFunction","lookupTable","category","gapPeriod","processValues","forceGap","processFields","parseGraphData","removeValueAxesAndGraphs","removeValueAxis","removeGraph","addGraph","chooseGraphColor","handleValueAxisZoom","[[title]]","[[description]]","description","getGraphById","itemColors","bulletBorderColor","patterns","handleLegendEvent","dataItem","textClickEnabled","hideGraphsBalloon","showGraphsBalloon","highlightGraph","unhighlightGraph","hideGraph","showGraph","rollOverGraphAlpha","updateLegend","resetAnimation","animateAgain","TrendLine","isProtected","initialDate","initialCategory","finalDate","finalCategory","valueAxisX","initialXValue","finalXValue","initialValue","finalValue","dateToCoordinate","initialImage","Image","finalImage","handleLineClick","handleLineOver","handleLineOut","trendLine","rollOverColor","stroke","svgPath","outlineColor","fill-opacity","stroke-width","stroke-opacity","ellipse","gradient","adjustLuminosity","font-family","font-size","makeHD","triangle","handDrawnLine","doNothing","wedge","thickness","grad","rgb2hex","bezierX","bezierY","drawSegment","SVG_XLINK","createSVGRect","rBin","createSvgElement","SVGRenderer","VMLRenderer","vmlStyleSheet","namespaces","styleSheets","createStyleSheet","addRule","disableSelection","AmDObject","addToContainer","rx","ry","bw","cs","dd","accessibleTitle","rtl","createTextNode","accessibleDescription","defs","scale","getAttr","angle","clipPath","hasChildNodes","prevNextNode","nextSibling","toPrevious","insertBefore","an_translate","an_y","an_x","cNames","styleMap","visibility","shapeType","anchor","fontWeight","svgPathToVml","weight","dashstyle","arcSize","whiteSpace","getBox","clip","getBGColor","paddingLeft","onselectstart","setAttributeNS","baseHref","removeTarget","clipPathC","patternNode","randomX","randomY","markerLabelGap","verticalGap","horizontalGap","spacing","markerDisabledColor","markerType","markerSize","markerBorderThickness","markerBorderAlpha","marginBottom","valueWidth","switchType","switchColor","reversedOrder","valueText","useMarkerColorForLabels","equalWidths","useGraphSettings","showEntries","labelDx","legendData","entries","valueLabels","drawLegend","combineLegend","maxColumnsReal","maxColumns","divWidth","lx","ly","maxLabelWidth","createEntry","createValue","arrangeEntries","updateValues","hideFromLegend","legendEntryWidth","customMarker","createMarker","createX","createV","dItem","legendSwitch","selectedColor","clickMarker","legendTextReal","labelWidth","legendEntry","legendMarker","legendLabel","rollOverMarker","rollOutMarker","dispatch","rollOverLabel","rollOutLabel","clickLabel","forceWidth","valueAlign","useMarkerColorForValues","markerBorderColor","periodDataItem","periodPercentDataItem","periodValueText","legendPeriodValueText","legendPeriodValueTextR","legendValueText","legendValueTextR","formatPeriodString","valueFunction","legendColorFunction","formatMilliseconds","getMilliseconds","newDate","stringToDate","daysInMonth","getYear","getMonth","getFullYear","getHours","getMinutes","getSeconds","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","getUTCMilliseconds","getUTCDay","getDay","setUTCFullYear","setUTCHours","getWeekNumber","setHours","setDate","getFromDateString","year","hours","minutes","seconds","milliseconds","changeDate","changeUTCDate","setFullYear","setMonth","setMinutes","setSeconds","setMilliseconds","setUTCDate","setUTCMonth","setUTCMinutes","setUTCSeconds","setUTCMilliseconds","AmRectangularChart","depth3D","plotAreaFillColors","plotAreaFillAlphas","plotAreaBorderColor","plotAreaBorderAlpha","maxZoomFactor","zoomOutButtonImageSize","zoomOutButtonImage","zoomOutText","zoomOutButtonColor","zoomOutButtonAlpha","zoomOutButtonRollOverAlpha","zoomOutButtonPadding","trendLines","updateDxy","resetMargins","processScrollbars","updateMargins","updatePlotArea","updateScrollbars","updateTrendLines","updateChartCursor","updateValueAxes","scrollbarOnly","updateGraphs","drawPlotArea","xAxes","yAxes","fixMargins","measureMargins","getAxisBounds","minMarginLeft","minMarginRight","minMarginTop","minMarginBottom","drawZoomOutButton","zoomOutButtonFontSize","zoomOutButtonFontColor","zoomOutButton","zbBG","rollOverZB","rollOutZB","clickZB","zoomOutButtonTabIndex","rolledOverZB","zoomOutValueAxes","plotAreaGradientAngle","bbset","marginRightReal","marginBottomReal","columnSpacing3D","setAxisRenderers","updateObjectSize","addChartCursor","addChartScrollbar","removeChartCursor","zoomTrendLines","handleCursorValueZoom","addTrendLine","removeTrendLine","adjustMargins","getScrollbarPosition","updateChartScrollbar","showZB","handleScrollbarValueZoom","relativeZoomValueAxes","zoomAxesAndGraphs","zoomValueScrollbar","handleValueAxisZoomReal","updateAfterValueZoom","handleCursorZoom","handleCursorZoomStarted","handleCursorPanning","handleCursorChange","skipZoomed","startX0","endX0","endY0","startY0","handleCursorZoomReal","zoomOutOnDataUpdate","skipZoom","updateCategoryAxis","countColumns","getStartTime","syncGrid","synchronizeGrid","wheelBusy","zoomToDates","zoomToIndexes","valueScrollbar","indexZoom","updateLegendValues","fixCursor","updateColumnsDepth","dispatchTimeZoomEvent","maxSelectedSeries","dispatchIndexZoomEvent","sort","compareDepth","zoomedByScrollbar","getCategoryIndexByValue","handleScrollbarZoom","prevStartTime","prevEndTime","prevStartIndex","prevEndIndex","zoomToCategoryValues","average","sum","customData","categoryBalloonColor","valueLineEnabled","valueLineBalloonEnabled","categoryBalloonFunction","categoryLineAxis","addValueScrollbar","removeChartScrollbar","removeValueScrollbar","getNextItem","start0","end0","startTime0","endTime0","prevCursorItem","showNextAvailable","prevMostCloseGraph","graphBulletAlpha","arrangeBalloons","compareY","bwidth","bcolor","balpha","totalFrames","rh","rw","safeDistance","widthField","widthValue","previousPos","tickPosition","toCategory","expand","toDate","coordinateToDate","AmSlicedChart","groupPercent","groupedTitle","groupedPulled","groupedAlpha","hoverAlpha","outlineAlpha","outlineThickness","pullOutDuration","pullOutEffect","pullOnHover","pullOutOnlyOne","labelTickColor","labelTickAlpha","hideLabelsPercent","gradientRatio","clickSlice","rollOverSlice","rollOutSlice","hideSlice","showSlice","invalidateVisibility","recalculatePercents","tempPrec","startSlices","setStartTO","startSlice","startSequenced","pullSlices","pulled","pullSlice","started","labelSet","showLabels","tick","balloonX","balloonY","pullX","pullY","drawTicks","skipTick","tx0","tx2","ty0","initialStart","pullInAll","pullOutAll","pieAlpha","titleField","pulledField","descriptionField","labelRadius","labelRadiusField","urlField","patternField","visibleInLegendField","alphaField","colorField","groupValue","removeSmallSlices","groupedColor","groupedUrl","groupedDescription","groupedPattern","groupedClassName","baseColor","pieBaseColor","brightnessStep","pieBrightnessStep","measureMaxLabel","minRadius","startAngle","innerRadius","startRadius","pullOutRadius","previousScale","adjustPrecision","gradientType","pieX","pieY","showZeroSlices","ix","iy","labelQuarter","textX","arrangeLabels","pieXReal","pieYReal","radiusReal","innerRadiusReal","setDepths","checkOverlapping","checkOverlappingReal","Promise","_dereq_","promise","setHowMany","setUnwrap","_SomePromiseArray","any","_customScheduler","_isTickUsed","_lateQueue","_normalQueue","_haveDrainedQueues","drainQueues","_drainQueues","_schedule","_settlePromises","setScheduler","hasCustomScheduler","haveItemsQueued","fatalError","process","stderr","exit","throwLater","invokeLater","_queueTick","invoke","settlePromises","_pushOne","_reset","firstLineError","./queue","./schedule","_reject","promiseRejectionQueued","bindingPromise","_then","_bitField","_resolveCallback","_propagateFrom","propagateFromFunction","_boundValue","boundValueFunction","_setBoundTo","_setOnCancel","_boundTo","_isBound","resolve","noConflict","./promise","classString","canEvaluate","isIdentifier","./util","tryCatch","errorObj","_async","cancel","cancellation","_warn","_isCancellable","_cancelBy","_isFollowing","_followee","_cancelBranched","_cancellationParent","_setWillBeCancelled","_branchHasCancelled","_branchesRemainingToCancel","_enoughBranchesHaveCancelled","_invokeOnCancel","_cancel","_setCancelled","_cancelPromises","_length","_unsetOnCancel","_onCancelField","isPending","_isCancelled","isCancellable","isCancelled","_doInvokeOnCancel","_attachExtraTrace","_resultCancelled","_onCancel","_invokeInternalOnCancel","./es5","_trace","CapturedTrace","_promiseCreated","_pushContext","_popContext","_peekContext","deactivateLongStackTraces","activateLongStackTraces","9","_attachCancellationCallback","isFulfilled","_parent","attachExtraTrace","__stackCleaned__","notEnumerableProp","lt","longStackTraces","ot","at","ut","fileName","_promisesCreated","uncycle","Warning","canAttachTrace","env","_notifyUnhandledRejection","contentWindow","suppressUnhandledRejections","_ensurePossibleRejectionHandled","_setRejectionIsUnhandled","_notifyUnhandledRejectionIsHandled","_setReturnedNonUndefined","_returnedNonUndefined","_isRejectionUnhandled","_settledValue","_setUnhandledRejectionIsNotified","_unsetUnhandledRejectionIsNotified","_isUnhandledRejectionNotified","_unsetRejectionIsUnhandled","onPossiblyUnhandledRejection","_getContext","contextBind","onUnhandledRejectionHandled","tt","et","_captureStackTrace","_dereferenceTrace","hasLongStackTraces","unhandledrejection","before","onunhandledrejection","after","rejectionhandled","onrejectionhandled","nt","cancelable","reason","Event","rt","isNode","it","promiseCreated","promiseFulfilled","promiseRejected","promiseResolved","promiseCancelled","promiseChained","child","warning","unhandledRejection","rejectionHandled","st","wForgottenReturn","_clearCancellationData","_execute","monitoring","_fireEvent","nodeSupportsAsyncResource","asyncHooks","stackTraceLimit","captureStackTrace","isTTY","checkForgottenReturns","deprecated","fireDomEvent","fireGlobalEvent","./errors","10","thenReturn","thenThrow","catchThrow","caught","catchReturn","11","reduce","all","mapSeries","12","cause","isOperational","freeze","RangeError","__BluebirdErrorTypes__","CancellationError","TimeoutError","OperationalError","RejectionError","AggregateError","13","getDescriptor","getOwnPropertyDescriptor","getOwnPropertyNames","isES5","propertyIsWritable","14","15","called","cancelPromise","finallyHandler","isFinallyHandler","isRejected","_passThrough","then","lastly","tapCatch","reject","./catch_filter","16","_finallyPromise","_promise","_stack","_generatorFunction","_receiver","_generator","_yieldHandlers","_yieldedPromise","_cancellationPhase","_isResolved","_cleanup","_fulfill","_promiseCancelled","coroutine","returnSentinel","_continue","_promiseFulfilled","_promiseRejected","_run","_rejectCallback","done","_proxy","_value","_reason","yieldHandler","addYieldHandler","spawn","17","spread","18","constructor$","_callback","_preservedValues","_limit","_inFlight","_queue","_asyncInit","concurrency","isFinite","_init$","_values","_drainQueue","_totalResolved","_filter","_resolve","preservedValues","19","_resolveFromSyncValue","attempt","20","markAsOriginatingFromRejection","maybeWrapAsError","21","asCallback","nodeify","22","_fulfillmentHandler0","_rejectionHandler0","_promise0","_receiver0","_resolveFromExecutor","PromiseInspection","domain","async","setReflectHandler","AsyncResource","reflect","_setIsFinal","toJSON","fulfillmentValue","rejectionReason","originatesFromRejection","getNewLibraryCopy","fromNode","fromCallback","multiArgs","_isFateSealed","_setAsyncGuaranteed","fulfilled","cast","_setFulfilled","rejected","_settlePromiseCtx","_settlePromiseLateCancellationObserver","receiver","_addCallbacks","_setLength","_setRejected","_setFollowing","_isFinal","_unsetCancelled","_setNoAsyncGuarantee","_receiverAt","_promiseAt","_fulfillmentHandlerAt","_rejectionHandlerAt","_migrateCallback0","_migrateCallbackAt","_setFollowee","ensureErrorObject","_settlePromiseFromHandler","_settlePromise","_settlePromise0","_clearCallbackDataAtIndex","_fulfillPromises","_rejectPromises","defer","pending","toFastProperties","lastLineError","./any.js","./async","./bind","./call_get.js","./cancel","./context","./debuggability","./direct_resolve","./each.js","./filter.js","./finally","./generators.js","./join","./map.js","./method","./nodeback","./nodeify.js","./promise_array","./promisify.js","./props.js","./race.js","./reduce.js","./settle.js","./some.js","./synchronous_inspection","./thenables","./timers.js","./using.js","async_hooks","23","asArray","_resolveEmptyArray","Map","_iterate","getActualLength","shouldCopyValues","24","__isPromisified__","inheritedDataKeys","getDataPropertyOrDefault","withAppended","promisify","copyDescriptors","promisifyAll","promisifier","isClass","25","_isMap","26","_capacity","_front","_willBeOverCapacity","_checkCapacity","_resizeTo","27","race","28","_fn","_initialValue","_currentCancellable","_eachValues","accum","array","_gotAccum","_eachComplete","_resultCancelled$","29","getNativePromise","MutationObserver","setImmediate","nextTick","isRecentNode","standalone","cordova","attributes","observe","disconnect","30","_promiseResolved","_settledValueField","settle","allSettled","31","_howMany","_unwrap","_initialized","_canPossiblyFulfill","_getRangeError","howMany","_addFulfilled","_fulfilled","_addRejected","_checkOutcome","_rejected","some","32","isResolved","__isCancelled","33","34","handle","35","_isDisposable","_getDisposer","_setDisposable","tryDispose","_data","_context","isDisposer","resources","resource","doDispose","_unsetDisposable","using","_disposer","disposer","36","thrower","isPrimitive","isError","foo","filledRange","hasEnvVariables","runInAsyncScope","./src/json2xml.js","buildOptions","defaultOptions","attributeNamePrefix","attrNodeName","textNodeName","ignoreAttributes","cdataTagName","cdataPositionChar","indentBy","supressEmptyNode","tagValueProcessor","attrValueProcessor","Parser","isAttribute","attrPrefixLen","isCDATA","replaceCDATAstr","replaceCDATAarr","indentate","tagEndChar","newLine","buildTextNode","buildEmptyTextNode","buildObjNode","buildEmptyObjNode","buildTextValNode","buildObjectNode","cdata","attrStr","level","includes","repeat","startsWith","jObj","j2x","arrLen","Ks","_j","_result","./src/nimndata.js","_char","fromCharCode","_e","e_schema","getValue","hasValidData","chars","missingChar","nilChar","attrsMap","emptyChar","arrStart","itemSchema","arr_len","arr_i","processValue","_arr_i","_r","arrayEnd","objStart","_r2","isAppChar","ch","charsArr","nilPremitive","missingPremitive","emptyValue","boundryChar","x2j","convert2nimn","./src/node2json.js","convertToJson","isEmptyObject","isExist","arrayMode","merge","tagname","./src/node2json_str.js","_cToJsonStr","convertToJsonString","./src/parser.js","nodeToJson","xmlToNodeobj","x2xmlnode","validator","xmlData","validationOption","validate","msg","getTraversalObj","convertTonimn","j2xParser","parseToNimn","schema","./src/util.js","doesMatch","regex","newOptions","doesNotMatch","getAllMatches","allmatches","./src/validator.js","allowBooleanAttributes","localeRange","readCommentAndCDATA","angleBracketsCount","getErrorObject","tagFound","reachedRoot","regxAttrName","regxTagName","getLineNumberForPosition","readPI","closingTag","startChar","tagClosed","doubleQuote","singleQuote","readAttributeStr","isValid","validateAttributeString","otg","_isValid","validAttrStrRegxp","getPositionFromMatch","lineNumber","./src/xmlNode.js","addChild","./src/xmlstr2xmlnode.js","xmlNode","TagType","OPENING","CLOSING","SELF","CDATA","regx","ignoreNameSpace","parseNodeValue","parseAttributeValue","trimValues","stopNodes","processTagValue","parsedTags","parentTagName","parseValue","parseTrueNumberOnly","shouldParse","parsed","attrsRegx","buildAttributesMap","attrs","resolveNameSpace","attrCollection","xmlObj","currentNode","tagsRegx","nextTag","_childNode","childNode","_childNode2","./node_modules/babel-runtime/core-js/object/define-property.js","./node_modules/babel-runtime/core-js/object/keys.js","./node_modules/babel-runtime/core-js/object/values.js","./node_modules/babel-runtime/helpers/classCallCheck.js","./node_modules/babel-runtime/helpers/createClass.js","_defineProperty","_defineProperty2","./node_modules/core-js/library/fn/object/define-property.js","$Object","desc","./node_modules/core-js/library/fn/object/keys.js","./node_modules/core-js/library/fn/object/values.js","./node_modules/core-js/library/modules/_a-function.js","./node_modules/core-js/library/modules/_an-object.js","./node_modules/core-js/library/modules/_array-includes.js","toIObject","toLength","toAbsoluteIndex","IS_INCLUDES","$this","fromIndex","./node_modules/core-js/library/modules/_cof.js","./node_modules/core-js/library/modules/_core.js","core","__e","./node_modules/core-js/library/modules/_ctx.js","aFunction","./node_modules/core-js/library/modules/_defined.js","./node_modules/core-js/library/modules/_descriptors.js","./node_modules/core-js/library/modules/_dom-create.js","./node_modules/core-js/library/modules/_enum-bug-keys.js","./node_modules/core-js/library/modules/_export.js","$export","own","out","IS_FORCED","IS_GLOBAL","IS_STATIC","IS_PROTO","IS_BIND","IS_WRAP","expProto","PROTOTYPE","virtual","./node_modules/core-js/library/modules/_fails.js","./node_modules/core-js/library/modules/_global.js","__g","./node_modules/core-js/library/modules/_has.js","./node_modules/core-js/library/modules/_hide.js","dP","createDesc","./node_modules/core-js/library/modules/_ie8-dom-define.js","./node_modules/core-js/library/modules/_iobject.js","cof","propertyIsEnumerable","./node_modules/core-js/library/modules/_is-object.js","./node_modules/core-js/library/modules/_object-dp.js","anObject","IE8_DOM_DEFINE","toPrimitive","Attributes","./node_modules/core-js/library/modules/_object-keys-internal.js","arrayIndexOf","IE_PROTO","./node_modules/core-js/library/modules/_object-keys.js","$keys","enumBugKeys","./node_modules/core-js/library/modules/_object-pie.js","./node_modules/core-js/library/modules/_object-sap.js","fails","KEY","exp","./node_modules/core-js/library/modules/_object-to-array.js","getKeys","isEnum","isEntries","./node_modules/core-js/library/modules/_property-desc.js","bitmap","./node_modules/core-js/library/modules/_shared-key.js","shared","./node_modules/core-js/library/modules/_shared.js","SHARED","store","./node_modules/core-js/library/modules/_to-absolute-index.js","toInteger","./node_modules/core-js/library/modules/_to-integer.js","./node_modules/core-js/library/modules/_to-iobject.js","IObject","defined","./node_modules/core-js/library/modules/_to-length.js","./node_modules/core-js/library/modules/_to-object.js","./node_modules/core-js/library/modules/_to-primitive.js","valueOf","./node_modules/core-js/library/modules/_uid.js","px","./node_modules/core-js/library/modules/es6.object.define-property.js","./node_modules/core-js/library/modules/es6.object.keys.js","toObject","./node_modules/core-js/library/modules/es7.object.values.js","$values","./src/data.js","nativeName","ae","af","ak","an","ar","as","av","az","be","bh","bi","bm","bn","bo","br","bs","ce","co","cr","cu","cv","de","dv","dz","ee","en","eo","es","eu","ff","fi","fj","fo","fr","gd","gl","gn","gu","gv","he","hi","ho","hr","ht","hu","hy","hz","ie","ig","ii","ik","io","iu","jv","kg","ki","kj","kk","kl","km","kn","ko","kr","ks","ku","kv","kw","ky","lg","li","ln","lo","lu","lv","mg","mi","mk","ml","mn","mr","mt","my","nd","ne","ng","nl","nn","no","nr","nv","ny","oc","oj","om","or","pi","pl","ps","pt","qu","rm","rn","ro","ru","sc","sd","se","sg","si","sk","sl","sm","sn","so","sq","sr","su","sv","sw","te","tg","th","ti","tk","tl","tn","tr","ts","tw","ug","uk","ur","uz","ve","vi","vo","wo","xh","yi","yo","zh","zu","./src/index.js","_keys2","_values2","_classCallCheck3","_createClass3","_data2","ISO6391","getName","getNativeName","Constants","CONTENT_TYPE","MP4","HLS","RTSP","RTMP","NPP","LINEAR","DASH","MEDIA_TYPE","ENV","MOBILE_WEB","MOBILE_WEB_ALLOW_HD","TVPOT_WEB","DAUM_APP","KAKAOTV","IOS","ANDROID","PHASE","DEV","CBT","SANDBOX","PROD","PRODSLV","LOCAL","SUB_DOMAIN","KAKAO","PLAYER","DAUM","DOMAIN","HOST","protocol","SHARE_DOMAIN","APP_KEY","DTE_TYPE","IPHONE","IPAD","PC","ETC","VIDEO_TYPE","AD","VOD","LIVE","PROFILE","LOW","BASE","MAIN","HIGH","HIGH4","SUPER","ULTRA","AUTO","DASH_PROFILE","0","PROFILE_RESOULTION","ABR_RESTRICTION_PROFILE","ID","VIDEO_ELEMENT","VIDEO_CONTAINER","URL","THUMBNAIL_FARM_URL","KEMI_LOG_URL","LIVEAGENT_DOWNLOAD_URL_MAC","LIVEAGENT_DOWNLOAD_URL_WIN","LIVEAGENT_SETUP_GUIDE","STORAGE","UUID","VOLUME","ALERT_MSG","MUTE","ABR","CHART","SUBTITLE","ERROR","CLASS","BACKGROUND_ALPHA","BACKGROUND_DIMMED","THUMBNAIL_IMG","STATUS","Age18","NAME","MESSAGE_TYPE","DESCRIPTION","CLASS_NAME","HAS_OUT_LINK","Age19","AgeLimited18","AgeLimited19","AgeLimitedLive19","AudioCopyright","CleanCenterTemporaryRightViolations","LINK_TYPE","CodecNotInstalled","LINK_URL","LiveAgentNotInstalled","EncodingNotCompleted","ExceededAllowance","FailedEncoding","GeoBlocked","LiveFinished","LiveException","LivefarmServerError","Need19Login","NeedAuth","NeedAuth18","NeedAuth19","NeedAuthLive19","NeedChannel","NoOwnership","NotFound","NotOpenClipOrLive","RightViolations","UNAVAILABLE","UNAVAILABLE_DRM","UNAVAILABLE_COOKIE","Violation","VideoCopyright","OperationPolicy","LegacyPlayerNotice","UNAVAILABLE_ADBLOCK","UNAVAILABLE_ADCONTENTS","NETWORK_OFFLINE","ReservedClip","LimitExceeded","NotSupportedMedia","CONFIRM","CARRIER","LinearLive","LAUNCH_APP","NeedJoinAgreement","NeedLaunchApp","NeedPassword","NeedLogin","PasswordIncorrect","NoPurchased","NoPurchasedForMobile","NeedPurchased","HTTP","TYPE","XML","TEXT","METHOD","GET","POST","PUT","SHAKA","CONFIGURE","abr","defaultBandwidthEstimate","bandwidthUpgradeTarget","switchInterval","manifest","retryParameters","maxAttempts","streaming","rebufferingGoal","bufferingGoal","baseDelay","smallGapLimit","MOBILE","HTTP_ERROR","CODE","BAD_HTTP_STATUS","MEDIA_FORMAT_ERROR","FAILED_TO_GENERATE_LICENSE_REQUEST","QOE","EVENT","PLAYBACK_FAIL","REBUFFERING","SEEK","RESOLUTION_CHANGE","INITIAL_DELAY","BANDWIDTH","FRAME_DROP","DISPLAY_SIZE_CHANGE","PLAYER_CALLBACK_NAME","notReadyCallback","onAddPlaylist","onCheckNextVideo","onChangeAutoPlayMode","onKakaoIframeAPIReady","onEndAutoPlayTimer","onFullScreenChange","onLoadedContentVideo","onMeasureHeight","onClickEventStart","onPlayError","onPlayCancel","onFailAutoPlay","onReadyComplete","onReadyVideo","onStartImpression","onStartLoadVideo","onTouchEventStart","onTouchEventEnd","onVideoStateChange","onWideScreenChange","onPlayStart","onPlayEnd","onAlreadyInited","onOffsetPointUpdate","onTimeUpdate","pageReload","PLAYER_VIDEO_STATE","PLAYING","PLAY","PAUSE","PASSED","ENDED","PLAYER_CLICK_ACTION","TRACKING_OFF_PARAM","SENTRY","DEFAULT_MESSAGE_OPTION","CONFIG","DSN","TIARA","SVC_DOMAIN","SECTION","PLAYER_HTML5","PC_VOD","PAGE_VIEW","PAGE_NAME","ACTION_NAME","CLICK","LAYER1","PC_LIVE","MOBILE_VOD","MOBILE_LIVE","PLAYERCLASS","KAMP","HTML5","CAST","AGE_LIMIT","ALL","class","AGE_12","AGE_15","AGE_18","AGE_19","RATING","subject","sexual","violence","dialogue","fear","drug","imitation","RATING_LEVEL","NONE","NORMAL","LOW_HIGH","MEDIUM_HIGH","OFF","DRM","WIDEVINE","FAIRPLAY","PLAYREADY","constants","_defineProperties","dt","phase","defaultConfig","svcDomain","deployment","tiaraInstance","TiaraTracker","getInstance","setSection","sectionName","setPage","pageName","setExtras","extras","actionKind","customProps","setUrl","referrer","setReferrer","pageMeta","eventMeta","ecommerce","ecommerceContents","usage","viewImpContents","Tiara","trackEvent","params","setParameters","track","trackViewImp","trackUsage","page","extra","isNonEmptyString","MonetWebSocket","ws","monetWS","server","WebSocket","onopen","onOpen","onmessage","onMessage","onerror","onError","OPEN","send","hasValue","isNonEmptyArray","arr","parseXmlToJson","xmldata","option","helpers","debug","_isDebug","isShowServerSetting","hp","http","ajax","callbacks","successCallback","onSuccess","_type","_method","_body","xmlHttp","XMLHttpRequest","onreadystatechange","responseType","response","responseText","status","credentials","withCredentials","onTimeout","ontimeout","headers","setRequestHeader","fetchMethod","didTimeOut","fetch","json","catch","getHttpRequestMethod","httpRequestMethod","supportFetch","supportResponseJson","Response","contentType","sendBeacon","img","debugMode","isDebug","setDebug","sentry","captureException","table","groupCollapsed","tooltip","timer","hideTooltip","removeTooltip","setShowServerSetting","device","getDteType","isTV","arrVal","isSupportThumbnailVideo","isAndroidDown5","isSupportUniversalLinks","isSupportMutedControl","isPCWithSafari","isMobileWithSafari","isSupportInlinePlayOnIOS","playsinline","isSupportInlinePlayOnPC","isPC","msie","isIE9Under","isSupportDesktopBrowser","isIE11Under","isIMASupportedBrowser","isSupportInlinePlay","androidOver4","ipad","androidChrome","smarttv","isSupportCustomController","isSupportAd","uaStr","isFacebookWebview","isKakaotalkWebview","isChannelWebView","isKaKaoSubscribeWebView","isTalkWebView","isAllowContentAcessTalkWebView","isiPadOS","MSStream","isSupportAjaxAsync","isAllowedChromeVersion","isIeBrowser11Under","isiOSOver14","isMacOSChrome89Over","mac","isProd","isCbt","isDev","isSandbox","isLocal","feature","canPlayHLS","canPlayType","supportsH264","getVideoExtra","profile","canPlayHLSAndroid","osVersion","supportedOS","supportedBrowser","supportsVideoProfile","hhmmssToDate","hhmmss","fullscreen","playerElement","videoElement","requestFullscreen","webkitRequestFullscreen","webkitRequestFullScreen","mozRequestFullScreen","msRequestFullscreen","exitFullscreen","webkitExitFullscreen","webkitCancelFullScreen","mozCancelFullScreen","msExitFullscreen","webkitEnterFullscreen","webkitExitFullScreen","supportFullscreen","isSupport","request","isFullScreen","isSupportOnlyIOS","setFullscreen","fullScreen","fullscreenElement","webkitCurrentFullScreenElement","mozFullScreenElement","msFullscreenElement","webkitDisplayingFullscreen","webkitPresentationMode","isFullScreenChangeEvent","escapeHtml","unsafe","jsonToQueryString","separateTimes","totalSec","sec","hour","timeToString","times","stringToSec","timeString","splitTime","delimitTimes","delimiter","delimitNumbers","sec2hhmmss","timeInSeconds","pad","num","getThumbnailFarmUrl","encodeURIComponent","replaceLinefeed","isSupportOrientation","openPopup","windowName","features","windowRef","getParameter","param","decodeURIComponent","setParameter","removeParameter","parts","res","isValidate","addParam","paramName","expireDay","expireTime","setTime","timeZoneOffset","toGMTString","storage","setItem","cookie","getItem","expires","ckName","sendError","localStorage","removeItem","isExpiredTime","isExpired","expiredTime","webapi","share","network","getConnection","connection","mozConnection","webkitConnection","isWifi","pip","pictureInPictureEnabled","isPipScreen","pictureInPictureElement","requestPictureInPicture","exitPictureInPicture","traversal","nextAll","nextElementSibling","ui","preventDoubleClick","disabled","sdk","getDefaultCallbackParams","video","uuid","vid","sendEventCallback","cbName","cbParam","callbackParam","apiMessenger","sendCallback","polyfill","getProps","getPrefix","prefixes","launchTalk","deviceType","phaseHost","serverHost","klimtServer","urlParse","scheme","opt","launchApp","runType","linkId","packageName","live","vod","launchKakaoTV","phaseScheme","service","appSuffix","origin","appBridgeLink","launchPlusFriend","goStore","Sentry","dsn","release","playerVersion","exceptionMassage","errorDetail","captureMessage","cached","envHost","locationHost","link","sendOnAlreadyInited","xml2json","xml","isHlsVideo","videoUrl","tiara","tv","isConnected","framework","CastContext","getCastState","isOnTv","isOnAirPlay","webkitCurrentPlaybackTargetIsWireless","isOnChromecast","waiter","debounce","wait","immediate","later","restArguments","rest","debounced","callNow","throttle","previous","leading","throttled","remaining","trailing","kakao","sendMe","templateID","templateArgs","failCallback","Kakao","Auth","login","success","API","template_id","template_args","fail","alert","encoder","base64EncodeUint8Array","chr2","chr3","enc1","enc2","enc3","enc4","keyStr","output","chr1","drm","getType","edge","safari","