From 15c2d7a66374335902353fd2157a0fb405d65fe0 Mon Sep 17 00:00:00 2001 From: ajaxpf Date: Tue, 20 Sep 2016 14:54:47 +0900 Subject: [PATCH] skip: create 1.3.0 tag from 1.3.0-rc --- .gitignore | 9 +- bower.json | 2 +- dist/eg.js | 6015 ++++++++++++++++++ dist/eg.min.js | 17 + dist/pkgd/eg.pkgd.min.js | 38 + dist/pkgd/flicking.pkgd.min.js | 30 + dist/pkgd/infiniteGrid.pkgd.min.js | 26 + doc/class.js.html | 652 ++ doc/component.js.html | 777 +++ doc/cssPrefix.js.html | 636 ++ doc/eg.Class.html | 1169 ++++ doc/eg.Component.html | 1674 +++++ doc/eg.Flicking.html | 6271 +++++++++++++++++++ doc/eg.InfiniteGrid.html | 4198 +++++++++++++ doc/eg.MovableCoord.html | 5230 ++++++++++++++++ doc/eg.Visible.html | 2285 +++++++ doc/eg.html | 1938 ++++++ doc/eg.js.html | 815 +++ doc/flicking.js.html | 2169 +++++++ doc/fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes doc/fonts/glyphicons-halflings-regular.svg | 229 + doc/fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes doc/fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes doc/global.html | 5581 +++++++++++++++++ doc/index.html | 806 +++ doc/infiniteGrid.js.html | 1429 +++++ doc/jQuery.html | 3130 +++++++++ doc/module.js.html | 817 +++ doc/movableCoord.js.html | 1424 +++++ doc/pauseResume.js.html | 912 +++ doc/persist.js.html | 835 +++ doc/rotate.js.html | 748 +++ doc/scripts/bootstrap.min.js | 7 + doc/scripts/jquery.min.js | 6 + doc/scripts/jquery.min.map | 1 + doc/scripts/linenumber.js | 29 + doc/scripts/main.js | 101 + doc/scripts/prettify/Apache-License-2.0.txt | 202 + doc/scripts/prettify/lang-css.js | 2 + doc/scripts/prettify/prettify.js | 28 + doc/scripts/underscore-min.js | 6 + doc/scripts/underscore-min.map | 1 + doc/scrollEnd.js.html | 701 +++ doc/styles/bootstrap.min.css | 7 + doc/styles/jaguar.css | 466 ++ doc/styles/prettify-jsdoc.css | 111 + doc/styles/prettify-tomorrow.css | 132 + doc/styles/style.css | 13 + doc/transform.js.html | 847 +++ doc/visible.js.html | 784 +++ package.json | 2 +- 51 files changed, 53300 insertions(+), 8 deletions(-) create mode 100644 dist/eg.js create mode 100644 dist/eg.min.js create mode 100644 dist/pkgd/eg.pkgd.min.js create mode 100644 dist/pkgd/flicking.pkgd.min.js create mode 100644 dist/pkgd/infiniteGrid.pkgd.min.js create mode 100644 doc/class.js.html create mode 100644 doc/component.js.html create mode 100644 doc/cssPrefix.js.html create mode 100644 doc/eg.Class.html create mode 100644 doc/eg.Component.html create mode 100644 doc/eg.Flicking.html create mode 100644 doc/eg.InfiniteGrid.html create mode 100644 doc/eg.MovableCoord.html create mode 100644 doc/eg.Visible.html create mode 100644 doc/eg.html create mode 100644 doc/eg.js.html create mode 100644 doc/flicking.js.html create mode 100644 doc/fonts/glyphicons-halflings-regular.eot create mode 100644 doc/fonts/glyphicons-halflings-regular.svg create mode 100644 doc/fonts/glyphicons-halflings-regular.ttf create mode 100644 doc/fonts/glyphicons-halflings-regular.woff create mode 100644 doc/global.html create mode 100644 doc/index.html create mode 100644 doc/infiniteGrid.js.html create mode 100644 doc/jQuery.html create mode 100644 doc/module.js.html create mode 100644 doc/movableCoord.js.html create mode 100644 doc/pauseResume.js.html create mode 100644 doc/persist.js.html create mode 100644 doc/rotate.js.html create mode 100644 doc/scripts/bootstrap.min.js create mode 100644 doc/scripts/jquery.min.js create mode 100644 doc/scripts/jquery.min.map create mode 100644 doc/scripts/linenumber.js create mode 100644 doc/scripts/main.js create mode 100644 doc/scripts/prettify/Apache-License-2.0.txt create mode 100644 doc/scripts/prettify/lang-css.js create mode 100644 doc/scripts/prettify/prettify.js create mode 100644 doc/scripts/underscore-min.js create mode 100644 doc/scripts/underscore-min.map create mode 100644 doc/scrollEnd.js.html create mode 100644 doc/styles/bootstrap.min.css create mode 100644 doc/styles/jaguar.css create mode 100644 doc/styles/prettify-jsdoc.css create mode 100644 doc/styles/prettify-tomorrow.css create mode 100644 doc/styles/style.css create mode 100644 doc/transform.js.html create mode 100644 doc/visible.js.html diff --git a/.gitignore b/.gitignore index e2b130f3..3463f026 100644 --- a/.gitignore +++ b/.gitignore @@ -2,13 +2,10 @@ node_modules/ bower_components/ sample/ .DS_Store -report/ -temp/ -doc/ -dist/ -.idea/ -_site/ +report +temp *.log *.iml browserstack-run.pid config/browertstack.config.json +.idea/ \ No newline at end of file diff --git a/bower.json b/bower.json index 64290d85..f6de7a62 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "egjs", - "version": "1.2.0-snapshot", + "version": "1.3.0", "description": "Set of UI interactions, effects and utilities components library.", "authors": [ "NAVER corp" diff --git a/dist/eg.js b/dist/eg.js new file mode 100644 index 00000000..1b02d622 --- /dev/null +++ b/dist/eg.js @@ -0,0 +1,6015 @@ +/** +* Copyright (c) 2015 NAVER corp. +* egjs projects are licensed under the MIT license +* https://naver.github.io/egjs/license.txt +* +* egjs JavaScript library +* http://naver.github.io/egjs +* +* @version 1.3.0 +* @SHA-1 13e6ef5 (1.3.0-rc) +* +* For custom build use egjs-cli +* https://github.com/naver/egjs-cli +*/ +"use strict"; +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +(function(jQueryName, ns, global) { +var eg; + if (!global[ns]) { + global[ns] = {}; + } + eg = global[ns]; + + var $ = global[jQueryName]; + + var dependency = { + "jQuery": { + "url": "http://jquery.com/" + }, + "Hammer": { + "url": "http://hammerjs.github.io/" + } + }; + + // jscs:disable maximumLineLength + var templateMessage = [ + "[egjs] The {{name}} library must be loaded before {{componentName}}.", + "[egjs] For AMD environment (like RequireJS), \"{{name}}\" must be declared, which is required by {{componentName}}.", + "[egjs] The {{index}} argument of {{componentName}} is missing.\r\nDownload {{name}} from [{{url}}].", + "[egjs] The {{name}} parameter of {{componentName}} is not valid.\r\nPlease check and try again.", + "[egjs] The {{index}} argument of {{componentName}} is undefined.\r\nPlease check and try again." + ]; + + // jscs:enable maximumLineLength + + var ordinal = [ "1st", "2nd", "3rd"]; + + function changeOrdinal(index) { + return index > 2 ? (index + 1) + "th" : ordinal[index]; + } + + function replaceStr(str, obj) { + var i; + for (i in obj) { + str = str.replace(new RegExp("{{" + i + "}}","gi"), obj[i]); + } + return str; + } + + function checkDependency(componentName, di) { + var i = 0; + var l = di.length; + var message = []; + var paramList = []; + var require = global.require; + var dependencyInfo; + var param; + var messageInfo; + var isString; + var isUndefined; + var registedDependency; + var isNotGlobal; + var specifiedAMD; + + for (; i < l; i++) { + param = di[i]; + messageInfo = { + "index": changeOrdinal(i), + "name": param, + "componentName": componentName + }; + + isString = typeof di[i] === "string"; + isUndefined = di[i] === undefined; + registedDependency = isString && (dependencyInfo = dependency[di[i]]); + isNotGlobal = isString && dependencyInfo && !global[di[i]]; + specifiedAMD = isNotGlobal && + require && require.specified && require.specified(di[i]); + + // Message decision flow + // argument + // |--------------|--------------| + // undefined string !string&&!undefined + // | | | + // msg(4) | (OK) + // defined dependency + // | + // |-----------------------------| + // | | + // msg(3) in global + // | + // |------------------------------| + // use AMD (OK) + // | + // |------------------------------| + // msg(2) require.specified + // | + // |------------------------------| + // msg(1) require.defined + // | + // |------------------------------| + // msg(0) (OK) + + if (!isString && !isUndefined) { + paramList.push(param); + continue; + } + + if (specifiedAMD && require.defined(di[i])) { + param = require(di[i]); + paramList.push(param); + continue; + } + + if (specifiedAMD && !require.defined(di[i])) { + messageInfo.url = dependencyInfo.url; + message.push(replaceStr(templateMessage[0], messageInfo)); + continue; + } + + if (isNotGlobal && require && + require.specified && !require.specified(di[i])) { + messageInfo.url = dependencyInfo.url; + message.push(replaceStr(templateMessage[1], messageInfo)); + continue; + } + + if (isNotGlobal && !require) { + messageInfo.url = dependencyInfo.url; + message.push(replaceStr(templateMessage[2], messageInfo)); + continue; + } + + if (registedDependency && global[di[i]]) { + param = global[di[i]]; + paramList.push(param); + continue; + } + + if (isString && !dependencyInfo) { + message.push(replaceStr(templateMessage[3], messageInfo)); + continue; + } + + if (di[i] === undefined) { + message.push(replaceStr(templateMessage[4], messageInfo)); + continue; + } + } + + return [paramList, message]; + } + + function capitalizeFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + + function plugin(name) { + var upperCamelCase = capitalizeFirstLetter(name); + var events; + var special; + var componentMethodNames; + + if (!(eg[upperCamelCase] && eg[upperCamelCase].prototype && + eg[upperCamelCase].prototype._events)) { + return false; + } + + // jscs:disable validateLineBreaks, maximumLineLength + if ($.fn[name]) { + throw new Error("The name '" + upperCamelCase + "' has already been used and registered as plugin. Try with different one."); + } + + // jscs:enable validateLineBreaks, maximumLineLength + + // Extend method. + $.fn[name] = function(options) { + var ins; + var result; + if (typeof options === "string") { + ins = this.data(ns + "-" + name); + if (options === "instance") { + return ins; + } else { + result = ins[options].apply(ins, Array.prototype.slice.call(arguments, 1)); + return result === ins ? this : result; + } + } + + if (options === undefined || $.isPlainObject(options)) { + this.data(ns + "-" + name, new eg[upperCamelCase]( + this, options || {}, name + ":" + )); + } + return this; + }; + + componentMethodNames = { + trigger: "trigger", + add: "on", + remove: "off" + }; + events = eg[upperCamelCase].prototype._events(); + + for (var i in events) { + special = $.event.special[name + ":" + events[i]] = {}; + + // to not bind native event + special.setup = function() { + return true; + }; + + for (var j in componentMethodNames) { + // jscs:disable validateLineBreaks, maximumLineLength + /*jshint loopfunc: true */ + special[j] = (function(componentMethodName) { + return function(event, param) { + $(this).data(ns + "-" + name)[componentMethodName]( + event.type, + componentMethodName === "trigger" ? param : event.handler + ); + return false; + }; + })(componentMethodNames[j]); + + // jscs:enable validateLineBreaks, maximumLineLength + } + } + } + + var warn = function(msg) { + /* jshint ignore:start */ + if (global.console && global.console.warn) { + warn = function(msg) { + global.console.warn(msg); + }; + } else { + warn = function(msg) { + }; + } + /* jshint ignore:end */ + warn(msg); + }; + + /** + * Regist module. + * @private + */ + if (!eg.module) { + eg.module = function(name, di, fp) { + var result = checkDependency(name, di); + if (result[1].length) { + warn(result[1].join("\r\n")); + } else { + fp.apply(global, result[0]); + plugin(name); + } + }; + } + +})("jQuery", "eg", window); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +eg.module("agent", [eg], function(ns) { +/* + * {String|RegEx} criteria + * {String|RegEx} identity + * {String} versionSearch + * {String} versionAlias + * {String|RegEx} webviewBrowserVersion + * {String|RegEx} webviewToken + */ + var userAgentRules = { + browser: [{ + criteria: "PhantomJS", + identity: "PhantomJS" + }, { + criteria: /Edge/, + identity: "Edge", + versionSearch: "Edge" + }, { + criteria: /MSIE|Trident|Windows Phone/, + identity: "IE", + versionSearch: "IEMobile|MSIE|rv" + }, { + criteria: /SAMSUNG|SamsungBrowser/, + identity: "SBrowser", + versionSearch: "Chrome" + }, { + criteria: /Chrome|CriOS/, + identity: "Chrome" + }, { + criteria: /Android/, + identity: "default" + }, { + criteria: /iPhone|iPad/, + identity: "Safari", + versionSearch: "Version" + }, { + criteria: "Apple", + identity: "Safari", + versionSearch: "Version" + }, { + criteria: "Firefox", + identity: "Firefox" + }], + os: [{ + criteria: /Windows Phone|Windows NT/, + identity: "Window", + versionSearch: "Windows Phone|Windows NT" + }, { + criteria: "Windows 2000", + identity: "Window", + versionAlias: "5.0" + }, { + criteria: /iPhone|iPad/, + identity: "iOS", + versionSearch: "iPhone OS|CPU OS" + }, { + criteria: "Mac", + versionSearch: "OS X", + identity: "MAC" + }, { + criteria: /Android/, + identity: "Android" + }], + + // Webview check condition + // ios: If has no version information + // Android 5.0 && chrome 40+: Presence of "; wv" in userAgent + // Under android 5.0: Presence of "NAVER" or "Daum" in userAgent + webview: [{ + criteria: /iPhone|iPad/, + browserVersionSearch: "Version", + webviewBrowserVersion: /-1/ + }, { + criteria: /iPhone|iPad|Android/, + webviewToken: /NAVER|DAUM|; wv/ + + }], + defaultString: { + browser: { + version: "-1", + name: "default" + }, + os: { + version: "-1", + name: "unknown" + } + } + }; + + var UA; + + function getBrowserName(browserRules) { + return getIdentityStringFromArray( + browserRules, + userAgentRules.defaultString.browser + ); + } + + function getBrowserVersion(browserName) { + var browserVersion; + var versionToken; + + if (!browserName) { + return; + } + versionToken = getBrowserRule(browserName).versionSearch || browserName; + browserVersion = extractBrowserVersion(versionToken, UA); + return browserVersion; + } + + function extractBrowserVersion(versionToken, ua) { + var browserVersion = userAgentRules.defaultString.browser.version; + var versionIndex; + var versionTokenIndex; + var versionRegexResult = + (new RegExp("(" + versionToken + ")", "i")).exec(ua); + + if (!versionRegexResult) { + return browserVersion; + } + + versionTokenIndex = versionRegexResult.index; + versionToken = versionRegexResult[0]; + if (versionTokenIndex > -1) { + versionIndex = versionTokenIndex + versionToken.length + 1; + browserVersion = ua.substring(versionIndex) + .split(" ")[0] + .replace(/_/g, ".") + .replace(/\;|\)/g, ""); + } + return browserVersion; + } + + function getOSName(osRules) { + return getIdentityStringFromArray( + osRules, + userAgentRules.defaultString.os + ); + } + + function getOSVersion(osName) { + var ua = UA; + var osRule = getOSRule(osName) || {}; + var defaultOSVersion = userAgentRules.defaultString.os.version; + var osVersion; + var osVersionToken; + var osVersionRegex; + var osVersionRegexResult; + if (!osName) { + return; + } + if (osRule.versionAlias) { + return osRule.versionAlias; + } + osVersionToken = osRule.versionSearch || osName; + osVersionRegex = + new RegExp( + "(" + osVersionToken + ")\\s([\\d_\\.]+|\\d_0)", + "i" + ); + + osVersionRegexResult = osVersionRegex.exec(ua); + if (osVersionRegexResult) { + osVersion = osVersionRegex.exec(ua)[2].replace(/_/g, ".") + .replace(/\;|\)/g, ""); + } + return osVersion || defaultOSVersion; + } + + function getOSRule(osName) { + return getRule(userAgentRules.os, osName); + } + + function getBrowserRule(browserName) { + return getRule(userAgentRules.browser, browserName); + } + + function getRule(rules, targetIdentity) { + var criteria; + var identityMatched; + + for (var i = 0, rule; rule = rules[i]; i++) { + criteria = rule.criteria; + identityMatched = + new RegExp(rule.identity, "i").test(targetIdentity); + if (criteria ? + identityMatched && isMatched(UA, criteria) : + identityMatched) { + return rule; + } + } + } + function getIdentityStringFromArray(rules, defaultStrings) { + for (var i = 0, rule; rule = rules[i]; i++) { + if (isMatched(UA, rule.criteria)) { + return rule.identity || defaultStrings.name; + } + } + return defaultStrings.name; + } + function isMatched(base, target) { + return target && + target.test ? !!target.test(base) : base.indexOf(target) > -1; + } + function isWebview() { + var ua = UA; + var webviewRules = userAgentRules.webview; + var ret = false; + var browserVersion; + + for (var i = 0, rule; rule = webviewRules[i]; i++) { + if (!isMatched(ua, rule.criteria)) { + continue; + } + + browserVersion = + extractBrowserVersion(rule.browserVersionSearch, ua); + + if (isMatched(ua, rule.webviewToken) || + isMatched(browserVersion, rule.webviewBrowserVersion)) { + ret = true; + break; + } + } + + return ret; + } + + ns.Agent = { + "create": function(useragent) { + this.ua = UA = useragent; + var agent = { + os: {}, + browser: {} + }; + agent.browser.name = getBrowserName(userAgentRules.browser); + agent.browser.version = getBrowserVersion(agent.browser.name); + agent.os.name = getOSName(userAgentRules.os); + agent.os.version = getOSVersion(agent.os.name); + agent.browser.webview = isWebview(); + + agent.browser.name = agent.browser.name.toLowerCase(); + agent.os.name = agent.os.name.toLowerCase(); + + return agent; + } + }; +}); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +eg.module("eg", ["jQuery", eg, window, eg.Agent], function($, ns, global, Agent) { +var raf = global.requestAnimationFrame || global.webkitRequestAnimationFrame || + global.mozRequestAnimationFrame || global.msRequestAnimationFrame; + var caf = global.cancelAnimationFrame || global.webkitCancelAnimationFrame || + global.mozCancelAnimationFrame || global.msCancelAnimationFrame; + + if (raf && !caf) { + var keyInfo = {}; + var oldraf = raf; + raf = function(callback) { + function wrapCallback() { + if (keyInfo[key]) { + callback(); + } + } + var key = oldraf(wrapCallback); + keyInfo[key] = true; + return key; + }; + caf = function(key) { + delete keyInfo[key]; + }; + } else if (!(raf && caf)) { + raf = function(callback) { + return global.setTimeout(callback, 16); + }; + caf = global.clearTimeout; + } + + function resultCache(scope, name, param, defaultValue) { + var method = scope.hook[name]; + if (method) { + defaultValue = method.apply(scope, param); + } + + scope[name] = function() { + var method = scope.hook[name]; + if (method) { + return method.apply(scope, param); + } + return defaultValue; + }; + return defaultValue; + } + + /** + * @namespace eg + * @group egjs + */ + + /** + * @name eg.VERSION + * @description The version numbers of egjs. + * @ko egjs 버전 + */ + ns.VERSION = "1.3.0"; + ns.hook = {}; + /** + * Returns the User-Agent information + * @ko user-agent 정보를 반환한다. + * @method eg#agent + * @return {Object} agent + * @return {Object} agent.os os Operating system information 운영체제 정보 + * @return {String} agent.os.name Operating system name (android, ios, window, mac) 운영체제 이름 (android, ios, window, mac) + * @return {String} agent.os.version Operating system version 운영체제 버전 + * @return {String} agent.browser Browser information 브라우저 정보 + * @return {String} agent.browser.name Browser name (default, safari, chrome, sbrowser, ie, firefox) 브라우저 이름 (default, safari, chrome, sbrowser, ie, firefox) + * @return {String} agent.browser.version Browser version 브라우저 버전 + * @return {String} agent.browser.webview Indicates whether a WebView browser is available웹뷰 브라우저 여부 + * @example +eg.agent(); +// { +// os : { +// name : "ios", +// version : "8.2" +// }, +// browser : { +// name : "safari", +// version : "8.2" +// nativeVersion : "-1" +// } +// } +eg.hook.agent = function(agent) { +if(agent.os.name === "naver") { + agent.browser.name = "inapp"; + return agent; +} +} + */ + ns.agent = function() { + var info = Agent.create(global.navigator.userAgent); + return resultCache(this, "agent", [info], info); + }; + + /** + * Returns the syntax of the translate style which is applied to CSS transition properties. + * + * @ko CSS 트랜지션 속성에 적용할 translate 스타일 구문을 반환한다 + * @method eg#translate + * @param {String} x Distance to move along the X axis x축을 따라 이동할 거리 + * @param {String} y Distance to move along the Y axis y축을 따라 이동할 거리 + * @param {Boolean} [isHA] Force hardware acceleration 하드웨어 가속 사용 여부 + * @return {String} Syntax of the translate style translate 스타일 구문 + * @example +eg.translate('10px', '200%'); // translate(10px,200%); +eg.translate('10px', '200%', true); // translate3d(10px,200%,0); + */ + ns.translate = function(x, y, isHA) { + isHA = isHA || false; + return "translate" + (isHA ? + "3d(" : "(") + x + "," + y + (isHA ? ",0)" : + ")"); + }; + + /** + * Checks whether hardware acceleration is enabled. + * + * @ko 하드웨어 가속을 사용할 수 있는 환경인지 확인한다 + * @method eg#isHWAccelerable + * @return {Boolean} Indicates whether hardware acceleration is enabled. 하드웨어 가속 사용 가능 여부 + * @example +eg.isHWAccelerable(); // Returns 'true' when hardware acceleration is supported + +// also, you can control return value +eg.hook.isHWAccelerable = function(defalutVal,agent) { +if(agent.os.name === "ios") { + // if os is 'ios', return value is 'false' + return false; +} else if(agent.browser.name === "chrome" ) { + // if browser is 'chrome', return value is 'true' + return true; +} +return defaultVal; +} + */ + ns.isHWAccelerable = function() { + var result = false; + var agent = ns.agent(); + var osVersion = agent.os.version; + var browser = agent.browser.name; + var browserVersion = agent.browser.version; + var useragent; + + // chrome 25- has a text blur bug (except Samsung's sbrowser) + if (browser.indexOf("chrome") !== -1) { + result = browserVersion >= "25"; + } else if (/ie|edge|firefox|safari|inapp/.test(browser)) { + result = true; + } else if (agent.os.name.indexOf("android") !== -1) { + // for Xiaomi + useragent = (Agent.ua.match(/\(.*\)/) || [null])[0]; + + // android 4.1+ blacklist + // EK-GN120 : Galaxy Camera, SM-G386F : Galaxy Core LTE + // SHW-M420 : Galaxy Nexus , SHW-M200 : NexusS , GT-S7562 : Galaxy S duos + result = (osVersion >= "4.1.0" && !/EK-GN120|SM-G386F/.test(useragent)) || + (osVersion >= "4.0.3" && + /SHW-|SHV-|GT-|SCH-|SGH-|SPH-|LG-F160|LG-F100|LG-F180|LG-F200|EK-|IM-A|LG-F240|LG-F260/.test(useragent) && !/SHW-M420|SHW-M200|GT-S7562/.test(useragent)); + } + return resultCache(this, "isHWAccelerable", [result, agent], result); + }; + + /** + * Checks whether CSS transition properties can be used. + * + * @ko CSS 트랜지션 속성을 사용할 수 있는 환경인지 확인한다. + * @method eg#isTransitional + * @return {Boolean} Indicates whether CSS transition properties can be used. CSS 트랜지션 속성 사용 가능 여부 + * @example +eg.isTransitional(); // Returns 'true' when CSS transition is supported. + +// also, you can control return value +eg.hook.isTransitional = function(defaultVal, agent) { +if(agent.os.name === "ios") { + // if os is 'ios', return value is 'false' + return false; +} else if(agent.browser.name === "chrome" ) { + // if browser is 'chrome', return value is 'true' + return true; +} +return defaultVal; +} + */ + ns.isTransitional = function() { + var result = false; + var agent = ns.agent(); + var browser = agent.browser.name; + + if (/chrome|firefox|sbrowser/.test(browser)) { + result = true; + } else { + switch (agent.os.name) { + case "ios" : + result = /safari|inapp/.test(browser) && + parseInt(agent.os.version, 10) < 6; + break; + case "window" : + result = /safari/.test(browser) || + (/ie/.test(browser) && + parseInt(agent.browser.nativeVersion, 10) >= 10); + break; + default : + result = /safari/.test(browser); + break; + } + } + return resultCache(this, "isTransitional", [result, agent], result); + }; + + // 1. user press one position on screen. + // 2. user moves to the other position on screen. + // 3. when user releases fingers on screen, 'click' event is fired at previous position. + ns._hasClickBug = function() { + var agent = ns.agent(); + var result = agent.browser.name === "safari"; + + return resultCache(this, "_hasClickBug", [result, agent], result); + }; + + /** + * A polyfill for the window.requestAnimationFrame() method. + * @ko window.requestAnimationFrame() 메서드의 polyfill 함수다 + * @method eg#requestAnimationFrame + * @param {Function} timer The function returned through a call to the requestAnimationFrame() method requestAnimationFrame() 메서드가 호출할 함수 + * @return {Number} ID of the requestAnimationFrame() method. requestAnimationFrame() 메서드의 아이디 + * @example + var timerId = eg.requestAnimationFrame(function() { + console.log("call"); + }); + * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame + */ + ns.requestAnimationFrame = function(fp) { + return raf(fp); + }; + /** + * A polyfill for the window.cancelAnimationFrame() method. It cancels an animation executed through a call to the requestAnimationFrame() method. + * @ko window.cancelAnimationFrame() 메서드의 polyfill 함수다. requestAnimationFrame() 메서드로 실행한 애니메이션을 중단한다 + * @method eg#cancelAnimationFrame + * @param {Number} key − The ID value returned through a call to the requestAnimationFrame() method. requestAnimationFrame() 메서드가 반환한 아이디 값 + * @example + eg.cancelAnimationFrame(timerId); + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame + */ + ns.cancelAnimationFrame = function(key) { + caf(key); + }; + + $.extend($.easing, { + easeOutCubic: function(p) { + return 1 - Math.pow(1 - p, 3); + } + }); +}); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +eg.module("class", [eg], function(ns) { +/** + * + * A module used to implement an application in object-oriented programming style + * @group egjs + * @ko 애플리케이션을 객체지향 프로그래밍 방식으로 구현할 때 사용하는 모듈 + * @class + * @name eg.Class + * + * @support {"ie": "7+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * @param {Object} def definition. Follow the rules under Literals of objects. Note that "construct" is a key reserved as a constructor function. 클래스를 정의하는 부분. 객체 리터럴 규칙을 따른다. 단, 'construct'는 생성자 함수로 예약된 키다 + * @param {Function} [def.construct] The constructor of the class 클래스 생성자 함수 (Optional) + * + * @example + var Some = eg.Class({ + //Class initialize + "construct" : function(val){ + this.val = val; + }, + "sumVal" : function(val) { + return this.val + val; + } + }); + + var some = new Some(5); + some.sumVal(5);//10 + */ + ns.Class = function(def) { + var typeClass = function typeClass() { + if (typeof def.construct === "function") { + def.construct.apply(this, arguments); + } + }; + + typeClass.prototype = def; + + /** + * Returns an instance of a class itself. + * @ko 클래스 자신의 인스턴스를 반환한다. + * @method eg.Class#instance + * @return {eg.Class} An instance of a class itself클래스 자신의 인스턴스 + */ + typeClass.prototype.instance = function() { + return this; + }; + + typeClass.prototype.constructor = typeClass; + return typeClass; + }; + /** + * Extends a class. + * @ko 클래스를 상속한다. + * @static + * @method eg.Class.extend + * @param {eg.Class} oSuperClass Superclass 상속하려는 클래스 + * @param {Object} def Class definition. Follow the rules under Literals of objects. Note that "construct" is a key reserved as a constructor function. 클래스를 정의하는 부분. 객체 리터럴 규칙을 따른다. 단, 'construct'는 생성자 함수로 예약된 키다. + * @param {Function} [def.construct] The constructor of the class 클래스 생성자 함수 (Optional) + * @return {eg.Class} An instance of a new class 새로 생성된 클래스의 인스턴스 + * @example + var Some = eg.Class.extend(eg.Component,{ + "some" : function(){} + }) + */ + + ns.Class.extend = function(superClass, def) { + var extendClass = function extendClass() { + // Call a parent constructor + superClass.apply(this, arguments); + + // Call a child constructor + if (typeof def.construct === "function") { + def.construct.apply(this, arguments); + } + }; + + var ExtProto = function() {}; + ExtProto.prototype = superClass.prototype; + + //extendClass.$super = oSuperClass.prototype; //'super' is supported not yet. + + var extProto = new ExtProto(); + for (var i in def) { + extProto[i] = def[i]; + } + extProto.constructor = extendClass; + extendClass.prototype = extProto; + + return extendClass; + }; +}); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +eg.module("component", [eg], function(ns) { +/** + * A class used to manage events and options in a component + * @class + * @group egjs + * @name eg.Component + * @ko 컴포넌트의 이벤트와 옵션을 관리할 수 있게 하는 클래스 + * + * @support {"ie": "7+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + */ + ns.Component = ns.Class({ + construct: function() { + // The reference count does not support yet. + // this.constructor.$count = (this.constructor.$count || 0) + 1; + this.eventHandler = {}; + this.options = {}; + }, + /** + * Sets options in a component or returns them. + * @ko 컴포넌트에 옵션을 설정하거나 옵션을 반환한다 + * @method eg.Component#option + * @param {String} key The key of the option옵션의 키 + * @param {Object} [value] The option value that corresponds to a given key 키에 해당하는 옵션값 + * @return {eg.Component|Object} An instance, an option value, or an option object of a component itself.
- If both key and value are used to set an option, it returns an instance of a component itself.
- If only a key is specified for the parameter, it returns the option value corresponding to a given key.
- If nothing is specified, it returns an option object. 컴포넌트 자신의 인스턴스나 옵션값, 옵션 객체.
- 키와 값으로 옵션을 설정하면 컴포넌트 자신의 인스턴스를 반환한다.
- 파라미터에 키만 설정하면 키에 해당하는 옵션값을 반환한다.
- 파라미터에 아무것도 설정하지 않으면 옵션 객체를 반환한다.
+ * @example + var Some = eg.Class.extend(eg.Component); + var some = new Some({ + "foo": 1, + "bar": 2, + }); + some.option("foo"); // return 1 + some.option("foo",3); // return some instance + some.option(); // return options object. + some.option({ + "foo" : 10, + "bar" : 20, + "baz" : 30 + }); // return some instance. + */ + option: function(key, value) { + if (arguments.length >= 2) { + this.options[key] = value; + return this; + } + + if (typeof key === "string") { + return this.options[key]; + } + + if (arguments.length === 0) { + return this.options; + } + + for (var i in key) { + this.options[i] = key[i]; + } + + return this; + }, + /** + * Triggers a custom event. + * @ko 커스텀 이벤트를 발생시킨다 + * @method eg.Component#trigger + * @param {String} eventName The name of the custom event to be triggered 발생할 커스텀 이벤트의 이름 + * @param {Object} customEvent Event data to be sent when triggering a custom event 커스텀 이벤트가 발생할 때 전달할 데이터 + * @return {Boolean} Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring. 이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다. + * @example + var Some = eg.Class.extend(eg.Component,{ + "some": function(){ + this.trigger("hi");// fire hi event. + } + }); + */ + trigger: function(eventName, customEvent) { + customEvent = customEvent || {}; + var handlerList = this.eventHandler[eventName] || []; + var hasHandlerList = handlerList.length > 0; + + if (!hasHandlerList) { + return true; + } + + // If detach method call in handler in first time then handeler list calls. + handlerList = handlerList.concat(); + + customEvent.eventType = eventName; + + var isCanceled = false; + var arg = [customEvent]; + var i; + var len; + var handler; + + customEvent.stop = function() { + isCanceled = true; + }; + + if ((len = arguments.length) > 2) { + arg = arg.concat(Array.prototype.slice.call(arguments, 2, len)); + } + + for (i = 0; handler = handlerList[i]; i++) { + handler.apply(this, arg); + } + + return !isCanceled; + }, + /** + * Checks whether an event has been attached to a component. + * @ko 컴포넌트에 이벤트가 등록됐는지 확인한다. + * @method eg.Component#hasOn + * @param {String} eventName The name of the event to be attached 등록 여부를 확인할 이벤트의 이름 + * @return {Boolean} Indicates whether the event is attached. 이벤트 등록 여부 + * @example + var Some = eg.Class.extend(eg.Component,{ + "some": function(){ + this.hasOn("hi");// check hi event. + } + }); + */ + hasOn: function(eventName) { + return !!this.eventHandler[eventName]; + }, + /** + * Attaches an event to a component. + * @ko 컴포넌트에 이벤트를 등록한다. + * @method eg.Component#on + * @param {eventName} eventName The name of the event to be attached 등록할 이벤트의 이름 + * @param {Function} handlerToAttach The handler function of the event to be attached 등록할 이벤트의 핸들러 함수 + * @return {eg.Component} An instance of a component itself컴포넌트 자신의 인스턴스 + * @example + var Some = eg.Class.extend(eg.Component,{ + "hi": function(){}, + "some": function(){ + this.on("hi",this.hi); //attach event + } + }); + */ + on: function(eventName, handlerToAttach) { + if (typeof eventName === "object" && + typeof handlerToAttach === "undefined") { + var eventHash = eventName; + var i; + for (i in eventHash) { + this.on(i, eventHash[i]); + } + return this; + } else if (typeof eventName === "string" && + typeof handlerToAttach === "function") { + var handlerList = this.eventHandler[eventName]; + + if (typeof handlerList === "undefined") { + handlerList = this.eventHandler[eventName] = []; + } + + handlerList.push(handlerToAttach); + } + + return this; + }, + /** + * Detaches an event from the component. + * @ko 컴포넌트에 등록된 이벤트를 해제한다 + * @method eg.Component#off + * @param {eventName} eventName The name of the event to be detached 해제할 이벤트의 이름 + * @param {Function} handlerToDetach The handler function of the event to be detached 해제할 이벤트의 핸들러 함수 + * @return {eg.Component} An instance of a component itself 컴포넌트 자신의 인스턴스 + * @example + var Some = eg.Class.extend(eg.Component,{ + "hi": function(){}, + "some": function(){ + this.off("hi",this.hi); //detach event + } + }); + */ + off: function(eventName, handlerToDetach) { + // All event detach. + if (arguments.length === 0) { + this.eventHandler = {}; + return this; + } + + // All handler of specific event detach. + if (typeof handlerToDetach === "undefined") { + if (typeof eventName === "string") { + this.eventHandler[eventName] = undefined; + return this; + } else { + var eventHash = eventName; + for (var i in eventHash) { + this.off(i, eventHash[i]); + } + return this; + } + } + + // The handler of specific event detach. + var handlerList = this.eventHandler[eventName]; + if (handlerList) { + var k; + var handlerFunction; + for (k = 0, handlerFunction; handlerFunction = handlerList[k]; k++) { + if (handlerFunction === handlerToDetach) { + handlerList = handlerList.splice(k, 1); + break; + } + } + } + + return this; + } + }); +}); + + +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +// jscs:disable maximumLineLength +eg.module("rotate", ["jQuery", eg, window, document], function($, ns, global, doc) { +// jscs:enable maximumLineLength + /** + * @namespace jQuery + * @group jQuery Extension + */ + /** + * This jQuery custom event is fired when device rotates. + * + * @ko 기기가 회전할 때 발생하는 jQuery 커스텀 이벤트 + * @name jQuery#rotate + * @event + * @param {Event} e The Event object in jQueryjQuery의 Event 객체 + * @param {Object} info The object of data to be sent when the event is fired이벤트가 발생할 때 전달되는 데이터 객체 + * @param {Boolean} info.isVertical The orientation of the device (true: portrait, false: landscape) 기기의 화면 방향(true: 수직 방향, false: 수평 방향) + * @support { "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * @example + * $(window).on("rotate",function(e, info){ + * info.isVertical; + * }); + * + */ + + var beforeScreenWidth = -1; + var beforeVertical = null; + var rotateTimer = null; + var agent = ns.agent(); + var isMobile = /android|ios/.test(agent.os.name); + + if (!isMobile) { + ns.isPortrait = function() { + return; + }; + + return; + } + + /** + * Return event name string for orientationChange according browser support + */ + var orientationChange = function() { + var type; + /** + * Some platform/broswer returns previous widht/height state value. For workaround, give some delays. + * + * Android bug: + * - Andorid 2.3 - Has orientationchange with bug. Needs 500ms delay. + * + * Note: Samsung's branded Android 2.3 + * When check orientationchange using resize event, could cause browser crash if user binds resize event on window + * + * - Android 2.2 - orientationchange fires twice(at first time width/height are not updated, but second returns well) + * - Lower than 2.2 - use resize event + * + * InApp bug: + * - Set 200ms delay + */ + if ((agent.os.name === "android" && agent.os.version === "2.1")) {//|| htInfo.galaxyTab2) + type = "resize"; + } else { + type = "onorientationchange" in global ? "orientationchange" : "resize"; + } + + orientationChange = function() { + return type; + }; + return type; + + }; + /** + * When viewport orientation is portrait, return true otherwise false + */ + function isVertical() { + var eventName = orientationChange(); + var screenWidth; + var degree; + var vertical; + + if (eventName === "resize") { + screenWidth = doc.documentElement.clientWidth; + + if (beforeScreenWidth === -1) { //first call isVertical + vertical = screenWidth < doc.documentElement.clientHeight; + } else { + if (screenWidth < beforeScreenWidth) { + vertical = true; + } else if (screenWidth === beforeScreenWidth) { + vertical = beforeVertical; + } else { + vertical = false; + } + } + } else { + degree = global.orientation; + if (degree === 0 || degree === 180) { + vertical = true; + } else if (degree === 90 || degree === -90) { + vertical = false; + } + } + return vertical; + } + + /** + * Trigger rotate event + */ + function triggerRotate() { + + var currentVertical = isVertical(); + if (isMobile) { + if (beforeVertical !== currentVertical) { + beforeVertical = currentVertical; + beforeScreenWidth = doc.documentElement.clientWidth; + $(global).trigger("rotate", { + isVertical: beforeVertical + }); + } + } + } + + /** + * Trigger event handler + */ + function handler(e) { + + var eventName = orientationChange(); + var delay; + var screenWidth; + + if (eventName === "resize") { + global.setTimeout(function() { + triggerRotate(); + }, 0); + } else { + delay = 300; + if (agent.os.name === "android") { + screenWidth = doc.documentElement.clientWidth; + if (e.type === "orientationchange" && screenWidth === beforeScreenWidth) { + global.setTimeout(function() { + handler(e); + }, 500); + + // When width value wasn't changed after firing orientationchange, then call handler again after 300ms. + return false; + } + } + + global.clearTimeout(rotateTimer); + rotateTimer = global.setTimeout(function() { + triggerRotate(); + }, delay); + } + } + + $.event.special.rotate = { + setup: function() { + beforeVertical = isVertical(); + beforeScreenWidth = doc.documentElement.clientWidth; + $(global).on(orientationChange(), handler); + }, + teardown: function() { + $(global).off(orientationChange(), handler); + }, + trigger: function(e) { + e.isVertical = beforeVertical; + } + }; + + /** + * Checks whether the current orientation of the device is portrait. + * @ko 기기의 화면이 수직 방향인지 확인한다 + * @method eg#isPortrait + * @return {Boolean} The orientation of the device (true: portrait, false: landscape) 기기의 화면 방향(true: 수직 방향, false: 수평 방향) + * @example +eg.isPortrait(); // Check if device is in portrait mode + */ + ns.isPortrait = isVertical; + + return { + "orientationChange": orientationChange, + "isVertical": isVertical, + "triggerRotate": triggerRotate, + "handler": handler + }; +}); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +// jscs:disable maximumLineLength +eg.module("scrollEnd", ["jQuery", eg, window], function($, ns, global) { +// jscs:eable maximumLineLength + /** + * A custom event in jQuery occurs when scroll ends. + * @ko 스크롤이 끝날 때 발생하는 jQuery 커스텀 이벤트 + * @name jQuery#scrollEnd + * @event + * @param {Event} e The Event object in jQuery jQuery의 Event 객체 + * @param {Object} info The object of data to be sent when the event is fired이벤트가 발생할 때 전달되는 데이터 객체 + * @param {Number} info.top The size of the vertical scroll pane (unit: px)세로 스크롤 영역의 크기(단위: px) + * @param {Number} info.left The size of horizontal scroll pane (unit: px)가로 스크롤 영역의 크기(단위: px) + * @support {"ie": "9+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * @example + * $(window).on("scrollend",function(e, info){ + * info.top; + * info.left; + * }); + * + */ + + var scrollEndTimer; + var rotateFlag = false; + + var CHROME = 3; + var TIMERBASE = 2; + var TOUCHBASE = 1; + var SCROLLBASE = 0; + + var latency = 250; + + var deviceType = getDeviceType(); + + $.event.special.scrollend = { + setup: function() { + attachEvent(); + }, + teardown: function() { + removeEvent(); + } + }; + + /** + * iOS & Safari: + * iOS7 and lower, scroll event occurs once when the scroll is stopped + * iOS8 and upper, scroll event occurs on every scroll + * Scroll event occurs when the rotation + * Android: + * Scroll event occurs on every scroll + * Scroll event occurs on rotation and should be ignored to handle + * @ko + * iOS & Safari : + * iOS 7.x 이하에서는 스크롤이 멈췄을때 scroll 이벤트 한번 발생 + * iOS 8.x 이상에서는 scroll 이벤트가 android 와 동일하게 스크롤시 매번 발생 + * 회전시 scroll 이벤트가 발생되어 이를 무시처리해야함 + * (orientationchange 에 의해 발생하는 scroll 이벤트 1회만 무시) + * Android : + * 스크롤시 scroll 이벤트 매번 발생 + * 회전시 scroll 이벤트가 발생되어 이를 무시 처리해야 함 + */ + function getDeviceType() { + var retValue = TIMERBASE; + var agent = ns.agent(); + var osInfo = agent.os; + var osVersion = parseInt(osInfo.version, 10); + var browserInfo = agent.browser; + + // webview : TIMERBASE + if (!browserInfo.webview) { + + // Browsers that trigger scroll event like scrollstop : SCROLLBASE + if (osInfo.name === "ios" && osVersion <= 7) { + retValue = SCROLLBASE; + } else if (osInfo.name === "android") { + if (browserInfo.name === "default" && osVersion <= 2.3) { + retValue = SCROLLBASE; + } + } + } + return retValue; + } + + function attachEvent() { + $(global).on("scroll", scroll); + $(global).on("orientationchange", onOrientationchange); + } + + function onOrientationchange() { + rotateFlag = true; + } + + function scroll() { + if (rotateFlag) { + rotateFlag = false; + return; + } + + switch (deviceType) { + case SCROLLBASE : + triggerScrollEnd(); + break; + case TIMERBASE : + triggerScrollEndAlways(); + break; + } + + } + + function triggerScrollEnd() { + $(global).trigger("scrollend", { + top: global.pageYOffset, + left: global.pageXOffset + }); + } + + function triggerScrollEndAlways() { + clearTimeout(scrollEndTimer); + scrollEndTimer = setTimeout(function() { + if (rotateFlag) { + rotateFlag = false; + return; + } + triggerScrollEnd(); + }, latency); + } + + function removeEvent() { + $(global).off("scroll", scroll); + $(global).off("orientationchange", onOrientationchange); + } + + return { + getDeviceType: getDeviceType, + CHROME: CHROME, + TIMERBASE: TIMERBASE, + TOUCHBASE: TOUCHBASE, + SCROLLBASE: SCROLLBASE + }; +}); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +/** + * A method that extends the .animate() method provided by jQuery. With this method, you can use the transform property and 3D acceleration + * @ko jQuery의animate() 메서드를 확장한 메서드. CSS의 transform 속성과 3D 가속을 사용할 수 있다. + * @name jQuery#animate + * @method + * @param {Object} properties An object composed of the CSS property and value which will be applied to an animation애니메이션을 적용할 CSS 속성과 값으로 구성된 객체 + * @param {Number|String} [duration=4000] Duration of the animation (unit: ms)애니메이션 진행 시간(단위: ms) + * @param {String} [easing="swing"] The easing function to apply to an animation애니메이션에 적용할 easing 함수 + * @param {Function} [complete] A function that is called once the animation is complete.애니메이션을 완료한 다음 호출할 함수 + * + * @example + * $("#box") + * .animate({"transform" : "translate3d(150px, 100px, 0px) rotate(20deg) scaleX(1)"} , 3000) + * .animate({"transform" : "+=translate3d(150px, 10%, -20px) rotate(20deg) scale3d(2, 4.2, 1)"} , 3000); + * @see {@link http://api.jquery.com/animate/} + * + * @support {"ie": "10+", "ch" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + */ +eg.module("transform", ["jQuery", window], function($) { +/** + * Get a 'px' converted value if it has a %. + * Otherwise it returns value appened with 'px'. + */ + function getConverted(val, base) { + var ret = val; + var num = val.match(/((-|\+)*[0-9]+)%/); + + if (num && num.length >= 1) { + ret = base * (parseFloat(num[1]) / 100) + "px"; + } else if (val.indexOf("px") === -1) { + ret = val + "px"; + } + + return ret; + } + + function correctUnit(transform, width, height) { + var m; + var ret = ""; + var arr = transform.split(")"); + + for (var i = 0, len = arr.length - 1; i < len; i++) { + var name = arr[i]; + + // '%' is only meaningful on translate. + if ((m = name.match(/(translate([XYZ]|3d)?|rotate)\(([^)]*)/)) && m.length > 1) { + if (m[1] === "rotate") { + if (m[3].indexOf("deg") === -1) { + name = m[1] + "(" + m[3] + "deg"; + } + } else { + switch (m[2]) { + case "X": + name = m[1] + "(" + getConverted(m[3], width); + break; + case "Y": + name = m[1] + "(" + getConverted(m[3], height); + break; + case "Z": + + //Meaningless. Do nothing + break; + default://2d, 3d + var nums = m[3].split(","); + var bases = [width, height, 100]; + + for (var k = 0, l = nums.length; k < l; k++) { + nums[k] = getConverted(nums[k], bases[k]); + } + name = m[1] + "(" + nums.join(","); + break; + } + } + } + + name = " " + name + ")"; + ret += name; + } + + //Remove wrong '%'s and '+=' because it cannot be translated to a matrix. + ret = ret.replace("%", "").replace("+=", ""); + return ret; + } + + /** + * Parse a transform atom value. + * + * "30px" --> {num: 30, unit: "px"} + * + * Because calculation of string number is heavy, + * In advance, convert a string number to a float number with an unit for the use of transformByPos, + * which is called very frequently. + */ + function toParsedFloat(val) { + var m = val.match(/((-|\+)*[\d|\.]+)(px|deg|rad)*/); + if (m && m.length >= 1) { + return {"num": parseFloat(m[1]), "unit": m[3]}; + } + } + + function getTransformGenerateFunction(transform) { + var splitted = transform.split(")"); + var list = []; + + //Make parsed transform list. + for (var i = 0, len = splitted.length - 1; i < len; i++) { + var parsed = parseStyle(splitted[i]); + + parsed[1] = $.map(parsed[1], toParsedFloat); + list.push(parsed); + } + + return function transformByPos(pos) { + var transform = ""; + var defaultVal = 0; + + $.each(list, function(i) { + if (list[i][0].indexOf("scale") >= 0) { + defaultVal = 1; + } else { + defaultVal = 0; + } + + var valStr = $.map(list[i][1], function(value) { + var val = value.num; + defaultVal === 1 && (val = val - 1); + return (defaultVal + val * pos) + (value.unit || ""); + }).join(","); + + transform += list[i][0] + "(" + valStr + ") "; + }); + + return transform; + }; + } + + function rateFn(element, startTf, endTf) { + var isRelative = endTf.indexOf("+=") >= 0; + var start; + var end; + var basePos; + + // Convert translate unit to 'px'. + endTf = correctUnit(endTf, + parseFloat($.css(element, "width")) || 0, + parseFloat($.css(element, "height")) || 0); + + if (isRelative) { + start = (!startTf || startTf === "none") ? + "matrix(1, 0, 0, 1, 0, 0)" : startTf; + end = getTransformGenerateFunction(endTf); + } else { + start = toMatrixArray(startTf); + basePos = toMatrixArray("none");//transform base-position + + //If the type of matrix is not equal, then match to matrix3d + if (start[1].length < basePos[1].length) { + start = toMatrix3d(start); + } else if (start[1].length > basePos[1].length) { + basePos = toMatrix3d(basePos); + } + + end = getTransformGenerateFunction(endTf); + } + + return function(pos) { + var result = []; + var ret = "";//matrix for interpolated value from current to base(1, 0, 0, 1, 0, 0) + + if (isRelative) { + // This means a muliply between a matrix and a transform. + return start + end(pos); + } + + if (pos === 1) { + ret = data2String(basePos); + } else { + for (var i = 0, s, e, l = start[1].length; i < l; i++) { + s = parseFloat(start[1][i]); + e = parseFloat(basePos[1][i]); + + result.push(s + (e - s) * pos); + } + + ret = data2String([start[0], result]); + } + + return ret + end(pos); + }; + } + + /** + * ["translate", [100, 0]] --> translate(100px, 0) + * {translate : [100, 0]} --> translate(100px, 0) + * {matrix : [1, 0, 1, 0, 100, 0]} --> matrix(1, 0, 1, 0, 100, 0) + */ + function data2String(property) { + var name; + var tmp = []; + + if ($.isArray(property)) { + name = property[0]; + return name + "(" + property[1].join(unit(name) + ",") + unit(name) + ")"; + } else { + for (name in property) { + tmp.push(name); + } + + return $.map(tmp, function(v) { + return v + "(" + property[v] + unit(v) + ")"; + }).join(" "); + } + } + + function unit(name) { + return name.indexOf("translate") >= 0 ? + "px" : name.indexOf("rotate") >= 0 ? "deg" : ""; + } + + // ["translate" , ["10", "20"]] + function parseStyle(property) { + var m = property.match(/(\b\w+?)\((\s*[^\)]+)/); + var name; + var value; + var result = ["",""]; + + if (m && m.length > 2) { + name = m[1]; + value = m[2].split(","); + value = $.map(value, function(v) { + return $.trim(v); + }); + result = [ $.trim(name), value ]; + } + return result; + } + + /** + * Convert matrix string to array type. + * + * eg. matrix(1, 0, 0, 1, 0, 0) ==> ["matrix", [1, 0, 0, 1, 0, 0]] + * matrix3d(1,0,0,0,0,1,-2.44929e-16,0,0,2.44929e-16,1,0,0,0,0,1) + */ + function toMatrixArray(matrixStr) { + var matched; + + if (!matrixStr || matrixStr === "none") { + return ["matrix", [ "1", "0", "0", "1", "0", "0"] ]; + } + + matrixStr = matrixStr.replace(/\s/g, ""); + matched = matrixStr.match(/(matrix)(3d)*\((.*)\)/); + + return [matched[1] + (matched[2] || ""), matched[3].split(",")]; + } + + function toMatrix3d(matrix) { + var name = matrix[0]; + var val = matrix[1]; + + if (name === "matrix3d") { + return matrix; + } + + // matrix(a, b, c, d, tx, ty) is a shorthand for matrix3d(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1) + return [ + name + "3d", [val[0], val[1], "0", "0", + val[2], val[3], "0", "0", + "0", "0", "1", "0", + val[4], val[5], "0", "1"] + ]; + } + + $.fx.step.transform = function(fx) { + fx.rateFn = fx.rateFn || rateFn(fx.elem, fx.start, fx.end); + $.style(fx.elem, "transform", fx.rateFn(fx.pos)); + }; + + // All of this interfaces are functions for unit testing. + return { + toMatrix: toMatrixArray, + toMatrix3d: toMatrix3d + }; +}); + +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +eg.module("cssPrefix", ["jQuery", document], function($, doc) { +/** + * Apply css prefix cssHooks + * @ko 자동으로 css prefix가 적용되지 않는 jQuery 1.4.3 ~ 1.8.x에서 css prefix을 자동으로 등록하는 cssHooks이다. + * + * @name jQuery#cssPrefix + * @method + * + * * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * @example + * $("#ID").css("transform", "translate('10px', '10px'); + * $("#ID").css("Transform", "translate('10px', '10px'); + * $("#ID").css("webkitTransform", "translate('10px', '10px'); + * $("#ID").css("transform"); + * $("#ID").css("webkitTransform"); + */ + + if (!$.cssHooks) { + throw (new Error("jQuery 1.4.3+ is needed for this plugin to work")); + } + + // run in jQuery 1.8.x below + var matchTest = ($.fn.jquery.match(/^\d\.\d+/) || [])[0]; + if (!matchTest || +matchTest.replace(/\D/, "") >= 18) { + return; + } + + var cssPrefixes = [ "Webkit", "Moz", "O", "ms" ]; + var acts = ["transitionProperty", "transitionDuration", "transition", + "transform", "transitionTimingFunction"]; + + var vendorPrefix = (function() { + var bodyStyle = (doc.head || doc.getElementsByTagName("head")[0]).style; + for (var i = 0, len = cssPrefixes.length ; i < len ; i++) { + if (cssPrefixes[i] + "Transition" in bodyStyle) { + return cssPrefixes[i]; + } + } + })(); + + // ie7, 8 - transform and transition are not supported + // ie9 - transition not supported + if (!vendorPrefix) { + return; + } + + // If "ms" using "Ms" property in the get function + var setCssHooks = function(prop) { + var upperProp = prop.charAt(0).toUpperCase() + prop.slice(1); + var vendorProp = vendorPrefix + upperProp; + var getVendorProp = vendorPrefix === "ms" ? "Ms" + upperProp : vendorProp; + + $.cssHooks[upperProp] = + $.cssHooks[vendorPrefix.toLowerCase() + upperProp] = + $.cssHooks[prop] = { + get: function(elem, computed) { + return computed ? $.css(elem, getVendorProp) : elem.style[vendorProp]; + }, + set: function(elem, value) { + elem.style[vendorProp] = value; + } + }; + }; + + for (var n = 0, actsLen = acts.length; n < actsLen; n++) { + setCssHooks(acts[n]); + } + + return { + vendorPrefix: vendorPrefix, + setCssHooks: setCssHooks + }; + +}); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ +eg.module("pauseResume", ["jQuery"], function($) { +var animateFn = $.fn.animate; + var stopFn = $.fn.stop; + var delayFn = $.fn.delay; + var uuid = 1; + + function AniProperty(type, el, prop, optall) { + this.el = el; + this.opt = optall; + this.start = -1; + this.elapsed = 0; + this.paused = false; + this.uuid = uuid++; + this.easingNames = []; + this.prop = prop; + this.type = type; + } + + /** + * Generate a new absolute value maker. + * + * function to avoid JS Hint error "Don't make functions within a loop" + */ + function generateAbsoluteValMaker(prevValue, propName, sign) { + return function absoluteValMaker(match) { + if (!prevValue || prevValue === "auto") { + // Empty strings, null, undefined and "auto" are converted to 0. + // This solution is somewhat extracted from jQuery Tween.propHooks._default.get + // TODO: Should we consider adopting a Tween.propHooks? + prevValue = 0; + } else { + prevValue = parseFloat(prevValue); + } + return prevValue + (match * sign); + }; + } + + AniProperty.prototype.init = function() { + var currValue; + this.start = $.now(); + this.elapsed = 0; + + for (var propName in this.prop) { + var propValue = this.prop[propName]; + var markIndex; + var sign; + + // DO NOT SUPPORT TRANSFORM YET + // TODO: convert from relative value to absolute value on transform + if (propName === "transform") { + continue; + } + + //If it has a absoulte value. + if (typeof propValue !== "string" || + (markIndex = propValue.search(/[+|-]=/)) < 0) { + // this.prop[propName] = propValue; + continue; + } + + //If it has a relative value + sign = propValue.charAt(markIndex) === "-" ? -1 : 1; + + // Current value + currValue = $.css(this.el, propName); + + // CurrValue + (relativeValue) + this.prop[propName] = propValue + .replace(/([-|+])*([\d|\.])+/g, + generateAbsoluteValMaker(currValue, propName, sign)) + .replace(/[-|+]+=/g, ""); + } + }; + + AniProperty.prototype.addEasingFn = function(easingName) { + this.easingNames.push(easingName); + }; + + AniProperty.prototype.clearEasingFn = function() { + var easing; + while (easing = this.easingNames.shift()) { + delete $.easing[easing]; + } + this.easingNames = []; + }; + + function addAniProperty(type, el, prop, optall) { + var newProp; + + newProp = new AniProperty(type, el, prop, optall); + el.__aniProps = el.__aniProps || []; + + //Animation is excuted immediately. + if (el.__aniProps.length === 0) { + newProp.init(); + } + el.__aniProps.push(newProp); + } + + function removeAniProperty(el) { + var removeProp = el.__aniProps.shift(); + removeProp && removeProp.clearEasingFn(); + + el.__aniProps[0] && el.__aniProps[0].init(); + } + + $.fn.animate = function(prop, speed, easing, callback) { + return this.each(function() { + //optall should be made for each elements. + var optall = $.speed(speed, easing, callback); + var userCallback = optall.old;//hook a user callback. + + //Override to check current animation is done. + optall.complete = function() { + //Dequeue animation property that was ended. + var removeProp = this.__aniProps.shift(); + removeProp.clearEasingFn(); + + // Callback should be called before aniProps.init() + if (userCallback && typeof userCallback === "function") { + userCallback.call(this); + } + + // If next ani property exists + this.__aniProps[0] && this.__aniProps[0].init(); + }; + + //Queue animation property to recover the current animation. + addAniProperty("animate", this, prop, optall); + animateFn.call($(this), prop, optall); + }); + + // TODO: Below code is more reasonable? + // return animateFn.call(this, prop, optall); // and declare optall at outside this.each loop. + }; + + // Check if this element can be paused/resume. + function getStatus(el) { + if (!el.__aniProps || el.__aniProps.length === 0) { + // Current element doesn't have animation information. + // Check 'animate' is applied to this element. + return "empty"; + } + + return el.__aniProps[0].paused ? "paused" : "inprogress"; + } + + /** + * Set a timer to delay execution of subsequent items in the queue. + * And it internally manages "fx"queue to support pause/resume if "fx" type. + * + * @param {Number} An integer indicating the number of milliseconds to delay execution of the next item in the queue. + * @param {String} A string containing the name of the queue. Defaults to fx, the standard effects queue. + */ + $.fn.delay = function(time, type) { + var t; + var isCallByResume = arguments[2];//internal used value. + + if (type && type !== "fx") { + return delayFn.call(this, time, type); + } + + t = parseInt(time, 10); + t = isNaN(t) ? 0 : t; + + return this.each(function() { + if (!isCallByResume) { + // Queue delay property to recover the current animation. + // Don't add property when delay is called by resume. + addAniProperty("delay", this, null, {duration: t}); + } + + var self = this; + delayFn.call($(this), time).queue(function(next) { + next(); + + // Remove delay property when delay has been expired. + removeAniProperty(self); + }); + }); + }; + + /** + * Pauses the animation executed through a call to the jQuery .animate() method. + * @ko jQuery의animate() 메서드가 실행한 애니메이션을 일시 정지한다 + * + * @name jQuery#pause + * @method + * @support {"ie": "10+", "ch" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + * @example + * $("#box").pause(); //paused the current animation + */ + $.fn.pause = function() { + return this.each(function() { + var p; + var type = "fx"; + + if (getStatus(this) !== "inprogress") { + return; + } + + //Clear fx-queue except 1 dummy function + //for promise not to be expired when calling stop() + $.queue(this, type || "fx", [$.noop]); + stopFn.call($(this)); + + //Remember current animation property + if (p = this.__aniProps[0]) { + p.elapsed += $.now() - p.start; + p.paused = true; + } + }); + }; + + /** + * Resumes the animation paused through a call to the pause() method. + * @ko pause() 메서드가 일시 정지한 애니메이션을 다시 실행한다 + * + * @name jQuery#resume + * @method + * @support {"ie": "10+", "ch" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + * @example + * $("#box").resume(); //resume the paused animation + */ + $.fn.resume = function() { + return this.each(function() { + var type = "fx"; + var p; + var i; + + if (getStatus(this) !== "paused") { + return; + } + + //Clear fx-queue, + //And this queue will be initialized by animate call. + $.queue(this, type || "fx", []); + + // Restore __aniProps + i = 0; + while (p = this.__aniProps[i]) { + // Restore easing status + if (p.elapsed > 0 && p.opt.easing) { + var resumePercent = p.elapsed / p.opt.duration; + var remainPercent = 1 - resumePercent; + var originalEasing = $.easing[p.opt.easing]; + var startEasingValue = originalEasing(resumePercent); + var scale = scaler([startEasingValue, 1], [0, 1]); + var newEasingName = p.opt.easing + "_" + p.uuid; + + // Make new easing function that continues from pause point. + $.easing[newEasingName] = generateNewEasingFunc( + resumePercent, remainPercent, scale, originalEasing); + p.opt.easing = newEasingName; + + //Store new easing function to clear it later. + p.addEasingFn(newEasingName); + } + + p.paused = false; + p.opt.duration -= p.elapsed; + + // If duration remains, request 'animate' with storing aniProps + if (p.opt.duration > 0 || p.elapsed === 0) { + i === 0 && p.init(); + + if (p.type === "delay") { + // pass last parameter 'true' not to add an aniProperty. + $(this).delay(p.opt.duration, "fx", true); + } else { + animateFn.call($(this), p.prop, p.opt); + } + } + + i++; + } + }); + }; + + /** + * Generate a new easing function. + * + * function to avoid JS Hint error "Don't make functions within a loop" + */ + function generateNewEasingFunc(resumePercent, remainPercent, scale, originalEasing) { + return function easingFunc(percent) { + var newPercent = resumePercent + remainPercent * percent; + return scale(originalEasing(newPercent)); + }; + } + + $.fn.stop = function(type, clearQueue) { + var clearQ = clearQueue; + stopFn.apply(this, arguments); + + if (typeof type !== "string") { + clearQ = type; + } + + return this.each(function() { + var p; + + // When this element was not animated properly, do nothing. + if (getStatus(this) === "empty") { + return; + } + + if (!clearQ) { + p = this.__aniProps.shift(); + p && p.clearEasingFn(); + } else { + //If clearQueue is requested, + //then all properties must be initialized + //for element not to be resumed. + while (p = this.__aniProps.shift()) { + p.clearEasingFn(); + } + this.__aniProps = []; + } + }); + }; + + jQuery.expr.filters.paused = function(elem) { + return getStatus(elem) === "paused"; + }; + + //Adopt linear scale from d3 + function scaler(domain, range) { + var u = uninterpolateNumber(domain[0], domain[1]); + var i = interpolateNumber(range[0], range[1]); + + return function(x) { + return i(u(x)); + }; + } + + function interpolateNumber(a, b) { + a = +a, b = +b; + return function(t) { + return a * (1 - t) + b * t; + }; + } + + function uninterpolateNumber(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return (x - a) / b; + }; + } +}); + +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +// jscs:disable maximumLineLength +eg.module("persist", ["jQuery", window, document], function($, global, doc) { +// jscs:enable maximumLineLength + var wp = global.performance; + var history = global.history; + var isNeeded = (function() { + var ua = global.navigator.userAgent; + var version = ua ? ua.match(/Android\s([^\;]*)/i) : null; + + /* + * a isNeeded value is + * - iOS: false, + * - Android 4.4+: true + * - Android 4.4 and less: false + */ + return !(/iPhone|iPad/.test(ua) || (version ? parseFloat(version.pop()) < 4.4 : true)); + })(); + + var JSON = global.JSON; + var CONST_PERSIST = "___persist___"; + var GLOBAL_KEY = "KEY" + CONST_PERSIST; + var $global = $(global); + var isPersisted = $global.attr(CONST_PERSIST) === true; + + // In case of IE8, TYPE_BACK_FORWARD is undefined. + var isBackForwardNavigated = (wp && wp.navigation && + (wp.navigation.type === (wp.navigation.TYPE_BACK_FORWARD || 2))); + var isSupportState = "replaceState" in history && "state" in history; + + var storage = (function() { + if (isStorageAvailable(global.sessionStorage)) { + return global.sessionStorage; + } else if (isStorageAvailable(global.localStorage)) { + return global.localStorage; + } + })(); + + function isStorageAvailable(storage) { + if (!storage) { + return; + } + var TMP_KEY = "__tmp__" + CONST_PERSIST; + + try { + // In case of iOS safari private mode, calling setItem on storage throws error + storage.setItem(TMP_KEY, CONST_PERSIST); + + // In Chrome incognito mode, can not get saved value + // In IE8, calling storage.getItem occasionally makes "Permission denied" error + return storage.getItem(TMP_KEY) === CONST_PERSIST; + } catch (e) { + return false; + } + } + if (!isSupportState && !storage) { + return; + } + + // jscs:disable maximumLineLength + /* jshint ignore:start */ + if (!JSON) { + console.warn( + "The JSON object is not supported in your browser.\r\n" + + "For work around use polyfill which can be found at:\r\n" + + "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#Polyfill"); + return; + } + /* jshint ignore:end */ + + // jscs:enable maximumLineLength + + function onPageshow(e) { + isPersisted = isPersisted || (e.originalEvent && e.originalEvent.persisted); + if (!isPersisted && isBackForwardNavigated) { + $global.trigger("persist"); + } else { + reset(); + } + } + + /* + * flush current history state + */ + function reset() { + setState(null); + } + /* + * Get state value + */ + function getState() { + var state; + var stateStr = storage ? + storage.getItem(global.location.href + CONST_PERSIST) : history.state; + + // the storage is clean + if (stateStr === null) { + return {}; + } + + // "null" is not a valid + var isValidStateStr = typeof stateStr === "string" && + stateStr.length > 0 && stateStr !== "null"; + var isValidType; + + try { + state = JSON.parse(stateStr); + + // like '[ ... ]', '1', '1.234', '"123"' is also not valid + isValidType = !($.type(state) !== "object" || state instanceof Array); + + if (!isValidStateStr || !isValidType) { + throw new Error(); + } + } catch (e) { + warnInvalidStorageValue(); + state = {}; + } + + // Note2 (Android 4.3) return value is null + return state; + } + + function warnInvalidStorageValue() { + /* jshint ignore:start */ + console.warn("window.history or session/localStorage has no valid " + + "format data to be handled in persist."); + /* jshint ignore:end */ + } + + function getStateByKey(key) { + var result = getState()[key]; + + // some device returns "null" or undefined + if (result === "null" || typeof result === "undefined") { + result = null; + } + return result; + } + /* + * Set state value + */ + function setState(state) { + if (storage) { + if (state) { + storage.setItem( + global.location.href + CONST_PERSIST, JSON.stringify(state)); + } else { + storage.removeItem(global.location.href + CONST_PERSIST); + } + } else { + try { + history.replaceState( + state === null ? null : JSON.stringify(state), + doc.title, + global.location.href + ); + } catch (e) { + /* jshint ignore:start */ + console.warn(e.message); + /* jshint ignore:end */ + } + } + + state ? $global.attr(CONST_PERSIST, true) : $global.attr(CONST_PERSIST, null); + } + + function setStateByKey(key, data) { + var beforeData = getState(); + beforeData[key] = data; + setState(beforeData); + } + /** + * Stores the current state of the web page in a default key using JSON. + * @ko 웹 페이지의 현재 상태를 기본 키에 JSON 형식으로 저장한다. + * @method jQuery.persist + * @deprecated since version 1.2.0 + * @support {"ie": "9+", "ch" : "latest", "ff" : "1.5+", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.2+ (except 3.x)"} + * @param {Object} state The state information of the web page written in JSON JSON 객체로 정의한 웹 페이지의 상태 정보 + * @example + $("a").on("click",function(e){ + e.preventdefault(); + // save state + $.persist(state); + }); + */ + /** + * Return stored state in global namespace as object + * @ko 디폴트 키에 저장된 상태를 반환한다. +` * @method jQuery.persist + * @deprecated since version 1.2.0 + * @return {Object} + * @example + $("a").on("click",function(e){ + e.preventdefault(); + // get state + var state = $.persist(); + }); + */ + /** + * Stores the current state of the web page using JSON. + * @ko 웹 페이지의 현재 상태를 JSON 형식으로 저장한다 + * @method jQuery.persist + * @param {String} key The key of the state information to be stored 저장할 상태 정보의 키 + * @param {Object} state The value to be stored in a given key키에 저장할 값 + * @example + $("a").on("click",function(e){ + e.preventdefault(); + // save state + $.persist("KEY",state); + }); + */ + /** + * Returns the state of stored web pages. + * @ko 저장된 웹 페이지의 상태를 반환한다 + * @method jQuery.persist + * @param {String} key The name of the key to be checked값을 확인할 키의 이름 + * @return {Object} The value of the key 키의 값 + * @example + $("a").on("click",function(e){ + e.preventdefault(); + // get state + var state = $.persist("KEY"); + }); + */ + $.persist = function(state) { + var key; + var data; + if (typeof state === "string") { + key = state; + data = arguments.length === 2 ? arguments[1] : null; + } else { + key = GLOBAL_KEY; + data = arguments.length === 1 ? state : null; + } + data && setStateByKey(key, data); + return getStateByKey(key); + }; + + /** + * Return whether you need "Persist" module by checking the bfCache support of the current browser + * @ko 현재 브라우저의 bfCache 지원여부에 따라 persist 모듈의 필요여부를 반환한다. + * @method $.persist.isApplicable + * @example + $.persist.isApplicable(); + */ + $.persist.isNeeded = function() { + return isNeeded; + }; + + // in case of reload + !isBackForwardNavigated && reset(); + + $.event.special.persist = { + setup: function() { + $global.on("pageshow", onPageshow); + }, + teardown: function() { + $global.off("pageshow", onPageshow); + }, + trigger: function(e) { + //If you use 'persist' event, you can get global-key only! + e.state = getStateByKey(GLOBAL_KEY); + } + }; + return { + "isBackForwardNavigated": isBackForwardNavigated, + "onPageshow": onPageshow, + "reset": reset, + "getState": getState, + "setState": setState, + "GLOBALKEY": GLOBAL_KEY + }; +}); +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +eg.module("visible", ["jQuery", eg, document], function($, ns, doc) { +/** + * A module used to check whether an element is visible in the base element or viewport. + * @ko 엘리먼트가 기준 엘리먼트나 뷰포트 안에 보이는지 확인하는 모듈 + * @class + * @name eg.Visible + * @extends eg.Component + * @group egjs + * + * @param {HTMLElement|String|jQuery} [element=document] A base element that detects if another element is visible엘리먼트가 보이는 기준 엘리먼트 + * @param {Object} options The option object of the eg.Visible moduleeg.Visible 모듈의 옵션 객체 + * @param {String} [options.targetClass="check_visible"] The class name of the element to be checked보이는지 확인할 엘리먼트의 클래스 이름 + * @param {Number} [options.expandSize=0] The size of the expanded area to be checked whether an element is visible. If this value is less than zero, the size of the area is smaller than that of the base element. 기준 엘리먼트의 경계를 넘어 엘리먼트가 보이는지 확인할 영역의 크기. 값이 0보다 작으면 엘리먼트가 보이는지 확인할 영역의 크기가 기준 엘리먼트보다 작아진다 + * @support {"ie": "7+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * + * @codepen {"id":"WbWzqq", "ko":"Visible 기본 예제", "en":"Visible basic example", "collectionId":"Ayrabj", "height" : 403} + */ + var EVENTS = { + "change": "change" + }; + ns.Visible = ns.Class.extend(ns.Component, { + _events: function() { + return EVENTS; + }, + construct: function(element, options, _prefix) { + this._prefix = _prefix || ""; + this.options = { + targetClass: "check_visible", + expandSize: 0 + }; + $.extend(this.options, options); + + this._wrapper = $(element)[0] || doc; + + // this._wrapper is Element, or may be Window + if (this._wrapper.nodeType && this._wrapper.nodeType === 1) { + this._getAreaRect = this._getWrapperRect; + } else { + this._getAreaRect = this._getWindowRect; + } + + this._targets = []; + this._timer = null; + this._supportElementsByClassName = (function() { + var dummy = doc.createElement("div"); + var dummies; + if (!dummy.getElementsByClassName) { + return false; + } + dummies = dummy.getElementsByClassName("dummy"); + dummy.innerHTML = ""; + return dummies.length === 1; + })(); + + this.refresh(); + }, + /** + * Updates the list of elements where the visibility property is to be checked + * @ko visibility 속성을 검사할 엘리먼트의 목록을 갱신한다 + * @method eg.Visible#refresh + * @return {eg.Visible} An instance of a module itself모듈 자신의 인스턴스 + * + * @remark + * If targets was added or removed from DOM tree, must call refresh method to update internal target list. + * 확인 대상이 영역 안에 추가되거나 삭제된 경우, 모듈내부에서 사용하는 확인 대상 목록을 이 메소드를 호출하여 갱신해야한다. + */ + refresh: function() { + if (this._supportElementsByClassName) { + this._targets = this._wrapper + .getElementsByClassName(this.options.targetClass); + this.refresh = function() { + return this; + }; + } else { + this.refresh = function() { + this._targets = $(this._wrapper) + .find("." + this.options.targetClass) + .get(); + return this; + }; + } + return this.refresh(); + }, + /** + * Checks whether the visibility property of the target elements has changed. The change event is fired when the property has changed. + * @ko 보이는지 확인할 대상 엘리먼트 목록의 visibility 속성이 변경됐는지 확인한다. 속성이 변경됐으면 change 이벤트가 발생한다 + * @method eg.Visible#check + * @param {Number} [delay=-1] Delay time. It is used to check the property after a method is called and a period of time has passed.속성 확인 지연 시간. 메서드를 호출하고 일정 시간이 지난 후에 속성을 확인할 때 사용한다 + * @return {eg.Visible} An instance of a module itself모듈 자신의 인스턴스 + */ + check: function(delay) { + if (typeof delay === "undefined") { + delay = -1; + } + clearTimeout(this._timer); + if (delay < 0) { + this._check(); + } else { + this._timer = setTimeout($.proxy(function() { + this._check(); + this._timer = null; + }, this), delay); + } + return this; + }, + _getWrapperRect: function() { + return this._wrapper.getBoundingClientRect(); + }, + _getWindowRect: function() { + // [IE7] document.documentElement.clientHeight has always value 0 (bug) + return { + top: 0, + left: 0, + bottom: doc.documentElement.clientHeight || + doc.body.clientHeight, + right: doc.documentElement.clientWidth || + doc.body.clientWidth + }; + }, + _reviseElements: function(target, i) { + if (this._supportElementsByClassName) { + this._reviseElements = function() { + return true; + }; + } else { + this._reviseElements = function(target, i) { + if (!$(target).hasClass(this.options.targetClass)) { + target.__VISIBLE__ = null; + this._targets.splice(i, 1); + return false; + } + return true; + }; + } + return this._reviseElements(target, i); + }, + _check: function() { + var expandSize = parseInt(this.options.expandSize, 10); + var visibles = []; + var invisibles = []; + var area = this._getAreaRect(); + + // Error Fix: Cannot set property top of # which has only a getter + area = $.extend({}, area); + + area.top -= expandSize; + area.left -= expandSize; + area.bottom += expandSize; + area.right += expandSize; + for (var i = this._targets.length - 1, target, targetArea, after, before; + target = this._targets[i] ; i--) { + targetArea = target.getBoundingClientRect(); + if (targetArea.width === 0 && targetArea.height === 0) { + continue; + } + if (this._reviseElements(target, i)) { + before = !!target.__VISIBLE__; + target.__VISIBLE__ = after = !( + targetArea.bottom < area.top || + area.bottom < targetArea.top || + targetArea.right < area.left || + area.right < targetArea.left + ); + (before !== after) && (after ? visibles : invisibles).unshift(target); + } + } + /** + * This event is fired when the event is compared with the last verified one and there is an element of which the visibility property has changed. + * @ko 마지막으로 확인한 결과와 비교해 visibility 속성이 변경된 엘리먼트가 있을 때 발생하는 이벤트 + * @name eg.Visible#change + * @event + * @param {Array} visible Visible elements (the element type is `HTMLElement`) 보이게 된 엘리먼트들 + * @param {Array} invisible Invisible elements (the element type is `HTMLElement`) 안 보이게 된 엘리먼트들 + */ + this.trigger(this._prefix + EVENTS.change, { + visible: visibles, + invisible: invisibles + }); + }, + destroy: function() { + this.off(); + this._targets = []; + this._wrapper = this._timer = null; + } + }); +}); +/** + * A jQuery custom event of the eg.Visible module. This event is fired when the event is compared with the last verified one and there is an element of which the visibility property has changed. + * + * @ko eg.Visible 모듈의 jQuery 커스텀 이벤트. 마지막으로 확인한 결과와 비교해 visibility 속성이 변경된 엘리먼트가 있을 때 발생한다 + * @name jQuery#visible:change + * @event + * @example + // create + $("body").visible(); + + // event + $("body").on("visible:change",callback); + $("body").off("visible:change",callback); + $("body").trigger("visible:change",callback); + * @see eg.Visble + */ +/** + * A jQuery plugin available in the eg.Visible module. + * @ko eg.Visible 모듈의 jQuery 플러그인 + * @method jQuery.visible + * @example + // create + $("body").visible(); + + // event + $("body").on("visible:change",callback); + $("body").off("visible:change",callback); + $("body").trigger("visible:change",callback); + + // method + $("body").visible("option","circular",true); //Set option + $("body").visible("instance"); // Return flicking instance + $("body").visible("check",10); // Check to change target elements. + * @see eg.Visble#event:change + */ + +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +// jscs:disable maximumLineLength +eg.module("movableCoord", ["jQuery", eg, window, "Hammer"], function($, ns, global, HM) { +var SUPPORT_TOUCH = "ontouchstart" in global; + + // jscs:enable maximumLineLength + /** + * A module used to change the information of user action entered by various input devices such as touch screen or mouse into logical coordinates within the virtual coordinate system. The coordinate information sorted by time events occurred is provided if animations are made by user actions. You can implement a user interface by applying the logical coordinates provided. For more information on the eg.MovableCoord module, see demos. + * @group egjs + * @ko 터치 입력 장치나 마우스와 같은 다양한 입력 장치로 전달 받은 사용자의 동작을 가상 좌표계의 논리적 좌표로 변경하는 모듈. 사용자의 동작으로 애니메이션이 일어나면 시간순으로 변경되는 좌표 정보도 제공한다. 변경된 논리적 좌표를 반영해 UI를 구현할 수 있다. eg.MovableCoord 모듈의 자세한 작동 방식은 데모를 참고한다. + * @class + * @name eg.MovableCoord + * @extends eg.Component + * + * @param {Object} options The option object of the eg.MovableCoord moduleeg.MovableCoord 모듈의 옵션 객체 + * @param {Array} options.min The minimum value of X and Y coordinates 좌표계의 최솟값 + * @param {Number} [options.min.0=0] The X coordinate of the minimum 최소 x좌표 + * @param {Number} [options.min.1=0] The Y coordinate of the minimum 최소 y좌표 + * + * @param {Array} options.max The maximum value of X and Y coordinates 좌표계의 최댓값 + * @param {Number} [options.max.0=100] The X coordinate of the maximum최대 x좌표 + * @param {Number} [options.max.1=100] The Y coordinate of the maximum최대 y좌표 + * + * @param {Array} options.bounce The size of bouncing area. The coordinates can exceed the coordinate area as much as the bouncing area based on user action. If the coordinates does not exceed the bouncing area when an element is dragged, the coordinates where bouncing effects are applied are retuned back into the coordinate area바운스 영역의 크기. 사용자의 동작에 따라 좌표가 좌표 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 사용자가 끌어다 놓는 동작을 했을 때 좌표가 바운스 영역에 있으면, 바운스 효과가 적용된 좌표가 다시 좌표 영역 안으로 들어온다 + * @param {Boolean} [options.bounce.0=10] The size of top area 위쪽 바운스 영역의 크기 + * @param {Boolean} [options.bounce.1=10] The size of right area 오른쪽 바운스 영역의 크기 + * @param {Boolean} [options.bounce.2=10] The size of bottom area 아래쪽 바운스 영역의 크기 + * @param {Boolean} [options.bounce.3=10] The size of left area 왼쪽 바운스 영역의 크기 + * + * @param {Array} options.margin The size of accessible space outside the coordinate area. If an element is dragged outside the coordinate area and then dropped, the coordinates of the element are returned back into the coordinate area. The size of margins that can be exceeded − 좌표 영역을 넘어 이동할 수 있는 바깥 영역의 크기. 사용자가 좌표를 바깥 영역까지 끌었다가 놓으면 좌표가 좌표 영역 안으로 들어온다. + * @param {Boolean} [options.margin.0=0] The size of top margin 위쪽 바깥 영역의 크기 + * @param {Boolean} [options.margin.1=0] The size of right margin 오른쪽 바깥 영역의 크기 + * @param {Boolean} [options.margin.2=0] The size of bottom margin 아래쪽 바깥 영역의 크기 + * @param {Boolean} [options.margin.3=0] The size of left margin 왼쪽 바깥 영역의 크기 + * @param {Array} options.circular Indicates whether a circular element is available. If it is set to "true" and an element is dragged outside the coordinate area, the element will appear on the other side.순환 여부. 'true'로 설정한 방향의 좌표 영역 밖으로 엘리먼트가 이동하면 반대 방향에서 엘리먼트가 나타난다 + * @param {Boolean} [options.circular.0=false] Indicates whether to circulate to top 위로 순환 여부 + * @param {Boolean} [options.circular.1=false] Indicates whether to circulate to right 오른쪽으로 순환 여부 + * @param {Boolean} [options.circular.2=false] Indicates whether to circulate to bottom 아래로 순환 여부 + * @param {Boolean} [options.circular.3=false] Indicates whether to circulate to left 왼쪽으로 순환 여부 + * + * @param {Function} [options.easing=easing.easeOutCubic] The easing function to apply to an animation 애니메이션에 적용할 easing 함수 + * @param {Number} [options.maximumDuration=Infinity] Maximum duration of the animation 가속도에 의해 애니메이션이 동작할 때의 최대 좌표 이동 시간 + * @param {Number} [options.deceleration=0.0006] Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time. 사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다 + * @see HammerJS {@link http://hammerjs.github.io} + * @see • Hammer.JS applies specific CSS properties by default when creating an instance (See {@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}). The eg.MovableCoord module removes all default CSS properties provided by Hammer.JS Hammer.JS는 인스턴스를 생성할 때 기본으로 특정 CSS 속성을 적용한다(참고: @link{http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}). 특정한 상황에서는 Hammer.JS의 속성 때문에 사용성에 문제가 있을 수 있다. eg.MovableCoord 모듈은 Hammer.JS의 기본 CSS 속성을 모두 제거했다 + * + * @codepen {"id":"jPPqeR", "ko":"MovableCoord Cube 예제", "en":"MovableCoord Cube example", "collectionId":"AKpkGW", "height": 403} + * + * @see Easing Functions Cheat Sheet {@link http://easings.net/} + * @see If you want to try a different easing function, use the jQuery easing plugin ({@link http://gsgd.co.uk/sandbox/jquery/easing}) or the jQuery UI easing library ({@link https://jqueryui.com/easing}) 다른 easing 함수를 사용하려면 jQuery easing 플러그인({@link http://gsgd.co.uk/sandbox/jquery/easing})이나, jQuery UI easing 라이브러리({@lin https://jqueryui.com/easing})를 사용한다 + * + * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + */ + var MC = ns.MovableCoord = ns.Class.extend(ns.Component, { + construct: function(options) { + $.extend(this.options = { + min: [0, 0], + max: [100, 100], + bounce: [10, 10, 10, 10], + margin: [0,0,0,0], + circular: [false, false, false, false], + easing: $.easing.easeOutCubic, + maximumDuration: Infinity, + deceleration: 0.0006 + }, options); + this._reviseOptions(); + this._status = { + grabOutside: false, // check whether user's action started on outside + curHammer: null, // current hammer instance + moveDistance: null, // a position of the first user's action + animationParam: null, // animation information + prevented: false // check whether the animation event was prevented + }; + this._hammers = {}; + this._pos = this.options.min.concat(); + this._subOptions = {}; + this._raf = null; + this._animationEnd = $.proxy(this._animationEnd, this); // for caching + this._restore = $.proxy(this._restore, this); // for caching + this._panmove = $.proxy(this._panmove, this); // for caching + this._panend = $.proxy(this._panend, this); // for caching + }, + /** + * Registers an element to use the eg.MovableCoord module. + * @ko eg.MovableCoord 모듈을 사용할 엘리먼트를 등록한다 + * @method eg.MovableCoord#bind + * @param {HTMLElement|String|jQuery} element Element to use the eg.MovableCoord module− eg.MovableCoord 모듈을 사용할 엘리먼트 + * @param {Object} options The option object of the bind() method bind() 메서드의 옵션 객체 + * @param {Number} [options.direction=eg.MovableCoord.DIRECTION_ALL] Coordinate direction that a user can move
- eg.MovableCoord.DIRECTION_ALL: All directions available.
- eg.MovableCoord.DIRECTION_HORIZONTAL: Horizontal direction only.
- eg.MovableCoord.DIRECTION_VERTICAL: Vertical direction only사용자의 동작으로 움직일 수 있는 좌표의 방향.
- eg.MovableCoord.DIRECTION_ALL: 모든 방향으로 움직일 수 있다.
- eg.MovableCoord.DIRECTION_HORIZONTAL: 가로 방향으로만 움직일 수 있다.
- eg.MovableCoord.DIRECTION_VERTICAL: 세로 방향으로만 움직일 수 있다.
+ * @param {Array} options.scale Coordinate scale that a user can move사용자의 동작으로 이동하는 좌표의 배율 + * @param {Number} [options.scale.0=1] X-axis scale x축 배율 + * @param {Number} [options.scale.1=1] Y-axis scale y축 배율 + * @param {Number} [options.thresholdAngle=45] The threshold value that determines whether user action is horizontal or vertical (0~90) 사용자의 동작이 가로 방향인지 세로 방향인지 판단하는 기준 각도(0~90) + * @param {Number} [options.interruptable=true] Indicates whether an animation is interruptible.
- true: It can be paused or stopped by user action or the API.
- false: It cannot be paused or stopped by user action or the API while it is running.진행 중인 애니메이션 중지 가능 여부.
- true: 사용자의 동작이나 API로 애니메이션을 중지할 수 있다.
- false: 애니메이션이 진행 중일 때는 사용자의 동작이나 API가 적용되지 않는다
+ * @param {Array} [options.inputType] Types of input devices. (default: ["touch", "mouse"])
- touch: Touch screen
- mouse: Mouse 입력 장치 종류.(기본값: ["touch", "mouse"])
- touch: 터치 입력 장치
- mouse: 마우스
+ * + * @return {eg.MovableCoord} An instance of a module itself 모듈 자신의 인스턴스 + */ + bind: function(el, options) { + var $el = $(el); + var keyValue = $el.data(MC._KEY); + var subOptions = { + direction: MC.DIRECTION_ALL, + scale: [ 1, 1 ], + thresholdAngle: 45, + interruptable: true, + inputType: [ "touch", "mouse" ] + }; + + $.extend(subOptions, options); + + var inputClass = this._convertInputType(subOptions.inputType); + if (!inputClass) { + return this; + } + + if (keyValue) { + this._hammers[keyValue].inst.destroy(); + } else { + keyValue = Math.round(Math.random() * new Date().getTime()); + } + this._hammers[keyValue] = { + inst: this._createHammer( + $el.get(0), + subOptions, + inputClass + ), + options: subOptions + }; + $el.data(MC._KEY, keyValue); + return this; + }, + + _createHammer: function(el, subOptions, inputClass) { + try { + // create Hammer + var hammer = new HM.Manager(el, { + recognizers: [ + [ + HM.Pan, { + direction: subOptions.direction, + threshold: 0 + } + ] + ], + + // css properties were removed due to usablility issue + // http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html + cssProps: { + userSelect: "none", + touchSelect: "none", + touchCallout: "none", + userDrag: "none" + }, + inputClass: inputClass + }); + + return this._attachHammerEvents(hammer, subOptions); + } catch (e) {} + }, + + _attachHammerEvents: function(hammer, options) { + return hammer.on("hammer.input", $.proxy(function(e) { + if (e.isFirst) { + // apply options each + this._subOptions = options; + this._status.curHammer = hammer; + this._panstart(e); + } else if (e.isFinal) { + // substitute .on("panend tap", this._panend); Because it(tap, panend) cannot catch vertical(horizontal) movement on HORIZONTAL(VERTICAL) mode. + this._panend(e); + } + }, this)) + .on("panstart panmove", this._panmove); + }, + + _detachHammerEvents: function(hammer) { + hammer.off("hammer.input panstart panmove panend"); + }, + + _convertInputType: function(inputType) { + var hasTouch = false; + var hasMouse = false; + inputType = inputType || []; + $.each(inputType, function(i, v) { + switch (v) { + case "mouse" : hasMouse = true; break; + case "touch" : hasTouch = SUPPORT_TOUCH; + } + }); + + return hasTouch && HM.TouchInput || hasMouse && HM.MouseInput || null; + }, + + /** + * Detaches elements using the eg.MovableCoord module. + * @ko eg.MovableCoord 모듈을 사용하는 엘리먼트를 해제한다 + * @method eg.MovableCoord#unbind + * @param {HTMLElement|String|jQuery} element Elements from which the eg.MovableCoord module is detachedeg.MovableCoord 모듈을 해제할 엘리먼트 + * @return {eg.MovableCoord} An instance of a module itself모듈 자신의 인스턴스 + */ + unbind: function(el) { + var $el = $(el); + var key = $el.data(MC._KEY); + if (key) { + this._hammers[key].inst.destroy(); + delete this._hammers[key]; + $el.data(MC._KEY, null); + } + return this; + }, + + _grab: function() { + if (this._status.animationParam) { + this.trigger("animationEnd"); + var pos = this._getCircularPos(this._pos); + if (pos[0] !== this._pos[0] || pos[1] !== this._pos[1]) { + this._pos = pos; + this._triggerChange(this._pos, true); + } + this._status.animationParam = null; + this._raf && ns.cancelAnimationFrame(this._raf); + this._raf = null; + } + }, + + _getCircularPos: function(pos, min, max, circular) { + min = min || this.options.min; + max = max || this.options.max; + circular = circular || this.options.circular; + + if (circular[0] && pos[1] < min[1]) { // up + pos[1] = (pos[1] - min[1]) % (max[1] - min[1] + 1) + max[1]; + } + if (circular[1] && pos[0] > max[0]) { // right + pos[0] = (pos[0] - min[0]) % (max[0] - min[0] + 1) + min[0]; + } + if (circular[2] && pos[1] > max[1]) { // down + pos[1] = (pos[1] - min[1]) % (max[1] - min[1] + 1) + min[1]; + } + if (circular[3] && pos[0] < min[0]) { // left + pos[0] = (pos[0] - min[0]) % (max[0] - min[0] + 1) + max[0]; + } + pos[0] = +pos[0].toFixed(5), pos[1] = +pos[1].toFixed(5); + + return pos; + }, + + // determine outside + _isOutside: function(pos, min, max) { + return pos[0] < min[0] || pos[1] < min[1] || + pos[0] > max[0] || pos[1] > max[1]; + }, + + // from outside to outside + _isOutToOut: function(pos, destPos) { + var min = this.options.min; + var max = this.options.max; + return (pos[0] < min[0] || pos[0] > max[0] || + pos[1] < min[1] || pos[1] > max[1]) && + (destPos[0] < min[0] || destPos[0] > max[0] || + destPos[1] < min[1] || destPos[1] > max[1]); + }, + + // panstart event handler + _panstart: function(e) { + if (!this._subOptions.interruptable && this._status.prevented) { + return; + } + this._setInterrupt(true); + var pos = this._pos; + this._grab(); + /** + * This event is fired when a user holds an element on the screen of the device. + * @ko 사용자가 기기의 화면에 손을 대고 있을 때 발생하는 이벤트 + * @name eg.MovableCoord#hold + * @event + * @param {Object} param The object of data to be sent when the event is fired이벤트가 발생할 때 전달되는 데이터 객체 + * @param {Array} param.pos coordinate 좌표 정보 + * @param {Number} param.pos.0 The X coordinatex 좌표 + * @param {Number} param.pos.1 The Y coordinatey 좌표 + * @param {Object} param.hammerEvent The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다. + * + */ + this.trigger("hold", { + pos: pos.concat(), + hammerEvent: e + }); + this._status.moveDistance = pos.concat(); + this._status.grabOutside = this._isOutside( + pos, + this.options.min, + this.options.max + ); + }, + + // panmove event handler + _panmove: function(e) { + if (!this._isInterrupting() || !this._status.moveDistance) { + return; + } + var tv; + var tn; + var tx; + var pos = this._pos; + var min = this.options.min; + var max = this.options.max; + var bounce = this.options.bounce; + var margin = this.options.margin; + var direction = this._subOptions.direction; + var scale = this._subOptions.scale; + var userDirection = this._getDirection(e.angle); + var out = [ + margin[0] + bounce[0], + margin[1] + bounce[1], + margin[2] + bounce[2], + margin[3] + bounce[3] + ]; + var prevent = false; + + // not support offset properties in Hammerjs - start + var prevInput = this._status.curHammer.session.prevInput; + if (prevInput) { + e.offsetX = e.deltaX - prevInput.deltaX; + e.offsetY = e.deltaY - prevInput.deltaY; + } else { + e.offsetX = e.offsetY = 0; + } + + // not support offset properties in Hammerjs - end + if (direction === MC.DIRECTION_ALL || + (direction & MC.DIRECTION_HORIZONTAL && + userDirection & MC.DIRECTION_HORIZONTAL) + ) { + this._status.moveDistance[0] += (e.offsetX * scale[0]); + prevent = true; + } + if (direction === MC.DIRECTION_ALL || + (direction & MC.DIRECTION_VERTICAL && + userDirection & MC.DIRECTION_VERTICAL) + ) { + this._status.moveDistance[1] += (e.offsetY * scale[1]); + prevent = true; + } + if (prevent) { + e.srcEvent.preventDefault(); + e.srcEvent.stopPropagation(); + } + + e.preventSystemEvent = prevent; + pos[0] = this._status.moveDistance[0]; + pos[1] = this._status.moveDistance[1]; + pos = this._getCircularPos(pos, min, max); + + // from outside to inside + if (this._status.grabOutside && !this._isOutside(pos, min, max)) { + this._status.grabOutside = false; + } + + // when move pointer is held in outside + if (this._status.grabOutside) { + tn = min[0] - out[3], tx = max[0] + out[1], tv = pos[0]; + pos[0] = tv > tx ? tx : (tv < tn ? tn : tv); + tn = min[1] - out[0], tx = max[1] + out[2], tv = pos[1]; + pos[1] = tv > tx ? tx : (tv < tn ? tn : tv); + } else { + + // when start pointer is held in inside + // get a initialization slope value to prevent smooth animation. + var initSlope = this._initSlope(); + if (pos[1] < min[1]) { // up + tv = (min[1] - pos[1]) / (out[0] * initSlope); + pos[1] = min[1] - this._easing(tv) * out[0]; + } else if (pos[1] > max[1]) { // down + tv = (pos[1] - max[1]) / (out[2] * initSlope); + pos[1] = max[1] + this._easing(tv) * out[2]; + } + if (pos[0] < min[0]) { // left + tv = (min[0] - pos[0]) / (out[3] * initSlope); + pos[0] = min[0] - this._easing(tv) * out[3]; + } else if (pos[0] > max[0]) { // right + tv = (pos[0] - max[0]) / (out[1] * initSlope); + pos[0] = max[0] + this._easing(tv) * out[1]; + } + + } + this._triggerChange(pos, true, e); + }, + + // panend event handler + _panend: function(e) { + var pos = this._pos; + + if (!this._isInterrupting() || !this._status.moveDistance) { + return; + } + + // Abort the animating post process when "tap" occurs + if (e.distance === 0 /*e.type === "tap"*/) { + this._setInterrupt(false); + this.trigger("release", { + depaPos: pos.concat(), + destPos: pos.concat(), + hammerEvent: e || null + }); + } else { + var direction = this._subOptions.direction; + var scale = this._subOptions.scale; + var vX = Math.abs(e.velocityX); + var vY = Math.abs(e.velocityY); + + !(direction & MC.DIRECTION_HORIZONTAL) && (vX = 0); + !(direction & MC.DIRECTION_VERTICAL) && (vY = 0); + + var offset = this._getNextOffsetPos([ + vX * (e.deltaX < 0 ? -1 : 1) * scale[0], + vY * (e.deltaY < 0 ? -1 : 1) * scale[1] + ]); + var destPos = [ pos[0] + offset[0], pos[1] + offset[1] ]; + destPos = this._getPointOfIntersection(pos, destPos); + /** + * This event is fired when a user release an element on the screen of the device. + * @ko 사용자가 기기의 화면에서 손을 뗐을 때 발생하는 이벤트 + * @name eg.MovableCoord#release + * @event + * + * @param {Object} param The object of data to be sent when the event is fired이벤트가 발생할 때 전달되는 데이터 객체 + * @param {Array} param.depaPos The coordinates when releasing an element손을 뗐을 때의 좌표현재 + * @param {Number} param.depaPos.0 The X coordinate x 좌표 + * @param {Number} param.depaPos.1 The Y coordinate y 좌표 + * @param {Array} param.destPos The coordinates to move to after releasing an element손을 뗀 뒤에 이동할 좌표 + * @param {Number} param.destPos.0 The X coordinate x 좌표 + * @param {Number} param.destPos.1 The Y coordinate y 좌표 + * @param {Object} param.hammerEvent The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다 + * + */ + this.trigger("release", { + depaPos: pos.concat(), + destPos: destPos, + hammerEvent: e || null + }); + + if (pos[0] !== destPos[0] || pos[1] !== destPos[1]) { + this._animateTo(destPos, null, e || null); + } else { + this._setInterrupt(false); + } + } + this._status.moveDistance = null; + }, + + _isInterrupting: function() { + // when interruptable is 'true', return value is always 'true'. + return this._subOptions.interruptable || this._status.prevented; + }, + + // get user's direction + _getDirection: function(angle) { + var thresholdAngle = this._subOptions.thresholdAngle; + if (thresholdAngle < 0 || thresholdAngle > 90) { + return MC.DIRECTION_NONE; + } + angle = Math.abs(angle); + return angle > thresholdAngle && angle < 180 - thresholdAngle ? + MC.DIRECTION_VERTICAL : MC.DIRECTION_HORIZONTAL; + }, + + _getNextOffsetPos: function(speeds) { + var normalSpeed = Math.sqrt( + speeds[0] * speeds[0] + speeds[1] * speeds[1] + ); + var duration = Math.abs(normalSpeed / -this.options.deceleration); + return [ + speeds[0] / 2 * duration, + speeds[1] / 2 * duration + ]; + }, + + _getDurationFromPos: function(pos) { + var normalPos = Math.sqrt(pos[0] * pos[0] + pos[1] * pos[1]); + var duration = Math.sqrt( + normalPos / this.options.deceleration * 2 + ); + + // when duration is under 100, then value is zero + return duration < 100 ? 0 : duration; + }, + + _getPointOfIntersection: function(depaPos, destPos) { + var circular = this.options.circular; + var bounce = this.options.bounce; + var min = this.options.min; + var max = this.options.max; + var boxLT = [ min[0] - bounce[3], min[1] - bounce[0] ]; + var boxRB = [ max[0] + bounce[1], max[1] + bounce[2] ]; + var xd; + var yd; + destPos = [destPos[0], destPos[1]]; + xd = destPos[0] - depaPos[0], yd = destPos[1] - depaPos[1]; + if (!circular[3]) { + destPos[0] = Math.max(boxLT[0], destPos[0]); + } // left + if (!circular[1]) { + destPos[0] = Math.min(boxRB[0], destPos[0]); + } // right + destPos[1] = xd ? + depaPos[1] + yd / xd * (destPos[0] - depaPos[0]) : + destPos[1]; + + if (!circular[0]) { + destPos[1] = Math.max(boxLT[1], destPos[1]); + } // up + if (!circular[2]) { + destPos[1] = Math.min(boxRB[1], destPos[1]); + } // down + destPos[0] = yd ? + depaPos[0] + xd / yd * (destPos[1] - depaPos[1]) : + destPos[0]; + return [ + Math.min(max[0], Math.max(min[0], destPos[0])), + Math.min(max[1], Math.max(min[1], destPos[1])) + ]; + }, + + _isCircular: function(destPos) { + var circular = this.options.circular; + var min = this.options.min; + var max = this.options.max; + return (circular[0] && destPos[1] < min[1]) || + (circular[1] && destPos[0] > max[0]) || + (circular[2] && destPos[1] > max[1]) || + (circular[3] && destPos[0] < min[0]); + }, + + _prepareParam: function(absPos, duration, hammerEvent) { + var pos = this._pos; + var destPos = this._getPointOfIntersection(pos, absPos); + destPos = this._isOutToOut(pos, destPos) ? pos : destPos; + var distance = [ + Math.abs(destPos[0] - pos[0]), + Math.abs(destPos[1] - pos[1]) + ]; + duration = duration == null ? this._getDurationFromPos(distance) : duration; + duration = this.options.maximumDuration > duration ? + duration : this.options.maximumDuration; + return { + depaPos: pos.concat(), + destPos: destPos.concat(), + isBounce: this._isOutside(destPos, this.options.min, this.options.max), + isCircular: this._isCircular(absPos), + duration: duration, + distance: distance, + hammerEvent: hammerEvent || null, + done: this._animationEnd + }; + }, + + _restore: function(complete, hammerEvent) { + var pos = this._pos; + var min = this.options.min; + var max = this.options.max; + this._animate(this._prepareParam([ + Math.min(max[0], Math.max(min[0], pos[0])), + Math.min(max[1], Math.max(min[1], pos[1])) + ], null, hammerEvent), complete); + }, + + _animationEnd: function() { + this._status.animationParam = null; + this._pos = this._getCircularPos([ + Math.round(this._pos[0]), + Math.round(this._pos[1]) + ]); + this._setInterrupt(false); + /** + * This event is fired when animation ends. + * @ko 에니메이션이 끝났을 때 발생한다. + * @name eg.MovableCoord#animationEnd + * @event + */ + this.trigger("animationEnd"); + }, + + _animate: function(param, complete) { + param.startTime = new Date().getTime(); + this._status.animationParam = param; + if (param.duration) { + var info = this._status.animationParam; + var self = this; + (function loop() { + self._raf = null; + if (self._frame(info) >= 1) { + // deferred.resolve(); + complete(); + return; + } // animationEnd + self._raf = ns.requestAnimationFrame(loop); + })(); + } else { + this._triggerChange(param.destPos, false); + complete(); + } + }, + + _animateTo: function(absPos, duration, hammerEvent) { + var param = this._prepareParam(absPos, duration, hammerEvent); + var retTrigger = this.trigger("animationStart", param); + + // You can't stop the 'animationStart' event when 'circular' is true. + if (param.isCircular && !retTrigger) { + throw new Error( + "You can't stop the 'animation' event when 'circular' is true." + ); + } + + if (retTrigger) { + var self = this; + var queue = []; + var dequeue = function() { + var task = queue.shift(); + task && task.call(this); + }; + if (param.depaPos[0] !== param.destPos[0] || + param.depaPos[1] !== param.destPos[1]) { + queue.push(function() { + self._animate(param, dequeue); + }); + } + if (this._isOutside(param.destPos, this.options.min, this.options.max)) { + queue.push(function() { + self._restore(dequeue, hammerEvent); + }); + } + queue.push(function() { + self._animationEnd(); + }); + dequeue(); + } + }, + + // animation frame (0~1) + _frame: function(param) { + var curTime = new Date() - param.startTime; + var easingPer = this._easing(curTime / param.duration); + var pos = [ param.depaPos[0], param.depaPos[1] ]; + + for (var i = 0; i < 2 ; i++) { + (pos[i] !== param.destPos[i]) && + (pos[i] += (param.destPos[i] - pos[i]) * easingPer); + } + pos = this._getCircularPos(pos); + this._triggerChange(pos, false); + return easingPer; + }, + + // set up 'css' expression + _reviseOptions: function() { + var key; + var self = this; + $.each(["bounce", "margin", "circular"], function(i, v) { + key = self.options[v]; + if (key != null) { + if ($.isArray(key)) { + self.options[v] = key.length === 2 ? + key.concat(key) : key.concat(); + } else if (/string|number|boolean/.test(typeof key)) { + self.options[v] = [ key, key, key, key ]; + } else { + self.options[v] = null; + } + } + }); + }, + + // trigger 'change' event + _triggerChange: function(pos, holding, e) { + /** + * This event is fired when coordinate changes. + * @ko 좌표가 변경됐을 때 발생하는 이벤트 + * @name eg.MovableCoord#change + * @event + * + * @param {Object} param The object of data to be sent when the event is fired 이벤트가 발생할 때 전달되는 데이터 객체 + * @param {Array} param.pos departure coordinate 좌표 + * @param {Number} param.pos.0 The X coordinate x 좌표 + * @param {Number} param.pos.1 The Y coordinate y 좌표 + * @param {Boolean} param.holding Indicates whether a user holds an element on the screen of the device.사용자가 기기의 화면을 누르고 있는지 여부 + * @param {Object} param.hammerEvent The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다. + * + */ + this._pos = pos.concat(); + this.trigger("change", { + pos: pos.concat(), + holding: holding, + hammerEvent: e || null + }); + }, + + /** + * Returns the current position of the logical coordinates. + * @ko 논리적 좌표의 현재 위치를 반환한다 + * @method eg.MovableCoord#get + * @return {Array} pos 좌표 + * @return {Number} pos.0 The X coordinate x 좌표 + * @return {Number} pos.1 The Y coordinate y 좌표 + */ + get: function() { + return this._pos.concat(); + }, + + /** + * Moves an element to specific coordinates. + * @ko 좌표를 이동한다. + * @method eg.MovableCoord#setTo + * @param {Number} x The X coordinate to move to 이동할 x좌표 + * @param {Number} y The Y coordinate to move to 이동할 y좌표 + * @param {Number} [duration=0] Duration of the animation (unit: ms) 애니메이션 진행 시간(단위: ms) + * @return {eg.MovableCoord} An instance of a module itself 자신의 인스턴스 + */ + setTo: function(x, y, duration) { + this._grab(); + var pos = this._pos.concat(); + var circular = this.options.circular; + var min = this.options.min; + var max = this.options.max; + if (x === pos[0] && y === pos[1]) { + return this; + } + this._setInterrupt(true); + if (x !== pos[0]) { + if (!circular[3]) { + x = Math.max(min[0], x); + } + if (!circular[1]) { + x = Math.min(max[0], x); + } + } + if (y !== pos[1]) { + if (!circular[0]) { + y = Math.max(min[1], y); + } + if (!circular[2]) { + y = Math.min(max[1], y); + } + } + if (duration) { + this._animateTo([ x, y ], duration); + } else { + this._pos = this._getCircularPos([ x, y ]); + this._triggerChange(this._pos, false); + this._setInterrupt(false); + } + return this; + }, + /** + * Moves an element from the current coordinates to specific coordinates. The change event is fired when the method is executed. + * @ko 현재 좌표를 기준으로 좌표를 이동한다. 메서드가 실행되면 change 이벤트가 발생한다 + * @method eg.MovableCoord#setBy + * @param {Number} x The X coordinate to move to 이동할 x좌표 + * @param {Number} y The Y coordinate to move to 이동할 y좌표 + * @param {Number} [duration=0] Duration of the animation (unit: ms) 애니메이션 진행 시간(단위: ms) + * @return {eg.MovableCoord} An instance of a module itself 자신의 인스턴스 + */ + setBy: function(x, y, duration) { + return this.setTo( + x != null ? this._pos[0] + x : this._pos[0], + y != null ? this._pos[1] + y : this._pos[1], + duration + ); + }, + + _easing: function(p) { + return p > 1 ? 1 : this.options.easing(p, p, 0, 1, 1); + }, + + _initSlope: function() { + var easing = this.options.easing; + var isIn = false; + var p; + for (p in $.easing) { + if ($.easing[p] === easing) { + isIn = !~p.indexOf("Out"); + break; + } + } + return isIn ? + easing(0.9999, 0.9999, 0, 1, 1) / 0.9999 : + easing(0.00001, 0.00001, 0, 1, 1) / 0.00001; + }, + + _setInterrupt: function(prevented) { + !this._subOptions.interruptable && + (this._status.prevented = prevented); + }, + + /** + * Destroys elements, properties, and events used in a module. + * @ko 모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다. + * @method eg.MovableCoord#destroy + */ + destroy: function() { + this.off(); + for (var p in this._hammers) { + this._hammers[p].inst.destroy(); + this._hammers[p] = null; + } + } + }); + MC._KEY = "__MOVABLECOORD__"; + /** + * @name eg.MovableCoord.DIRECTION_NONE + * @constant + * @type {Number} + */ + MC.DIRECTION_NONE = 1; + /** + * @name eg.MovableCoord.DIRECTION_LEFT + * @constant + * @type {Number} + */ + MC.DIRECTION_LEFT = 2; + /** + * @name eg.MovableCoord.DIRECTION_RIGHT + * @constant + * @type {Number} + */ + MC.DIRECTION_RIGHT = 4; + /** + * @name eg.MovableCoord.DIRECTION_UP + * @constant + * @type {Number} + */ + MC.DIRECTION_UP = 8; + /** + * @name eg.MovableCoord.DIRECTION_DOWN + * @constant + * @type {Number} + */ + MC.DIRECTION_DOWN = 16; + /** + * @name eg.MovableCoord.DIRECTION_HORIZONTAL + * @constant + * @type {Number} + */ + MC.DIRECTION_HORIZONTAL = 2 | 4; + /** + * @name eg.MovableCoord.DIRECTION_VERTICAL + * @constant + * @type {Number} + */ + MC.DIRECTION_VERTICAL = 8 | 16; + + /** + * @name eg.MovableCoord.DIRECTION_ALL + * @constant + * @type {Number} + */ + MC.DIRECTION_ALL = MC.DIRECTION_HORIZONTAL | MC.DIRECTION_VERTICAL; + + return { + "MovableCoord": ns.MovableCoord + }; +}); +// jscs:disable validateLineBreaks, maximumLineLength +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ +eg.module("flicking", ["jQuery", eg, window, document, eg.MovableCoord], function ($, ns, global, doc, MC) { +// jscs:enable validateLineBreaks, maximumLineLength + /** + * A module used to implement flicking interactions. With this module, you can make flicking gestures, which are ways to navigate left and right to move between panels arranged side by side. + * @group egjs + * @ko 플리킹 UI를 구현하는 모듈. 나란히 배치한 패널을 쓸어 넘겨 다음 패널이나 이전 패널로 이동하는 플리킹 UI를 만들 수 있다. + * @class + * @name eg.Flicking + * @extends eg.Component + * + * @param {HTMLElement|String|jQuery} element A base element for the eg.Flicking module eg.Flicking 모듈을 사용할 기준 엘리먼트 + * @param {Object} options The option object of the eg.Flicking moduleeg.Flicking 모듈의 옵션 객체 + * @param {Boolean} [options.hwAccelerable=eg.isHWAccelerable()] Force hardware compositing 하드웨어 가속 사용 여부 + * @param {String} [options.prefix=eg-flick] A prefix for class names of the panel elements 패널 엘리먼트의 클래스 이름에 설정할 접두사 + * @param {Number} [options.deceleration=0.0006] Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time 사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다 + * @param {Boolean} [options.horizontal=true] Direction of the panel movement (true: horizontal, false: vertical) 패널 이동 방향 (true 가로방향, false 세로방향) + * @param {Boolean} [options.circular=false] Indicates whether a circular panel is available 패널 순환 여부 + * @param {Number|Array} [options.previewPadding=[0,0]] The preview size for the previous or next panel. If direction is set to "horizontal", the preview section will be displayed on the left and right of the panel. If direction is set to "vertical", it will be displayed on the top and bottom of the panel 이전 패널과 다음 패널을 미리 보는 영역의 크기. 패널 이동 방향이 가로 방향이면 패널 왼쪽과 오른쪽에 미리 보는 영역이 나타난다. 패널 이동 방향이 세로 방향이면 패널 위쪽과 아래쪽에 미리 보는 영역이 나타난다 + * @param {Number|Array} [options.bounce=[10,10]] − The size of bouncing area. If a panel is set to "non-circulable", the start and end panels can exceed the base element area and move further as much as the bouncing area. If a panel is dragged to the bouncing area and then dropped, the panel where bouncing effects are applied is retuned back into the base element area. 바운스 영역의 크기. 패널이 순환하지 않도록 설정됐다면 시작 패널과 마지막 패널은 기준 엘리먼트 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 패널을 바운스 영역까지 끌었다가 놓으면, 바운스 효과가 적용된 패널이 다시 기준 엘리먼트 영역 안으로 들어온다 + * @param {Number} [options.threshold=40] Distance threshold. If the drag exceeds the threshold value, it will be changed to the next panel 다음 패널로 바뀌는 기준 이동 거리. 패널을 기준 이동 거리 이상 끌었다 놓으면 패널이 다음 패널로 바뀐다 + * @param {Number} [options.duration=100] Duration of the panel movement (unit: ms) 패널 이동 애니메이션 진행 시간(단위: ms) + * @param {Function} [options.panelEffect=easeOutCubic] The easing function to apply to a panel moving animation 패널 이동 애니메이션에 적용할 easing 함수 + * @param {Number} [options.defaultIndex=0] The index number of a panel to be selected upon module initialization 모듈이 초기화될 때 선택할 패널의 인덱스 번호 + * @param {Array} [options.inputType] Types of input devices.
- touch: A touch screen can be used to move a panel.
- mouse: A mouse can be used to move a panel. 입력 장치 종류.
- touch: 터치 입력 장치로 패널을 이동할 수 있다.
- mouse: 마우스로 패널을 이동할 수 있다.
+ * + * @codepen {"id":"rVOpPK", "ko":"플리킹 UI 기본 예제", "en":"Flicking UI default example", "collectionId":"ArxyLK", "height" : 403} + * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest" , "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + * + * @see Easing Functions Cheat Sheet {@link http://easings.net/} + * @see If you want to try a different easing function, use the jQuery easing plugin ({@link http://gsgd.co.uk/sandbox/jquery/easing}) or the jQuery UI easing library ({@link https://jqueryui.com/easing}). 다른 easing 함수를 사용하려면 jQuery easing 플러그인({@link http://gsgd.co.uk/sandbox/jquery/easing})이나, jQuery UI easing 라이브러리({@link https://jqueryui.com/easing})를 사용한다 + * @example + +
+
+

Layer 0

+
+
+

Layer 1

+
+
+

Layer 2

+
+
+ + */ + + // define custom events name + var EVENTS = { + "beforeFlickStart": "beforeFlickStart", + "beforeRestore": "beforeRestore", + "flick": "flick", + "flickEnd": "flickEnd", + "restore": "restore" + }; + + // check for css transform support + var SUPPORT_TRANSFORM = doc.documentElement.style; + SUPPORT_TRANSFORM = "transform" in SUPPORT_TRANSFORM || + "webkitTransform" in SUPPORT_TRANSFORM; + + // check for will-change support + var SUPPORT_WILLCHANGE = global.CSS && global.CSS.supports && + global.CSS.supports("will-change", "transform"); + + // check for Android 2.x + var IS_ANDROID2 = ns.agent().os; + IS_ANDROID2 = IS_ANDROID2.name === "android" && /^2\./.test(IS_ANDROID2.version); + + ns.Flicking = ns.Class.extend(ns.Component, { + _events: function() { + return EVENTS; + }, + /** + * Constructor + * @param {HTMLElement|String|jQuery} element - base element + * @param {Object} options + */ + construct: function (element, options, _prefix) { + this.$wrapper = $(element); + + var $children = this.$wrapper.children(); + if (!$children.length) { + // jscs:disable validateLineBreaks, maximumLineLength + throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized."); + + // jscs:enable validateLineBreaks, maximumLineLength + } + + this._setOptions(options); + this._setConfig($children, _prefix); + + !ns._hasClickBug() && (this._setPointerEvents = $.noop); + + this._build(); + this._bindEvents(true); + + this._applyPanelsCss(); + this._arrangePanels(); + + this.options.hwAccelerable && SUPPORT_WILLCHANGE && this._setHint(); + this._adjustContainerCss("end"); + }, + + /** + * Set options values + * @param {Object} options + */ + _setOptions: function(options) { + var arrVal = { + previewPadding: [ 0, 0 ], + bounce: [ 10, 10 ] + }; + + $.extend(this.options = { + hwAccelerable: ns.isHWAccelerable(), // check weather hw acceleration is available + prefix: "eg-flick", // prefix value of class name + deceleration: 0.0006, // deceleration value + horizontal: true, // move direction (true == horizontal, false == vertical) + circular: false, // circular mode. In this mode at least 3 panels are required. + previewPadding: arrVal.previewPadding, // preview padding value in left(up) to right(down) order. In this mode at least 5 panels are required. + bounce: arrVal.bounce, // bounce value in left(up) to right(down) order. Works only in non-circular mode. + threshold: 40, // the distance pixel threshold value for change panel + duration: 100, // duration ms for animation + panelEffect: $.easing.easeOutCubic, // $.easing function for panel change animation + defaultIndex: 0, // initial panel index to be shown + inputType: ["touch", "mouse"] // input type + }, options); + + var self = this; + $.each(arrVal, function(i, v) { + var val = self.options[i]; + + if ($.isNumeric(val)) { + val = [ val, val ]; + } else if (!$.isArray(val)) { + val = v; + } + + self.options[i] = val; + }); + }, + + /** + * Set config values + * @param {jQuery} $children wrappers' children elements + * @param {String} _prefix event prefix + */ + _setConfig: function($children, _prefix) { + var options = this.options; + var padding = options.previewPadding; + + if ($children.eq(0).hasClass(options.prefix + "-container")) { + this.$container = $children; + $children = $children.children(); + } + + // config value + this._conf = { + panel: { + $list: $children, // panel list + index: 0, // dom index used among process + no: 0, // panel no used among process + currIndex: 0, // current physical dom index + currNo: 0, // current logical panel number + size: 0, // panel size + count: 0, // total physical panel count + origCount: 0, // total count of given original panels + changed: false, // if panel changed + animating: false, // current animating status boolean + minCount: padding[0] + padding[1] > 0 ? 5 : 3 // minimum panel count + }, + touch: { + holdPos: [0, 0], // hold x,y coordinate + destPos: [0, 0], // destination x,y coordinate + distance: 0, // touch distance pixel of start to end touch + direction: null, // touch direction + lastPos: 0, // to determine move on holding + holding: false + }, + customEvent: { // for custom events value + flick: true, + restore: false, + restoreCall: false + }, + origPanelStyle: { // remember original class and inline style in case of restoration on destroy() + wrapper: { + className: this.$wrapper.attr("class") || null, + style: this.$wrapper.attr("style") || null + }, + list: $children.map(function(i, v) { + return { + className: $(v).attr("class") || null, + style: $(v).attr("style") || null + }; + }) + }, + inputEvent: false, // input event biding status + useLayerHack: options.hwAccelerable && !SUPPORT_WILLCHANGE, + dirData: [], // direction constant value according horizontal or vertical + indexToMove: 0, + eventPrefix: _prefix || "", + + // For buggy link highlighting on Android 2.x + $dummyAnchor: null + }; + + $([["LEFT", "RIGHT"], ["UP", "DOWN"]][+!options.horizontal]).each( + $.proxy(function (i, v) { + this._conf.dirData.push(MC["DIRECTION_" + v]); + }, this)); + }, + + /** + * Build and set panel nodes to make flicking structure + */ + _build: function () { + var panel = this._conf.panel; + var options = this.options; + var $children = panel.$list; + var padding = options.previewPadding.concat(); + var prefix = options.prefix; + var horizontal = options.horizontal; + var panelCount = panel.count = panel.origCount = $children.length; + var cssValue; + var bounce = options.bounce; + + this._setPadding(padding, true); + var sizeValue = this._getDataByDirection([ panel.size, "100%" ]); + + // create container element + cssValue = "position:relative;z-index:2000;width:100%;height:100%;" + + (horizontal ? "" : "top:0;"); + + if (this.$container) { + this.$container.attr("style", cssValue); + } else { + this.$container = $children.wrapAll( + "
" + ).parent(); + } + + // panels' css values + $children.addClass(prefix + "-panel").css({ + position: "absolute", + width: sizeValue[0], + height: sizeValue[1], + boxSizing: "border-box", + top: 0, + left: 0 + }); + + if (this._addClonePanels()) { + panelCount = panel.count = ( + panel.$list = this.$container.children() + ).length; + } + + // create MovableCoord instance + this._mcInst = new MC({ + min: [0, 0], + max: this._getDataByDirection([panel.size * (panelCount - 1), 0]), + margin: 0, + circular: false, + easing: options.panelEffect, + deceleration: options.deceleration, + bounce: this._getDataByDirection([ 0, bounce[1], 0, bounce[0] ]) + }); + + this._setDefaultPanel(options.defaultIndex); + }, + + /** + * Set preview padding value + * @param {Array} padding + * @param {Boolean} build + */ + _setPadding: function(padding, build) { + var horizontal = this.options.horizontal; + var panel = this._conf.panel; + var paddingSum = padding[0] + padding[1]; + var cssValue = {}; + + if (paddingSum || !build) { + cssValue.padding = (horizontal ? + "0 " + padding.reverse().join("px 0 ") : + padding.join("px 0 ")) + "px"; + } + + if (build) { + cssValue.overflow = "hidden"; + cssValue.boxSizing = "border-box"; + } + + !$.isEmptyObject(cssValue) && + this.$wrapper.css(cssValue); + + panel.size = this.$wrapper[ horizontal ? "width" : "height" ](); + }, + + /** + * To fulfill minimum panel count cloning original node when circular or previewPadding option are set + * @return {Boolean} true : added clone node, false : not added + */ + _addClonePanels: function () { + var panel = this._conf.panel; + var panelCount = panel.origCount; + var cloneCount = panel.minCount - panelCount; + var list = panel.$list; + var cloneNodes; + + // if panels are given less than required when circular option is set, then clone node to apply circular mode + if (this.options.circular && panelCount < panel.minCount) { + cloneNodes = list.clone(); + + while (cloneNodes.length < cloneCount) { + cloneNodes = cloneNodes.add(list.clone()); + } + + return this.$container.append(cloneNodes); + } + }, + + /** + * Move panel's position within array + * @param {Number} count element counts to move + * @param {Boolean} append where the list to be appended(moved) (true: to the end, false: to the beginning) + */ + _movePanelPosition: function (count, append) { + var panel = this._conf.panel; + var list = panel.$list.toArray(); + var listToMove; + + listToMove = list.splice(append ? 0 : panel.count - count, count); + panel.$list = $(append ? list.concat(listToMove) : listToMove.concat(list)); + }, + + /** + * Set default panel to show + * @param {Number} index + */ + _setDefaultPanel: function (index) { + var panel = this._conf.panel; + var lastIndex = panel.count - 1; + var coords; + var baseIndex; + + if (this.options.circular) { + // if default index is given, then move correspond panel to the first position + if (index > 0 && index <= lastIndex) { + this._movePanelPosition(index, true); + } + + // set first panel's position according physical node length + baseIndex = this._getBasePositionIndex(); + this._movePanelPosition(baseIndex, false); + + this._setPanelNo({ + no: index, + currNo: index + }); + } else { + // if defaultIndex option is given, then move to that index panel + if (index > 0 && index <= lastIndex) { + this._setPanelNo({ + index: index, + no: index, + currIndex: index, + currNo: index + }); + + coords = [ -(panel.size * index), 0]; + + this._setTranslate(coords); + this._setMovableCoord("setTo", [ + Math.abs(coords[0]), Math.abs(coords[1]) + ], true, 0); + } + } + }, + + /** + * Arrange panels' position + * @param {Boolean} sort Need to sort panel's position + * @param {Number} indexToMove Number to move from current position (negative: left, positive: right) + */ + _arrangePanels: function (sort, indexToMove) { + var conf = this._conf; + var panel = conf.panel; + var touch = conf.touch; + var dirData = conf.dirData; + var baseIndex; + + if (this.options.circular) { + // when arranging panels, set flag to not trigger flick custom event + conf.customEvent.flick = false; + + // move elements according direction + if (sort) { + indexToMove && (touch.direction = dirData[+!Boolean(indexToMove > 0)]); + this._arrangePanelPosition(touch.direction, indexToMove); + } + + // set index for base element's position + baseIndex = this._getBasePositionIndex(); + + this._setPanelNo({ + index: baseIndex, + currIndex: baseIndex + }); + + // arrange MovableCoord's coord position + conf.customEvent.flick = !!this._setMovableCoord("setTo", [ + panel.size * panel.index, 0 + ], true, 0); + } + + this._applyPanelsPos(); + }, + + /** + * Set each panel's position in DOM + */ + _applyPanelsPos: function() { + this._conf.panel.$list.each( + $.proxy(this._applyPanelsCss, this) + ); + }, + + /** + * Set CSS style values to move elements + * + * Initialize setting up checking if browser support transform css property. + * If browser doesn't support transform, then use left/top properties instead. + */ + _setMoveStyle: (function () { + return SUPPORT_TRANSFORM ? + function ($element, coords) { + $element.css("transform", + ns.translate(coords[0], coords[1], this._conf.useLayerHack) + ); + } : function ($element, coords) { + $element.css({ left: coords[0], top: coords[1] }); + }; + })(), + + /** + * Callback function for applying CSS values to each panels + * + * Need to be initialized before use, to set up for Android 2.x browsers or others. + */ + _applyPanelsCss: function () { + var conf = this._conf; + var dummyAnchorClassName = "__dummy_anchor"; + + if (IS_ANDROID2) { + conf.$dummyAnchor = $("." + dummyAnchorClassName); + + !conf.$dummyAnchor.length && this.$wrapper.append( + conf.$dummyAnchor = $("") + ); + + this._applyPanelsCss = function (i, v) { + var coords = this._getDataByDirection([ + (this._conf.panel.size * i) + "px", 0 + ]); + + $(v).css({ + left: coords[0], + top: coords[1] + }); + }; + } else { + this._applyPanelsCss = function (i, v) { + var coords = this._getDataByDirection([ + SUPPORT_TRANSFORM ? + (100 * i) + "%" : + (this._conf.panel.size * i) + "px", 0]); + + this._setMoveStyle($(v), coords); + }; + } + }, + + /** + * Adjust container's css value to handle Android 2.x link highlighting bug + * + * @param {String} phase + * start - set left/top value to 0 + * end - set translate value to 0 + * @param {Array} coords coordinate value + */ + _adjustContainerCss: function (phase, coords) { + var conf = this._conf; + var panel = conf.panel; + var options = this.options; + var horizontal = options.horizontal; + var paddingTop = options.previewPadding[0]; + var container = this.$container; + var value; + + if (IS_ANDROID2) { + if (!coords) { + coords = [-panel.size * panel.index, 0]; + } + + if (phase === "start") { + container = container[0].style; + value = parseInt(container[horizontal ? "left" : "top"], 10); + + if (horizontal) { + value && (container.left = 0); + } else { + value !== paddingTop && (container.top = paddingTop + "px"); + } + + this._setTranslate([-coords[+!options.horizontal], 0]); + + } else if (phase === "end") { + !horizontal && (coords[0] += paddingTop); + coords = this._getCoordsValue(coords); + + container.css({ + left: coords.x, + top: coords.y, + transform: ns.translate(0, 0, conf.useLayerHack) + }); + + conf.$dummyAnchor[0].focus(); + } + } + }, + + /** + * Set MovableCoord coord value + * @param {String} method + * @param {Array} coord + * @param {Boolean} isDirVal + * @param {Number} duration + * @return {eg.MovableCoord} MovableCoord instance + */ + _setMovableCoord: function (method, coord, isDirVal, duration) { + if (isDirVal) { + coord = this._getDataByDirection(coord); + } + + return this._mcInst[method](coord[0], coord[1], duration); + }, + + /** + * Set hint for browser to decide efficient way of doing transform changes(or animation) + * https://dev.opera.com/articles/css-will-change-property/ + */ + _setHint: function () { + var value = "transform"; + this.$container.css("willChange", value); + this._conf.panel.$list.css("willChange", value); + }, + + /** + * Get data according options.horizontal value + * + * @param {Array} value primary data to handle + * @return {Array} + */ + _getDataByDirection: function (value) { + value = value.concat(); + !this.options.horizontal && value.reverse(); + return value; + }, + + /** + * Move nodes + * @param {Boolean} direction + * @param {Number} indexToMove + */ + _arrangePanelPosition: function (direction, indexToMove) { + var next = direction === this._conf.dirData[0]; + this._movePanelPosition(Math.abs(indexToMove || 1), next); + }, + + /** + * Get the base position index of the panel + */ + _getBasePositionIndex: function () { + return Math.floor(this._conf.panel.count / 2 - 0.1); + }, + + /** + * Bind events + * @param {Boolean} bind + */ + _bindEvents: function (bind) { + var options = this.options; + var $wrapper = this.$wrapper; + var mcInst = this._mcInst; + + if (bind) { + mcInst.bind($wrapper, { + scale: this._getDataByDirection([-1, 0]), + direction: MC["DIRECTION_" + + (options.horizontal ? "HORIZONTAL" : "VERTICAL")], + interruptable: false, + inputType: options.inputType + }).on({ + hold: $.proxy(this._holdHandler, this), + change: $.proxy(this._changeHandler, this), + release: $.proxy(this._releaseHandler, this), + animationStart: $.proxy(this._animationStartHandler, this), + animationEnd: $.proxy(this._animationEndHandler, this) + }); + } else { + mcInst.unbind($wrapper).off(); + } + + this._conf.inputEvent = !!bind; + }, + + /** + * 'hold' event handler + */ + _holdHandler: function (e) { + var conf = this._conf; + + conf.touch.holdPos = e.pos; + conf.touch.holding = true; + conf.panel.changed = false; + + this._adjustContainerCss("start", e.pos); + }, + + /** + * 'change' event handler + */ + _changeHandler: function (e) { + var conf = this._conf; + var touch = conf.touch; + var posIndex = +!this.options.horizontal; + var pos = e.pos[posIndex]; + var holdPos = touch.holdPos[posIndex]; + var direction; + var eventRes = null; + var movedPx; + + this._setPointerEvents(e); // for "click" bug + + /** + * This event is fired when panel moves. + * @ko 패널이 이동할 때 발생하는 이벤트 + * @name eg.Flicking#flick + * @event + * @param {Object} param The object of data to be sent to an event 이벤트에 전달되는 데이터 객체 + * @param {String} param.eventType The name of the event이름명 + * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM (@deprecated since 1.3.0)현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0) + * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content 현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다 + * @param {Number} param.direction Direction of the movement (see eg.MovableCoord.DIRECTION_* constant) 이동 방향(eg.MovableCoord.DIRECTION_* constant 참고) + * @param {Array} param.pos Start coordinate 출발점 좌표 + * @param {Number} param.pos.0 x-coordinate x 좌표 + * @param {Number} param.pos.1 y-coordinate y 좌표 + * @param {Boolean} param.holding Indicates whether a user holds an element on the screen of the device. 사용자가 기기의 화면을 누르고 있는지 여부 + * @param {Number} param.distance Distance moved from then starting point. According the move direction, positive on eg.MovableCoord.DIRECTION_LEFT/UP and negative on eg.MovableCoord.DIRECTION_RIGHT/DOWN 시작점부터 이동된 거리의 값. 이동 방향에 따라 eg.MovableCoord.DIRECTION_LEFT/UP의 경우 양수를 eg.MovableCoord.DIRECTION_RIGHT/DOWN의 경우는 음수를 반환 + */ + if (e.hammerEvent) { + direction = e.hammerEvent.direction; + + // Adjust direction in case of diagonal touch move + movedPx = e.hammerEvent[ this.options.horizontal ? "deltaX" : "deltaY" ]; + + if (!~$.inArray(direction, conf.dirData)) { + direction = conf.dirData[ +(Math.abs(touch.lastPos) <= movedPx) ]; + } + + touch.lastPos = movedPx; + } else { + touch.lastPos = null; + } + + conf.customEvent.flick && (eventRes = this._triggerEvent(EVENTS.flick, { + pos: e.pos, + holding: e.holding, + direction: direction || touch.direction, + distance: pos - (holdPos || (touch.holdPos[posIndex] = pos)) + })); + + (eventRes || eventRes === null) && this._setTranslate([ -pos, 0 ]); + }, + + /** + * 'release' event handler + */ + _releaseHandler: function (e) { + var touch = this._conf.touch; + var pos = e.destPos; + var posIndex = +!this.options.horizontal; + var holdPos = touch.holdPos[posIndex]; + var panelSize = this._conf.panel.size; + + touch.distance = e.depaPos[posIndex] - touch.holdPos[posIndex]; + + touch.direction = this._conf.dirData[ + +!Boolean(touch.holdPos[posIndex] < e.depaPos[posIndex]) + ]; + + pos[posIndex] = Math.max( + holdPos - panelSize, Math.min(holdPos, pos[posIndex]) + ); + + touch.destPos[posIndex] = + pos[posIndex] = Math.round(pos[posIndex] / panelSize) * panelSize; + + touch.distance === 0 && this._adjustContainerCss("end"); + touch.holding = false; + + this._setPointerEvents(); // for "click" bug + }, + + /** + * 'animationStart' event handler + */ + _animationStartHandler: function (e) { + var conf = this._conf; + var panel = conf.panel; + var customEvent = conf.customEvent; + + panel.animating = true; + + if (!customEvent.restoreCall && e.hammerEvent && + this._setPhaseValue("start", { + depaPos: e.depaPos, + destPos: e.destPos + }) === false) { + e.stop(); + } + + if (e.hammerEvent) { + e.duration = this.options.duration; + + e.destPos[+!this.options.horizontal] = + panel.size * ( + panel.index + conf.indexToMove + ); + } + + if (this._isMovable()) { + !customEvent.restoreCall && (customEvent.restore = false); + } else { + this._triggerBeforeRestore(e); + } + }, + + /** + * 'animationEnd' event handler + */ + _animationEndHandler: function () { + this._setPhaseValue("end"); + + this._conf.panel.animating = false; + this._triggerRestore(); + }, + + /** + * Trigger beforeRestore event + * @param {Object} e event object + */ + _triggerBeforeRestore: function(e) { + var conf = this._conf; + var touch = conf.touch; + + // reverse direction value when restore + touch.direction = ~~conf.dirData.join("").replace(touch.direction, ""); + + /** + * This event is fired before an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached + * @ko 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원되기 전에 발생하는 이벤트 + * @name eg.Flicking#beforeRestore + * @event + * @param {Object} param The object of data to be sent to an event 이벤트에 전달되는 데이터 객체 + * @param {String} param.eventType The name of the event 이름명 + * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM. (@deprecated since 1.3.0)현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다. (@deprecated since 1.3.0) + * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content.현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다 + * @param {Number} param.direction Direction of the movement (see eg.MovableCoord.DIRECTION_* constant) 이동 방향(eg.MovableCoord.DIRECTION_* constant 참고) + * @param {Array} param.depaPos Start coordinate 출발점 좌표 + * @param {Number} param.depaPos.0 x-coordinate x 좌표 + * @param {Number} param.depaPos.1 y-coordinate y 좌표 + * @param {Array} param.destPos End coordinate 도착점 좌표 + * @param {Number} param.destPos.0 x-coordinate x 좌표 + * @param {Number} param.destPos.1 y-coordinate y 좌표 + */ + conf.customEvent.restore = this._triggerEvent(EVENTS.beforeRestore, { + depaPos: e.depaPos, + destPos: e.destPos + }); + + if (!conf.customEvent.restore) { + "stop" in e && e.stop(); + conf.panel.animating = false; + } + }, + + /** + * Trigger restore event + */ + _triggerRestore: function() { + var customEvent = this._conf.customEvent; + + /** + * This event is fired after an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached. + * @ko 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원된 다음 발생하는 이벤트 + * @name eg.Flicking#restore + * @event + * @param {Object} param The object of data to be sent to an event 이벤트에 전달되는 데이터 객체 + * @param {String} param.eventType The name of the event 이름명 + * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM(@deprecated since 1.3.0)현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0) + * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content. 현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다 + * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) 이동 방향(eg.MovableCoord.DIRECTION_* constant 참고) + */ + customEvent.restore && this._triggerEvent(EVENTS.restore); + customEvent.restoreCall = false; + }, + + /** + * Set value when panel changes + * @param {String} phase - [start|end] + * @param {Object} pos + */ + _setPhaseValue: function (phase, pos) { + var conf = this._conf; + var options = this.options; + var panel = conf.panel; + + if (phase === "start" && (panel.changed = this._isMovable())) { + /** + * This event is fired before flicking starts + * @ko 플리킹이 시작하기 전에 발생하는 이벤트 + * @name eg.Flicking#beforeFlickStart + * @event + * @param {Object} param The object of data to be sent to an event 이벤트에 전달되는 데이터 객체 + * @param {String} param.eventType The name of the event 이름명 + * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM. (@deprecated since 1.3.0)현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0) + * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content.현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다 + * @param {Number} param.direction Direction of the movement (see eg.MovableCoord.DIRECTION_* constant) − 이동 방향(eg.MovableCoord.DIRECTION_* constant 참고) + * @param {Array} param.depaPos Start coordinate 출발점 좌표 + * @param {Number} param.depaPos.0 x-coordinate x 좌표 + * @param {Number} param.depaPos.1 y-coordinate y 좌표 + * @param {Array} param.destPos End coordinate 도착점 좌표 + * @param {Number} param.destPos.0 x-coordinate x 좌표 + * @param {Number} param.destPos.1 y-coordinate y 좌표 + */ + if (!this._triggerEvent(EVENTS.beforeFlickStart, pos)) { + return panel.changed = panel.animating = false; + } + + conf.indexToMove === 0 && this._setPanelNo(); + } else if (phase === "end") { + if (options.circular && panel.changed) { + this._arrangePanels(true, conf.indexToMove); + } + + !IS_ANDROID2 && this._setTranslate([-panel.size * panel.index, 0]); + conf.touch.distance = conf.indexToMove = 0; + + /** + * This event is fired after panel moves. + * @ko 패널이 이동한 다음 발생하는 이벤트 + * @name eg.Flicking#flickEnd + * @event + * @param {Object} param The object of data to be sent to an event 이벤트에 전달되는 데이터 객체 + * @param {String} param.eventType The name of the event 이름명 + * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM (@deprecated since 1.3.0)현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0) + * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content. 현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다. + * @param {Number} param.direction Direction of the movemen (see eg.MovableCoord.DIRECTION_* constant) − 이동 방향(eg.MovableCoord.DIRECTION_* constant 참고 + */ + panel.changed && this._triggerEvent(EVENTS.flickEnd); + } + + !(phase === "start" && pos === undefined) && this._adjustContainerCss(phase); + }, + + /** + * Get positive or negative according direction + */ + _getNumByDirection: function() { + var conf = this._conf; + return conf.touch.direction === conf.dirData[0] ? 1 : -1; + }, + + /** + * Revert panel number + */ + _revertPanelNo: function() { + var panel = this._conf.panel; + var num = this._getNumByDirection(); + + var index = panel.currIndex >= 0 ? panel.currIndex : panel.index - num; + var no = panel.currNo >= 0 ? panel.currNo : panel.no - num; + + this._setPanelNo({ + index: index, + no: no + }); + }, + + /** + * Set the panel number + * @param {Object} obj number object + */ + _setPanelNo: function (obj) { + var panel = this._conf.panel; + var count = panel.origCount - 1; + var num = this._getNumByDirection(); + + if ($.isPlainObject(obj)) { + $.each(obj, function(i, v) { + panel[i] = v; + }); + + } else { + // remember current value + panel.currIndex = panel.index; + panel.currNo = panel.no; + + panel.index += num; + panel.no += num; + } + + if (panel.no > count) { + panel.no = 0; + } else if (panel.no < 0) { + panel.no = count; + } + }, + + /** + * Set pointerEvents css property on container element due to the iOS click bug + * @param {Event} e + */ + _setPointerEvents: function (e) { + var pointer = this.$container.css("pointerEvents"); + var val; + + if (e && e.holding && + e.hammerEvent && e.hammerEvent.preventSystemEvent && + pointer !== "none" + ) { + val = "none"; + } else if (!e && pointer !== "auto") { + val = "auto"; + } + + val && this.$container.css("pointerEvents", val); + }, + + /** + * Get coordinate value with unit + * @param coords {Array} x,y numeric value + * @return {Object} x,y coordinate value with unit + */ + _getCoordsValue: function (coords) { + // the param comes as [ val, 0 ], whatever the direction. So reorder the value depend the direction. + coords = this._getDataByDirection(coords); + + return { + x: this._getUnitValue(coords[0]), + y: this._getUnitValue(coords[1]) + }; + }, + + /** + * Set translate property value + * @param {Array} coords coordinate x,y value + */ + _setTranslate: function (coords) { + coords = this._getCoordsValue(coords); + this._setMoveStyle(this.$container, [ coords.x, coords.y ]); + }, + + /** + * Return unit formatted value + * @param {Number|String} val + * @return {String} val Value formatted with unit + */ + _getUnitValue: function (val) { + var rx = /(?:[a-z]{2,}|%)$/; + return (parseInt(val, 10) || 0) + (String(val).match(rx) || "px"); + }, + + /** + * Check if panel passed through threshold pixel + */ + _isMovable: function () { + var options = this.options; + var mcInst = this._mcInst; + var isMovable = Math.abs(this._conf.touch.distance) >= options.threshold; + var max; + var currPos; + + if (!options.circular && isMovable) { + max = this._getDataByDirection(mcInst.options.max)[0]; + currPos = this._getDataByDirection(mcInst.get())[0]; + + // if current position out of range + if (currPos < 0 || currPos > max) { + return false; + } + } + + return isMovable; + }, + + /** + * Trigger custom events + * @param {String} name - event name + * @param {Object} param - additional event value + * @return {Boolean} + */ + _triggerEvent: function (name, param) { + var conf = this._conf; + var panel = conf.panel; + + // pass changed panel no only on 'flickEnd' event + if (name === EVENTS.flickEnd) { + panel.currNo = panel.no; + panel.currIndex = panel.index; + } + + return this.trigger(conf.eventPrefix + name, $.extend({ + eventType: name, + index: panel.currIndex, + no: panel.currNo, + direction: conf.touch.direction + }, param)); + }, + + /** + * Get next/prev panel element/index. + * @param {Boolean} direction + * @param {Boolean} element - true:to get element, false:to get index + * @param {Number} physical - true : physical, false : logical + * @return {jQuery|Number} + */ + _getElement: function (direction, element, physical) { + var panel = this._conf.panel; + var circular = this.options.circular; + var pos = panel.currIndex; + var next = direction === this._conf.dirData[0]; + var result = null; + var total; + var index; + var currentIndex; + + if (physical) { + total = panel.count; + index = pos; + } else { + total = panel.origCount; + index = panel.currNo; + } + + currentIndex = index; + + if (next) { + if (index < total - 1) { + index++; + } else if (circular) { + index = 0; + } + } else { + if (index > 0) { + index--; + } else if (circular) { + index = total - 1; + } + } + + if (currentIndex !== index) { + result = element ? $(panel.$list[next ? pos + 1 : pos - 1]) : index; + } + + return result; + }, + + /** + * Set value to force move panels when duration is 0 + * @param {Boolean} next + */ + _setValueToMove: function (next) { + var conf = this._conf; + + conf.touch.distance = this.options.threshold + 1; + conf.touch.direction = conf.dirData[ +!next ]; + }, + + /** + * Check and parse value to number + * @param {Number|String} val + * @param {Number} defVal + * @return {Number} + */ + _getNumValue: function (val, defVal) { + return isNaN(val = parseInt(val, 10)) ? defVal : val; + }, + + /** + * Returns the index number of the current panel element. + * @ko 현재 패널 엘리먼트의 인덱스 번호를 반환한다 + * @method eg.Flicking#getIndex + * @param {Boolean} [physical=false] Types of index numbers
- true: Indicates physical index numbers relative to DOM.
- false: Indicates logical index numbers relative to the panel content. − 인덱스 번호의 종류
- true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.
- false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.
+ * @return {Number} Index number of the current panel element 현재 패널의 인덱스 번호 + */ + getIndex: function (physical) { + return this._conf.panel[ physical ? "currIndex" : "currNo" ]; + }, + + /** + * Returns the reference of the current panel element. + * @ko 현재 패널 엘리먼트의 레퍼런스를 반환한다 + * @method eg.Flicking#getElement + * @return {jQuery} Current element 현재 엘리먼트 + */ + getElement: function () { + var panel = this._conf.panel; + return $(panel.$list[ panel.currIndex ]); + }, + + /** + * Returns the reference of the next panel element. + * @ko 다음 패널 엘리먼트의 레퍼런스를 반환한다. + * @method eg.Flicking#getNextElement + * @return {jQuery|null} Next panel element or null if it does not exist.다음 패널 엘리먼트. 패널이 없으면 'null'을 반환한다. + */ + getNextElement: function () { + return this._getElement(this._conf.dirData[0], true); + }, + + /** + * Returns the index number of the next panel element. + * @ko 다음 패널 엘리먼트의 인덱스 번호를 반환한다 + * @method eg.Flicking#getNextIndex + * @param {Boolean} [physical=false] Types of index numbers
- true: Indicates physical index numbers relative to DOM.
- false: Indicates logical index numbers relative to the panel content. − 인덱스 번호의 종류
- true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.
- false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.
+ * @return {Number|null} Index number of the next panel element or null if it does not exist. 다음 패널 엘리먼트의 인덱스 번호. 패널이 없으면 'null'을 반환한다 + */ + getNextIndex: function (physical) { + return this._getElement(this._conf.dirData[0], false, physical); + }, + + /** + * Returns the references of whole panel elements. + * @ko 패널을 구성하는 모든 엘리먼트의 레퍼런스를 반환한다 + * @method eg.Flicking#getAllElements + * @return {jQuery} Whole panel elements 모든 패널 엘리먼트 + */ + getAllElements: function () { + return this._conf.panel.$list; + }, + + /** + * Returns the reference of the previous panel element. + * @ko 이전 패널 엘리먼트의 레퍼런스를 반환한다. + * @method eg.Flicking#getPrevElement + * @return {jQuery|null} Previous panel element or null if it does not exist. 이전 패널 엘리먼트. 패널이 없으면 'null'을 반환한다 + */ + getPrevElement: function () { + return this._getElement(this._conf.dirData[1], true); + }, + + /** + * Returns the index number of the previous panel element. + * @ko 이전 패널 엘리먼트의 인덱스 번호를 반환한다 + * @method eg.Flicking#getPrevIndex + * @param {Boolean} [physical=false] Types of index numbers
- true: Indicates physical index numbers relative to DOM.
- false: Indicates logical index numbers relative to the panel content. − 인덱스 번호의 종류
- true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.
- false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.
+ * @return {Number|null} Previous element index value or null if no more element exist이전 패널 인덱스 번호. 패널이 없는 경우에는 null + */ + getPrevIndex: function (physical) { + return this._getElement(this._conf.dirData[1], false, physical); + }, + + /** + * Returns the total number of whole panel elements. + * @ko 전체 패널 엘리먼트의 개수를 반환한다 + * @method eg.Flicking#getTotalCount + * @deprecated since 1.3.0 + * @param {Boolean} [physical=false] Number of elements relative to (true: DOM, false: panel content)엘리먼트 개수의 기준(true: DOM 엘리먼트 기준, false: 패널 콘텐츠 기준) + * @return {Number} Total number of whole panel elements 모든 패널 엘리먼트의 개수 + */ + getTotalCount: function (physical) { + return this._conf.panel[ physical ? "count" : "origCount" ]; + }, + + /** + * Checks whether the animated panel is playing. + * @ko 패널 이동 애니메이션이 진행 중인지 확인한다. + * @method eg.Flicking#isPlaying + * @return {Boolean} Indicates whether the animated panel is playing 패널 이동 애니메이션 진행 중 여부 + */ + isPlaying: function () { + return this._conf.panel.animating; + }, + + /** + * Move panel to the given direction + * @param {Boolean} next + * @param {Number} duration + */ + _movePanel: function (next, duration) { + var conf = this._conf; + var panel = conf.panel; + var options = this.options; + + if (panel.animating || conf.touch.holding) { + return; + } + + this._setValueToMove(next); + + if (options.circular || + this[next ? "getNextIndex" : "getPrevIndex"]() != null + ) { + this._movePanelByPhase("setBy", [ + panel.size * (next ? 1 : -1), 0 + ], duration); + } + + return this; + }, + + /** + * Move panel applying start/end phase value + * @param {String} method movableCoord method name + * @param {Object} coords coordinate array value + * @param {Number} duration duration value + */ + _movePanelByPhase: function(method, coords, duration) { + duration = this._getNumValue(duration, this.options.duration); + + if (this._setPhaseValue("start") !== false) { + this._setMovableCoord(method, coords, true, duration); + !duration && this._setPhaseValue("end"); + } + }, + + /** + * Moves an element to the next panel. + * @ko 다음 패널로 이동한다. + * @method eg.Flicking#next + * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) 패널 이동 애니메이션 진행 시간(단위: ms) + * @return {eg.Flicking} An instance of a module itself 모듈 자신의 인스턴스 + */ + next: function (duration) { + return this._movePanel(true, duration); + }, + + /** + * Moves an element to the previous panel. + * @ko 이전 패널로 이동한다. + * @method eg.Flicking#prev + * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) 패널 이동 애니메이션 진행 시간(단위: ms) + * @return {eg.Flicking} An instance of a module itself모듈 자신의 인스턴스 + */ + prev: function (duration) { + return this._movePanel(false, duration); + }, + + /** + * Moves an element to the indicated panel. + * @ko 지정한 패널로 이동한다. + * @method eg.Flicking#moveTo + * @param {Number} no Logical index number of the target panel element, which is relative to the panel content. 이동할 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다 + * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) 패널 이동 애니메이션 진행 시간(단위: ms) + * @return {eg.Flicking} An instance of a module itself모듈 자신의 인스턴스 + */ + moveTo: function (no, duration) { + var conf = this._conf; + var panel = conf.panel; + var circular = this.options.circular; + var currentIndex = panel.index; + var indexToMove; + var isPositive; + + no = this._getNumValue(no, -1); + + if (no < 0 || no >= panel.origCount || no === panel.no || + panel.animating || conf.touch.holding) { + return this; + } + + if (circular) { + indexToMove = no - panel.no; + isPositive = indexToMove > 0; + + // check for real panel count which can be moved on each sides + if (Math.abs(indexToMove) > (isPositive ? + panel.count - (currentIndex + 1) : currentIndex)) { + indexToMove = indexToMove + (isPositive ? -1 : 1) * panel.count; + } + + this._setPanelNo({ no: no }); + } else { + indexToMove = no - currentIndex; + this._setPanelNo({ index: no, no: no }); + } + + this._conf.indexToMove = indexToMove; + this._setValueToMove(isPositive); + + this._movePanelByPhase( + circular ? "setBy" : "setTo", + [ panel.size * (circular ? indexToMove : no), 0 ], + duration + ); + + return this; + }, + + /** + * Update panel's previewPadding size according options.previewPadding + */ + _checkPadding: function () { + var options = this.options; + var previewPadding = options.previewPadding.concat(); + var padding = this.$wrapper.css("padding").split(" "); + + options.horizontal && padding.reverse(); + + // get current padding value + padding = padding.length === 2 ? + [ padding[0], padding[0] ] : [ padding[0], padding[2] ]; + + padding = $.map(padding, function(num) { + return parseInt(num, 10); + }); + + // update padding when current and given are different + if (previewPadding.length === 2 && + previewPadding[0] !== padding[0] || previewPadding[1] !== padding[1]) { + + this._setPadding(previewPadding); + } + }, + + /** + * Updates the size of the panel. + * @ko 패널의 크기를 갱신한다 + * @method eg.Flicking#resize + * @return {eg.Flicking} An instance of a module itself모듈 자신의 인스턴스 + * @example + var some = new eg.Flicking("#mflick", { + previewPadding: [10,10] + }); + + // when device orientaion changes + some.resize(); + + // or when changes previewPadding option from its original value + some.options.previewPadding = [20, 30]; + some.resize(); + */ + resize: function () { + var conf = this._conf; + var options = this.options; + var panel = conf.panel; + var horizontal = options.horizontal; + var panelSize; + var maxCoords; + + if (~~options.previewPadding.join("")) { + this._checkPadding(); + panelSize = panel.size; + } else if (horizontal) { + panelSize = panel.size = this.$wrapper.width(); + } + + maxCoords = this._getDataByDirection([panelSize * (panel.count - 1), 0]); + + // resize elements + horizontal && this.$container.width(maxCoords[0] + panelSize); + panel.$list.css(horizontal ? "width" : "height", panelSize); + + this._mcInst.options.max = maxCoords; + this._setMovableCoord("setTo", [panelSize * panel.index, 0], true, 0); + + if (IS_ANDROID2) { + this._applyPanelsPos(); + this._adjustContainerCss("end"); + } + + return this; + }, + + /** + * Restores an element to its original position when it movement stops while the element is not dragged until a certain distance threshold is reached. + * @ko 다음 패널로 바뀌기 전에 패널 이동이 멈췄을 때 원래 패널로 복원한다 + * @method eg.Flicking#restore + * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) 패널 이동 애니메이션 진행 시간(단위: ms) + * @return {eg.Flicking} An instance of a module itself모듈 자신의 인스턴스 + * @example + var some = new eg.Flicking("#mflick").on({ + beforeFlickStart : function(e) { + if(e.no === 2) { + e.stop(); // stop flicking + this.restore(100); // restoring to previous position + } + } + ); + */ + restore: function (duration) { + var conf = this._conf; + var panel = conf.panel; + var currPos = this._getDataByDirection(this._mcInst.get()); + var destPos; + + // check if the panel isn't in right position + if (currPos[0] !== panel.currIndex * panel.size) { + conf.customEvent.restoreCall = true; + duration = this._getNumValue(duration, this.options.duration); + + this._revertPanelNo(); + destPos = this._getDataByDirection([panel.size * panel.index, 0]); + + this._triggerBeforeRestore({ depaPos: currPos, destPos: destPos }); + this._setMovableCoord("setTo", destPos, true, duration); + + if (!duration) { + this._adjustContainerCss("end"); + this._triggerRestore(); + } + + // to handle on api call + } else if (panel.changed) { + this._revertPanelNo(); + conf.touch.distance = conf.indexToMove = 0; + } + + return this; + }, + + /** + * Set input event biding + * @param {Boolean} bind - true: bind, false: unbind + * @return {eg.Flicking} instance of itself + */ + _setInputEvent: function(bind) { + var inputEvent = this._conf.inputEvent; + + if (bind ^ inputEvent) { + this._bindEvents(bind); + } + + return this; + }, + + /** + * Enables input devices. + * @ko 입력 장치를 사용할 수 있게 한다 + * @method eg.Flicking#enableInput + * @return {eg.Flicking} An instance of a module itself 모듈 자신의 인스턴스 + */ + enableInput: function() { + return this._setInputEvent(true); + }, + + /** + * Disables input devices. + * @ko 입력 장치를 사용할 수 없게 한다. + * @method eg.Flicking#disableInput + * @return {eg.Flicking} An instance of a module itself 모듈 자신의 인스턴스 + */ + disableInput: function() { + return this._setInputEvent(); + }, + + /** + * Destroys elements, properties, and events used in a panel. + * @ko 패널에 사용한 엘리먼트와 속성, 이벤트를 해제한다 + * @method eg.Flicking#destroy + */ + destroy: function() { + var conf = this._conf; + var origPanelStyle = conf.origPanelStyle; + var wrapper = origPanelStyle.wrapper; + var list = origPanelStyle.list; + + // unwrap container element and restore original inline style + this.$wrapper.attr("class", wrapper.className) + .attr("style", wrapper.style); + + this.$container.children().unwrap().each(function(i, v) { + var $el = $(v); + + if (i > list.length - 1) { + return !!$el.remove(); + } + + $el.attr("class", list[i].className) + .attr("style", list[i].style); + }); + + // unbind events + this.disableInput(); + this.off(); + + // release resources + for (var x in this) { + this[x] = null; + } + } + }); +}); +/** + * A jQuery plugin available in the eg.Flicking module. + * + * @ko eg.Flicking 모듈의 jQuery 플러그인 + * @method jQuery.flicking + * @example +
+
+

Layer 0

+
+
+

Layer 1

+
+
+

Layer 2

+
+
+ + * @see eg.Flicking + */ +/** + * A jQuery custom event of the eg.Flicking module. This event is fired before an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached. + * + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원되기 전에 발생한다 + * @name jQuery#flicking:beforeRestore + * @event + * @example + $("#mflick").on("flicking:beforeRestore",callback); + $("#mflick").off("flicking:beforeRestore",callback); + $("#mflick").trigger("flicking:beforeRestore",callback); + * @see eg.Flicking#event:beforeRestore + */ +/** + * A jQuery custom event of the eg.Flicking module, which occurs before the flicking starts. + * + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 플리킹을 시작하기 전에 발생한다 + * @name jQuery#flicking:beforeFlickStart + * @event + * @example + $("#mflick").on("flicking:beforeFlickStart",callback); + $("#mflick").off("flicking:beforeFlickStart",callback); + $("#mflick").trigger("flicking:beforeFlickStart",callback); + * @see eg.Flicking#event:beforeFlickStart + */ +/** + * A jQuery custom event of the eg.Flicking module. This event is fired when panel moves. + * + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 패널이 이동될 때 발생한다 + * @name jQuery#flicking:flick + * @event + * @example + $("#mflick").on("flicking:flick",callback); + $("#mflick").off("flicking:flick",callback); + $("#mflick").trigger("flicking:flick",callback); + * @see eg.Flicking#event:flick + */ +/** + * A jQuery custom event of the eg.Flicking module. This event is fired after the panel moves. + * + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 패널이 이동된 뒤 발생한다 + * @name jQuery#flicking:flickEnd + * @event + * @example + $("#mflick").on("flicking:flickEnd",callback); + $("#mflick").off("flicking:flickEnd",callback); + $("#mflick").trigger("flicking:flickEnd",callback); + * @see eg.Flicking#event:flickEnd + */ +/** + * A jQuery custom event of the eg.Flicking module. This event is fired after an element is restored to its original position when user action is done while the element has not bene dragged until a certain distance threshold is reached. + * + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원된 다음 발생한다 + * @name jQuery#flicking:restore + * @event + * @example + $("#mflick").on("flicking:restore",callback); + $("#mflick").off("flicking:restore",callback); + $("#mflick").trigger("flicking:restore",callback); + * @see eg.Flicking#event:restore + */ + +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +// jscs:disable validateLineBreaks, maximumLineLength +eg.module("infiniteGrid", ["jQuery", eg, window, document], function($, ns, global, doc) { +/** + * A module used to arrange card elements including content infinitely on a grid layout. With this module, you can implement a grid-pattern user interface composed of different card elements whose sizes vary. It guarantees performance by maintaining the number of DOMs the module is handling under any circumstance + * @group egjs + * @ko 콘텐츠가 있는 카드 엘리먼트를 그리드 레이아웃에 무한으로 배치하는 모듈. 다양한 크기의 카드 엘리먼트를 격자 모양으로 배치하는 UI를 만들 수 있다. 카드 엘리먼트의 개수가 계속 늘어나도 모듈이 처리하는 DOM의 개수를 일정하게 유지해 최적의 성능을 보장한다 + * @class + * @name eg.InfiniteGrid + * @extends eg.Component + * + * @param {HTMLElement|String|jQuery} element A base element for a module 모듈을 적용할 기준 엘리먼트 + * @param {Object} [options] The option object of the eg.InfiniteGrid module eg.InfiniteGrid 모듈의 옵션 객체 + * @param {String} [options.itemSelector] A selector to select card elements that make up the layout (@deprecated since 1.3.0)레이아웃을 구성하는 카드 엘리먼트를 선택할 선택자(selector) (@deprecated since 1.3.0) + * @param {Number} [options.count=30] The number of DOMs handled by module. If the count value is greater than zero, the number of DOMs is maintained. If the count value is zero or less than zero, the number of DOMs will increase as card elements are added. 모듈이 유지할 실제 DOM의 개수. count 값이 0보다 크면 DOM 개수를 일정하게 유지한다. count 값이 0 이하면 카드 엘리먼트가 추가될수록 DOM 개수가 계속 증가한다. + * @param {String} [options.defaultGroupKey=null] The default group key configured in a card element contained in the markup upon initialization of a module object 모듈 객체를 초기화할 때 마크업에 있는 카드 엘리먼트에 설정할 그룹 키 + * @param {Boolean} [options.isEqualSize=false] Indicates whether sizes of all card elements are equal to one another. If sizes of card elements to be arranged are all equal and this option is set to "true", the performance of layout arrangement can be improved. 카드 엘리먼트의 크기가 동일한지 여부. 배치될 카드 엘리먼트의 크기가 모두 동일할 때 이 옵션을 'true'로 설정하면 레이아웃 배치 성능을 높일 수 있다 + * @param {Number} [options.threshold=300] The threshold size of an event area where card elements are added to a layout.
- append event: If the current vertical position of the scroll bar is greater than "the bottom property value of the card element at the top of the layout" plus "the value of the threshold option", the append event will occur.
- prepend event: If the current vertical position of the scroll bar is less than "the bottom property value of the card element at the top of the layout" minus "the value of the threshold option", the prepend event will occur. − 레이아웃에 카드 엘리먼트를 추가하는 이벤트가 발생하는 기준 영역의 크기.
- append 이벤트: 현재 스크롤의 y 좌표 값이 '레이아웃의 맨 아래에 있는 카드 엘리먼트의 top 속성의 값 + threshold 옵션의 값'보다 크면 append 이벤트가 발생한다.
- prepend 이벤트: 현재 스크롤의 y 좌표 값이 '레이아웃의 맨 위에 있는 카드 엘리먼트의 bottom 속성의 값 - threshold 옵션의 값'보다 작으면 prepend 이벤트가 발생한다
+ * + * @codepen {"id":"zvrbap", "ko":"InfiniteGrid 데모", "en":"InfiniteGrid example", "collectionId":"DPYEww", "height": 403} + * @support {"ie": "8+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * + * @example + +
    +
  • +
    test1
    +
  • +
  • +
    test2
    +
  • +
  • +
    test3
    +
  • +
  • +
    test4
    +
  • +
  • +
    test5
    +
  • +
  • +
    test6
    +
  • +
+ + */ + var EVENTS = { + "layoutComplete": "layoutComplete", + "append": "append", + "prepend": "prepend" + }; + ns.InfiniteGrid = ns.Class.extend(ns.Component, { + _events: function() { + return EVENTS; + }, + construct: function(el, options, _prefix) { + this.options = $.extend({ + isEqualSize: false, + defaultGroupKey: null, + count: 30, + threshold: 300 + }, options); + + // if el is jQuery instance, el should change to HTMLElement. + this.$el = el instanceof $ ? el : $(el); + this.el = this.$el.get(0); + this.el.style.position = "relative"; + this._prefix = _prefix || ""; + this._isIos = /iPhone|iPad/.test(global.navigator.userAgent); + this._isIE10lower = !!(doc.documentMode && doc.documentMode < 10); + this._appendCols = this._prependCols = []; + this.$view = $(global); + this._reset(); + this._refreshViewport(); + if (this.el.children.length > 0) { + this.items = this._itemize($.makeArray(this.el.children), this.options.defaultGroupKey, true); + this.layout(this.items, true); + } + + this._onScroll = $.proxy(this._onScroll, this); + this._onResize = $.proxy(this._onResize, this); + this.$view.on("scroll", this._onScroll) + .on("resize", this._onResize); + }, + _getScrollTop: function() { + return doc.body.scrollTop || doc.documentElement.scrollTop; + }, + _onScroll: function() { + if (this.isProcessing()) { + return; + } + var scrollTop = this._getScrollTop(); + var prevScrollTop = this._prevScrollTop; + + if (this._isIos && scrollTop === 0 || prevScrollTop === scrollTop) { + return; + } + var ele; + var rect; + if (prevScrollTop < scrollTop) { + if ($.isEmptyObject(this._bottomElement)) { + this._bottomElement = this.getBottomElement(); + if (this._bottomElement == null) { + return; + } + } + ele = this._bottomElement; + rect = ele.getBoundingClientRect(); + if (rect.top <= this._clientHeight + this.options.threshold) { + /** + * This event is fired when a card element must be added at the bottom of a grid layout because there is no card to be displayed on screen when a user scrolls near bottom. + * @ko 카드 엘리먼트가 그리드 레이아웃의 아래에 추가돼야 할 때 발생하는 이벤트. 사용자가 아래로 스크롤해서 화면에 표시될 카드가 없을 때 발생한다 + * @name eg.InfiniteGrid#append + * @event + * + * @param {Object} param The object of data to be sent to an event 이벤트에 전달되는 데이터 객체 + * @param {Number} param.scrollTop Current vertical position of the scroll bar현재 스크롤의 y 좌표 값 + */ + this.trigger(this._prefix + EVENTS.append, { + scrollTop: scrollTop + }); + } + } else { + if (this.isRecycling() && this._removedContent > 0) { + if ($.isEmptyObject(this._topElement)) { + this._topElement = this.getTopElement(); + if (this._topElement == null) { + return; + } + } + ele = this._topElement; + rect = ele.getBoundingClientRect(); + if (rect.bottom >= -this.options.threshold) { + /** + * This event is fired when a card element must be added at the top of a grid layout because there is no card to be displayed on screen when a user scrolls near top. This event is available only if the isRecycling() method returns true. + * @ko 카드가 그리드 레이아웃의 위에 추가돼야 할 때 발생하는 이벤트. 사용자가 위로 스크롤해서 화면에 표시될 카드가 없을 때 발생한다. 이 이벤트는 isRecycling() 메서드의 반환값이 'true'일 때만 발생한다 + * @name eg.InfiniteGrid#prepend + * @event + * + * @param {Object} param The object of data to be sent to an event이벤트에 전달되는 데이터 객체 + * @param {Number} param.scrollTop Current vertical position of the scroll bar현재 스크롤의 y 좌표 값 + */ + var croppedDistance = this.fit(); + if (croppedDistance > 0) { + scrollTop -= croppedDistance; + this.$view.scrollTop(scrollTop); + } + this.trigger(this._prefix + EVENTS.prepend, { + scrollTop: scrollTop + }); + } + } + } + this._prevScrollTop = scrollTop; + }, + _onResize: function() { + if (this._resizeTimeout) { + clearTimeout(this._resizeTimeout); + } + var self = this; + this._resizeTimeout = setTimeout(function() { + self._refreshViewport(); + (self.$el.innerWidth() !== self._containerWidth) && self.layout(self.items, true); + self._resizeTimeout = null; + }, 100); + }, + _refreshViewport: function() { + this._clientHeight = this.$view.height(); + }, + /** + * Returns the current state of a module such as location information. You can use the setStatus() method to restore the information returned through a call to this method. + * @ko 카드의 위치 정보 등 모듈의 현재 상태 정보를 반환한다. 이 메서드가 반환한 정보를 저장해 두었다가 setStatus() 메서드로 복원할 수 있다 + * @method eg.InfiniteGrid#getStatue + * @return {Object} State object of the eg.InfiniteGrid moduleeg.InfiniteGrid 모듈의 상태 객체 + */ + getStatus: function() { + var data = {}; + var p; + for (p in this) { + if (this.hasOwnProperty(p) && /^_/.test(p) && + typeof this[p] !== "function" && !(this[p] instanceof Element)) { + data[p] = this[p]; + } + } + return { + prop: data, + options: $.extend({}, this.options), + items: $.map(this.items, function(v) { + var clone = $.extend({}, v); + delete clone.el; + return clone; + }), + html: this.el.innerHTML, + cssText: this.el.style.cssText + }; + }, + /** + * Sets the state of the eg.InfiniteGrid module with the information returned through a call to the getStatue() method. + * @ko getStatue() 메서드가 저장한 정보로 eg.InfiniteGrid 모듈의 상태를 설정한다. + * @method eg.InfiniteGrid#setStatus + * @param {Object} status State object of the eg.InfiniteGrid module eg.InfiniteGrid 모듈의 상태 객체 + * @return {eg.InfiniteGrid} An instance of a module itself모듈 자신의 인스턴스 + */ + setStatus: function(status) { + if (!status || !status.cssText || !status.html || + !status.prop || !status.items) { + return this; + } + this.el.style.cssText = status.cssText; + this.el.innerHTML = status.html; + $.extend(this, status.prop); + this._topElement = this._bottomElement = null; + this.items = $.map(this.el.children, function(v, i) { + status.items[i].el = v; + return status.items[i]; + }); + return this; + }, + /** + * Checks whether a card element is being added. + * @ko 카드 엘리먼트 추가가 진행 중인지 확인한다 + * @method eg.InfiniteGrid#isProcessing + * @return {Boolean} Indicates whether a card element is being added 카드 엘리먼트 추가 진행 중 여부 + */ + isProcessing: function() { + return this._isProcessing; + }, + /** + * Checks whether the total number of added card elements is greater than the value of the count option. Note that the value of the count option is always greater than zero. If it returns true, the number of DOMs won't increase even though card elements are added; instead of adding a new DOM, existing DOMs are recycled to maintain the number of DOMs. + * @ko 추가된 카드 엘리먼트의 전체 개수가 count 옵션의 값보다 큰지 확인한다. 단, count 옵션의 값은 0보다 크다. 'true'가 반환되면 카드 엘리먼트가 더 추가돼도 DOM의 개수를 증가하지 않고 기존 DOM을 재활용(recycle)해 DOM의 개수를 일정하게 유지한다 + * @method eg.InfiniteGrid#isRecycling + * @return {Boolean} Indicates whether the total number of added card elements is greater than the value of the count option. 추가된 카드 엘리먼트의 전체 개수가 count 옵션의 값보다 큰지 여부 + */ + isRecycling: function() { + return (this.options.count > 0) && this._isRecycling; + }, + /** + * Returns the list of group keys which belongs to card elements currently being maintained. You can use the append() or prepend() method to configure group keys so that multiple card elements can be managed at once. If you do not use these methods to configure group keys, it returns undefined as a group key. + * @ko 현재 유지하고 있는 카드 엘리먼트의 그룹 키 목록을 반환한다. 여러 개의 카드 엘리먼트를 묶어서 관리할 수 있도록 append() 메서드나 prepend() 메서드에서 그룹 키를 지정할 수 있다. append() 메서드나 prepend() 메서드에서 그룹 키를 지정하지 않았다면 'undefined'가 그룹 키로 반환된다 + * @method eg.InfiniteGrid#getGroupKeys + * @return {Array} List of group keys 그룹 키의 목록 + */ + getGroupKeys: function() { + return $.map(this.items, function(v) { + return v.groupKey; + }); + }, + /** + * Rearranges a layout. + * @ko 레이아웃을 다시 배치한다. + * @method eg.InfiniteGrid#layout + * @return {eg.InfiniteGrid} An instance of a module itself모듈 자신의 인스턴스 + */ + layout: function(items, isRefresh) { + items = items || this.items; + isRefresh = typeof isRefresh === "undefined" ? true : isRefresh; + this._isProcessing = true; + isRefresh && (items = $.map(items, function(v) { + v.isAppend = true; + return v; + })); + this._waitResource(items, isRefresh); + return this; + }, + _layoutItems: function(items) { + var self = this; + + // for performance + $.each( + $.map(items, function(v) { + v.position = self._getItemLayoutPosition(v); + return v; + }), + function(i, v) { + if (v.el) { + var style = v.el.style; + style.left = v.position.x + "px"; + style.top = v.position.y + "px"; + } + }); + }, + /** + * Adds a card element at the bottom of a grid layout. This method is available only if the isProcessing() method returns false. + * @ko 카드 엘리먼트를 그리드 레이아웃의 아래에 추가한다. isProcessing() 메서드의 반환값이 'false'일 때만 이 메서드를 사용할 수 있다 + * 이 메소드는 isProcessing()의 반환값이 false일 경우에만 사용 가능하다. + * @method eg.InfiniteGrid#append + * @param {Array|String|jQuery} elements Array of the card elements to be added 추가할 카드 엘리먼트의 배열 + * @param {Number|String} [groupKey] The group key to be configured in a card element. It is set to "undefined" by default.추가할 카드 엘리먼트에 설정할 그룹 키. 생략하면 값이 'undefined'로 설정된다 + * @return {Number} The number of added card elements 추가된 카드 엘리먼트의 개수 + */ + append: function($elements, groupKey) { + if (this._isProcessing || $elements.length === 0) { + return; + } + + // convert jQuery instance + $elements = $($elements); + this._isProcessing = true; + if (!this.isRecycling()) { + this._isRecycling = + (this.items.length + $elements.length) >= this.options.count; + } + this._insert($elements, groupKey, true); + return $elements.length; + }, + /** + * Adds a card element at the top of a grid layout. This method is available only if the isProcessing() method returns false and the isRecycling() method returns true. + * @ko 카드 엘리먼트를 그리드 레이아웃의 위에 추가한다. isProcessing() 메서드의 반환값이 'false'이고, isRecycling() 메서드의 반환값이 'true'일 때만 이 메서드를 사용할 수 있다 + * @method eg.InfiniteGrid#prepend + * @param {Array|String|jQuery} elements Array of the card elements to be added 추가할 카드 엘리먼트 배열 + * @param {Number|String} [groupKey] The group key to be configured in a card element. It is set to "undefined" by default.추가할 카드 엘리먼트에 설정할 그룹 키. 생략하면 값이 'undefined'로 설정된다 + * @return {Number} The number of added card elements 추가된 카드 엘리먼트의 개수 + */ + prepend: function($elements, groupKey) { + if (!this.isRecycling() || this._removedContent === 0 || + this._isProcessing || $elements.length === 0) { + return; + } + + // convert jQuery instance + $elements = $($elements); + + this._isProcessing = true; + this._fit(); + if ($elements.length > this._removedContent) { + $elements = $elements.slice(0, this._removedContent); + } + this._insert($elements, groupKey, false); + return $elements.length; + }, + /** + * Clears added card elements and data. + * @ko 추가된 카드 엘리먼트와 데이터를 모두 지운다. + * @method eg.InfiniteGrid#clear + * @return {eg.InfiniteGrid} An instance of a module itself모듈 자신의 인스턴스 + */ + clear: function() { + this.el.innerHTML = ""; + this.el.style.height = ""; + this._reset(); + return this; + }, + + _getTopItem: function() { + var item = null; + var min = Infinity; + $.each(this._getColItems(false), function(i, v) { + if (v && v.position.y < min) { + min = v.position.y; + item = v; + } + }); + return item; + }, + + /** + * Returns a card element at the top of a layout. + * @ko 레이아웃의 맨 위에 있는 카드 엘리먼트를 반환한다. + * @method eg.InfiniteGrid#getTopElement + * + * @return {HTMLElement} Card element at the top of a layout 레이아웃의 맨 위에 있는 카드 엘리먼트 + */ + getTopElement: function() { + var item = this._getTopItem(); + return item && item.el; + }, + + _getBottomItem: function() { + var item = null; + var max = -Infinity; + $.each(this._getColItems(true), function(i, v) { + if (v && v.position.y + v.size.height > max) { + max = v.position.y + v.size.height; + item = v; + } + }); + return item; + }, + + /** + * Returns a card element at the bottom of a layout. + * @ko 레이아웃의 맨 아래에 있는 카드 엘리먼트를 반환한다. + * @method eg.InfiniteGrid#getBottomElement + * + * @return {HTMLElement} Card element at the bottom of a layout 레이아웃의 맨 아래에 있는 카드 엘리먼트 + */ + getBottomElement: function() { + var item = this._getBottomItem(); + return item && item.el; + }, + + _postLayout: function(items) { + if (!this._isProcessing || items.length <= 0) { + return; + } + + var size = this._getContainerSize(); + this.el.style.width = size.width + "px"; + this.el.style.height = size.height + "px"; + + // refresh element + this._topElement = this.getTopElement(); + this._bottomElement = this.getBottomElement(); + + var distance = 0; + var isAppend = items[0].isAppend; + if (!isAppend) { + this._isFitted = false; + this._fit(true); + distance = items.length >= this.items.length ? + 0 : this.items[items.length].position.y; + if (distance > 0) { + this._prevScrollTop = this._getScrollTop() + distance; + this.$view.scrollTop(this._prevScrollTop); + } + } + + // reset flags + this._isProcessing = false; + + /** + * This event is fired when layout is successfully arranged through a call to the append(), prepend(), or layout() method. + * @ko 레이아웃 배치가 완료됐을 때 발생하는 이벤트. append() 메서드나 prepend() 메서드, layout() 메서드 호출 후 카드의 배치가 완료됐을 때 발생한다 + * @name eg.InfiniteGrid#layoutComplete + * @event + * + * @param {Object} param The object of data to be sent to an event 이벤트에 전달되는 데이터 객체 + * @param {Array} param.target Rearranged card elements재배치된 카드 엘리먼트들 + * @param {Boolean} param.isAppend Checks whether the append() method is used to add a card element. It returns true even though the layoutComplete event is fired after the layout() method is called. 카드 엘리먼트가 append() 메서드로 추가됐는지 확인한다. layout() 메서드가 호출된 후 layoutComplete 이벤트가 발생해도 'true'를 반환한다. + * @param {Number} param.distance Distance the card element at the top of a grid layout has moved after the layoutComplete event is fired. In other words, it is the same as an increased height with a new card element added using the prepend() method 그리드 레이아웃의 맨 위에 있던 카드 엘리먼트가 layoutComplete 이벤트 발생 후 이동한 거리. 즉, prepend() 메서드로 카드 엘리먼트가 추가돼 늘어난 높이다. + * @param {Number} param.croppedCount The number of deleted card elements to maintain the number of DOMs일정한 DOM 개수를 유지하기 위해, 삭제한 카드 엘리먼트들의 개수 + */ + this.trigger(this._prefix + EVENTS.layoutComplete, { + target: items.concat(), + isAppend: isAppend, + distance: distance, + croppedCount: this._removedContent + }); + }, + + // $elements => $([HTMLElement, HTMLElement, ...]) + _insert: function($elements, groupKey, isAppend) { + if ($elements.length === 0) { + return; + } + var elements = $elements.toArray(); + var $cloneElements = $(elements); + var dummy = -this._clientHeight + "px"; + $.each(elements, function(i, v) { + v.style.position = "absolute"; + v.style.top = dummy; + }); + var items = this._itemize(elements, groupKey, isAppend); + if (isAppend) { + this.items = this.items.concat(items); + } else { + this.items = items.concat(this.items); + items = items.reverse(); + } + this.isRecycling() && this._adjustRange(isAppend, $cloneElements); + + this.$el[isAppend ? "append" : "prepend"]($cloneElements); + this.layout(items, false); + }, + _waitResource: function(items, isRefresh) { + var needCheck = this._checkImageLoaded(); + var self = this; + var callback = function() { + if (self._isProcessing) { + if (isRefresh || !self._appendCols.length) { + $.each(items, function(i, v) { + v.el.style.position = "absolute"; + }); + self._measureColumns(); + } + self._layoutItems(items); + self._postLayout(items); + } + }; + if (needCheck.length > 0) { + this._waitImageLoaded(needCheck, callback); + } else { + // convert to async + setTimeout(function() { + callback && callback(); + }, 0); + } + }, + _adjustRange: function (isTop, $elements) { + var diff = this.items.length - this.options.count; + var targets; + var idx; + if (diff <= 0 || (idx = this._getDelimiterIndex(isTop, diff)) < 0) { + return; + } + if (isTop) { + targets = this.items.splice(0, idx); + this._isFitted = false; + } else { + targets = this.items.splice(idx, this.items.length - idx); + } + + // @todo improve performance + $.each(targets, function(i, v) { + idx = $elements.index(v.el); + if (idx !== -1) { + $elements.splice(idx, 1); + } else { + v.el.parentNode.removeChild(v.el); + } + }); + this._removedContent += isTop ? targets.length : -targets.length; + }, + _getDelimiterIndex: function(isTop, removeCount) { + var len = this.items.length; + var i; + var idx = 0; + var baseIdx = isTop ? removeCount - 1 : len - removeCount; + var targetIdx = baseIdx + (isTop ? 1 : -1); + var groupKey = this.items[baseIdx].groupKey; + if (groupKey != null && groupKey === this.items[targetIdx].groupKey) { + if (isTop) { + for (i = baseIdx; i > 0; i--) { + if (groupKey !== this.items[i].groupKey) { + break; + } + } + idx = i === 0 ? -1 : i + 1; + } else { + for (i = baseIdx; i < len; i++) { + if (groupKey !== this.items[i].groupKey) { + break; + } + } + idx = i === len ? -1 : i; + } + } else { + idx = isTop ? targetIdx : baseIdx; + } + return idx; + }, + + // fit size + _fit: function(applyDom) { + // for caching + if (this.options.count <= 0) { + this._fit = function() { + return false; + }; + this._isFitted = true; + return false; + } + + if (this._isFitted) { + return false; + } + var y = this._updateCols(); // for prepend + $.each(this.items, function(i, v) { + v.position.y -= y; + applyDom && (v.el.style.top = v.position.y + "px"); + }); + this._updateCols(true); // for append + var height = this._getContainerSize().height; + applyDom && (this.el.style.height = height + "px"); + this._isFitted = true; + return true; + }, + + /** + * Removes extra space caused by adding card elements. + * @ko 카드 엘리먼트를 추가한 다음 생긴 빈 공간을 제거한다 + * @method eg.InfiniteGrid#fit + * @deprecated since version 1.3.0 + * @return {Number} Actual length of space removed (unit: px) 빈 공간이 제거된 실제 길이(단위: px) + */ + fit: function() { + var item = this._getTopItem(); + var distance = item ? item.position.y : 0; + this._fit(true); + return distance; + }, + _reset: function() { + this._isProcessing = false; + this._topElement = null; + this._bottomElement = null; + this._isFitted = true; + this._isRecycling = false; + this._removedContent = 0; + this._prevScrollTop = 0; + this._equalItemSize = 0; + this._resizeTimeout = null; + this._resetCols(this._appendCols.length || 0); + this.items = []; + }, + _checkImageLoaded: function() { + return this.$el.find("img").filter(function(k, v) { + if (v.nodeType && ($.inArray(v.nodeType, [1,9,11]) !== -1)) { + return !v.complete; + } + }).toArray(); + }, + _waitImageLoaded: function(needCheck, callback) { + var checkCount = needCheck.length; + var onCheck = function(e) { + checkCount--; + $(e.target).off("load error"); + checkCount <= 0 && callback && callback(); + }; + var $el; + var self = this; + $.each(needCheck, function(i, v) { + $el = $(v); + + // for IE10 lower + if (self._isIE10lower) { + var url = v.getAttribute("src"); + v.setAttribute("src", ""); + v.setAttribute("src", url); + } + $el.on("load error", onCheck); + }); + }, + _measureColumns: function() { + this.el.style.width = null; + this._containerWidth = this.$el.innerWidth(); + this._columnWidth = this._getColumnWidth() || this._containerWidth; + var cols = this._containerWidth / this._columnWidth; + var excess = this._columnWidth - this._containerWidth % this._columnWidth; + + // if overshoot is less than a pixel, round up, otherwise floor it + cols = Math.max(Math[ excess && excess <= 1 ? "round" : "floor" ](cols), 1); + + // reset column Y + this._resetCols(cols || 0); + }, + _resetCols: function(count) { + count = typeof count === "undefined" ? 0 : count; + var arr = []; + while (count--) { + arr.push(0); + } + this._appendCols = arr.concat(); + this._prependCols = arr.concat(); + }, + _getContainerSize: function() { + return { + height: Math.max.apply(Math, this._appendCols), + width: this._containerWidth + }; + }, + _getColumnWidth: function() { + var el = this.items[0] && this.items[0].el; + var width = 0; + if (el) { + var $el = $(el); + width = $el.innerWidth(); + if (this.options.isEqualSize) { + this._equalItemSize = { + width: width, + height: $el.innerHeight() + }; + } + } + return width; + }, + _updateCols: function(isAppend) { + var col = isAppend ? this._appendCols : this._prependCols; + var items = this._getColItems(isAppend); + var base = this._isFitted || isAppend ? 0 : this._getMinY(items); + var i = 0; + var len = col.length; + var item; + for (; i < len; i++) { + if (item = items[i]) { + col[i] = item.position.y + (isAppend ? item.size.height : -base); + } else { + col[i] = 0; + } + } + return base; + }, + _getMinY: function(items) { + return Math.min.apply(Math, $.map(items, function(v) { + return v ? v.position.y : 0; + })); + }, + _getColIdx: function(item) { + return parseInt(item.position.x / parseInt(this._columnWidth, 10), 10); + }, + _getColItems: function(isTail) { + var len = this._appendCols.length; + var colItems = new Array(len); + var item; + var idx; + var count = 0; + var i = isTail ? this.items.length - 1 : 0; + while (item = this.items[i]) { + idx = this._getColIdx(item); + if (!colItems[idx]) { + colItems[idx] = item; + if (++count === len) { + return colItems; + } + } + i += isTail ? -1 : 1; + } + return colItems; + }, + _itemize: function(elements, groupKey, isAppend) { + return $.map(elements, function(v) { + return { + el: v, + position: { + x: 0, + y: 0 + }, + isAppend: typeof isAppend === "undefined" ? true : isAppend, + groupKey: typeof groupKey === "undefined" ? null : groupKey + }; + }); + }, + _getItemLayoutPosition: function(item) { + if (!item.el) { + return; + } + var $el = $(item.el); + item.size = this._equalItemSize || { + width: $el.innerWidth(), + height: $el.innerHeight() + }; + var isAppend = item.isAppend; + var cols = isAppend ? this._appendCols : this._prependCols; + var y = Math[isAppend ? "min" : "max"].apply(Math, cols); + var shortColIndex; + if (isAppend) { + shortColIndex = $.inArray(y, cols); + } else { + var i = cols.length; + while (i-- >= 0) { + if (cols[i] === y) { + shortColIndex = i; + break; + } + } + } + cols[shortColIndex] = y + (isAppend ? item.size.height : -item.size.height); + + return { + x: this._columnWidth * shortColIndex, + y: isAppend ? y : y - item.size.height + }; + }, + /** + * Destroys elements, properties, and events used on a grid layout. + * @ko 그리드 레이아웃에 사용한 엘리먼트와 속성, 이벤트를 해제한다 + * @method eg.InfiniteGrid#destroy + */ + destroy: function() { + this.off(); + this.$view.off("resize", this._onResize) + .off("scroll", this._onScroll); + this._reset(); + } + }); +}); +/** + * A jQuery plugin available in the eg.InfiniteGrid module. + * @ko eg.InfiniteGrid 모듈의 jQuery 플러그인 + * @method jQuery.infiniteGrid + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid + */ +/** + * A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a layout is successfully arranged. + * + * @ko eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 레이아웃 배치가 완료됐을 때 발생한다 + * @name jQuery#infiniteGrid:layoutComplete + * @event + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid#event:layoutComplete + */ +/** + * A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a card element must be added at the bottom of a grid layout + * + * @ko eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 그리드 레이아웃 아래에 카드 엘리먼트가 추가돼야 할 때 발생한다. + * @name jQuery#infiniteGrid:append + * @event + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid#event:append + */ +/** + * A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a card element must be added at the top of a grid layout + * + * @ko eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 그리드 레이아웃 위에 카드 엘리먼트가 추가돼야 할 때 발생한다 + * @name jQuery#infiniteGrid:prepend + * @event + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid#event:prepend + */ diff --git a/dist/eg.min.js b/dist/eg.min.js new file mode 100644 index 00000000..53f289d0 --- /dev/null +++ b/dist/eg.min.js @@ -0,0 +1,17 @@ +/** +* Copyright (c) 2015 NAVER corp. +* egjs projects are licensed under the MIT license +* https://naver.github.io/egjs/license.txt +* +* egjs JavaScript library +* http://naver.github.io/egjs +* +* @version 1.3.0 +* @SHA-1 13e6ef5 (1.3.0-rc) +* +* For custom build use egjs-cli +* https://github.com/naver/egjs-cli +*/ +"use strict";!function(a,b,c){function d(a){return a>2?a+1+"th":m[a]}function e(a,b){var c;for(c in b)a=a.replace(new RegExp("{{"+c+"}}","gi"),b[c]);return a}function f(a,b){for(var f,g,h,i,j,m,n,o,p=0,q=b.length,r=[],s=[],t=c.require;q>p;p++)g=b[p],h={index:d(p),name:g,componentName:a},i="string"==typeof b[p],j=void 0===b[p],m=i&&(f=k[b[p]]),n=i&&f&&!c[b[p]],o=n&&t&&t.specified&&t.specified(b[p]),i||j?o&&t.defined(b[p])?(g=t(b[p]),s.push(g)):!o||t.defined(b[p])?n&&t&&t.specified&&!t.specified(b[p])?(h.url=f.url,r.push(e(l[1],h))):!n||t?m&&c[b[p]]?(g=c[b[p]],s.push(g)):!i||f?void 0!==b[p]||r.push(e(l[4],h)):r.push(e(l[3],h)):(h.url=f.url,r.push(e(l[2],h))):(h.url=f.url,r.push(e(l[0],h))):s.push(g);return[s,r]}function g(a){return a.charAt(0).toUpperCase()+a.slice(1)}function h(a){var c,d,e,f=g(a);if(!(i[f]&&i[f].prototype&&i[f].prototype._events))return!1;if(j.fn[a])throw new Error("The name '"+f+"' has already been used and registered as plugin. Try with different one.");j.fn[a]=function(c){var d,e;return"string"==typeof c?(d=this.data(b+"-"+a),"instance"===c?d:(e=d[c].apply(d,Array.prototype.slice.call(arguments,1)),e===d?this:e)):((void 0===c||j.isPlainObject(c))&&this.data(b+"-"+a,new i[f](this,c||{},a+":")),this)},e={trigger:"trigger",add:"on",remove:"off"},c=i[f].prototype._events();for(var h in c){d=j.event.special[a+":"+c[h]]={},d.setup=function(){return!0};for(var k in e)d[k]=function(c){return function(d,e){return j(this).data(b+"-"+a)[c](d.type,"trigger"===c?e:d.handler),!1}}(e[k])}}var i;c[b]||(c[b]={}),i=c[b];var j=c[a],k={jQuery:{url:"http://jquery.com/"},Hammer:{url:"http://hammerjs.github.io/"}},l=["[egjs] The {{name}} library must be loaded before {{componentName}}.",'[egjs] For AMD environment (like RequireJS), "{{name}}" must be declared, which is required by {{componentName}}.',"[egjs] The {{index}} argument of {{componentName}} is missing.\r\nDownload {{name}} from [{{url}}].","[egjs] The {{name}} parameter of {{componentName}} is not valid.\r\nPlease check and try again.","[egjs] The {{index}} argument of {{componentName}} is undefined.\r\nPlease check and try again."],m=["1st","2nd","3rd"],n=function(a){(n=c.console&&c.console.warn?function(a){c.console.warn(a)}:function(){})(a)};i.module||(i.module=function(a,b,d){var e=f(a,b);e[1].length?n(e[1].join("\r\n")):(d.apply(c,e[0]),h(a))})}("jQuery","eg",window),eg.module("agent",[eg],function(a){function b(a){return j(a,n.defaultString.browser)}function c(a){var b,c;return a?(c=h(a).versionSearch||a,b=d(c,m)):void 0}function d(a,b){var c,d,e=n.defaultString.browser.version,f=new RegExp("("+a+")","i").exec(b);return f?(d=f.index,a=f[0],d>-1&&(c=d+a.length+1,e=b.substring(c).split(" ")[0].replace(/_/g,".").replace(/\;|\)/g,"")),e):e}function e(a){return j(a,n.defaultString.os)}function f(a){var b,c,d,e,f=m,h=g(a)||{},i=n.defaultString.os.version;return a?h.versionAlias?h.versionAlias:(c=h.versionSearch||a,d=new RegExp("("+c+")\\s([\\d_\\.]+|\\d_0)","i"),e=d.exec(f),e&&(b=d.exec(f)[2].replace(/_/g,".").replace(/\;|\)/g,"")),b||i):void 0}function g(a){return i(n.os,a)}function h(a){return i(n.browser,a)}function i(a,b){for(var c,d,e,f=0;e=a[f];f++)if(c=e.criteria,d=new RegExp(e.identity,"i").test(b),c?d&&k(m,c):d)return e}function j(a,b){for(var c,d=0;c=a[d];d++)if(k(m,c.criteria))return c.identity||b.name;return b.name}function k(a,b){return b&&b.test?!!b.test(a):a.indexOf(b)>-1}function l(){for(var a,b,c=m,e=n.webview,f=!1,g=0;b=e[g];g++)if(k(c,b.criteria)&&(a=d(b.browserVersionSearch,c),k(c,b.webviewToken)||k(a,b.webviewBrowserVersion))){f=!0;break}return f}var m,n={browser:[{criteria:"PhantomJS",identity:"PhantomJS"},{criteria:/Edge/,identity:"Edge",versionSearch:"Edge"},{criteria:/MSIE|Trident|Windows Phone/,identity:"IE",versionSearch:"IEMobile|MSIE|rv"},{criteria:/SAMSUNG|SamsungBrowser/,identity:"SBrowser",versionSearch:"Chrome"},{criteria:/Chrome|CriOS/,identity:"Chrome"},{criteria:/Android/,identity:"default"},{criteria:/iPhone|iPad/,identity:"Safari",versionSearch:"Version"},{criteria:"Apple",identity:"Safari",versionSearch:"Version"},{criteria:"Firefox",identity:"Firefox"}],os:[{criteria:/Windows Phone|Windows NT/,identity:"Window",versionSearch:"Windows Phone|Windows NT"},{criteria:"Windows 2000",identity:"Window",versionAlias:"5.0"},{criteria:/iPhone|iPad/,identity:"iOS",versionSearch:"iPhone OS|CPU OS"},{criteria:"Mac",versionSearch:"OS X",identity:"MAC"},{criteria:/Android/,identity:"Android"}],webview:[{criteria:/iPhone|iPad/,browserVersionSearch:"Version",webviewBrowserVersion:/-1/},{criteria:/iPhone|iPad|Android/,webviewToken:/NAVER|DAUM|; wv/}],defaultString:{browser:{version:"-1",name:"default"},os:{version:"-1",name:"unknown"}}};a.Agent={create:function(a){this.ua=m=a;var d={os:{},browser:{}};return d.browser.name=b(n.browser),d.browser.version=c(d.browser.name),d.os.name=e(n.os),d.os.version=f(d.os.name),d.browser.webview=l(),d.browser.name=d.browser.name.toLowerCase(),d.os.name=d.os.name.toLowerCase(),d}}}),eg.module("eg",["jQuery",eg,window,eg.Agent],function(a,b,c,d){function e(a,b,c,d){var e=a.hook[b];return e&&(d=e.apply(a,c)),a[b]=function(){var e=a.hook[b];return e?e.apply(a,c):d},d}var f=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,g=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(f&&!g){var h={},i=f;f=function(a){function b(){h[c]&&a()}var c=i(b);return h[c]=!0,c},g=function(a){delete h[a]}}else f&&g||(f=function(a){return c.setTimeout(a,16)},g=c.clearTimeout);b.VERSION="1.3.0",b.hook={},b.agent=function(){var a=d.create(c.navigator.userAgent);return e(this,"agent",[a],a)},b.translate=function(a,b,c){return c=c||!1,"translate"+(c?"3d(":"(")+a+","+b+(c?",0)":")")},b.isHWAccelerable=function(){var a,c=!1,f=b.agent(),g=f.os.version,h=f.browser.name,i=f.browser.version;return-1!==h.indexOf("chrome")?c=i>="25":/ie|edge|firefox|safari|inapp/.test(h)?c=!0:-1!==f.os.name.indexOf("android")&&(a=(d.ua.match(/\(.*\)/)||[null])[0],c=g>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||g>="4.0.3"&&/SHW-|SHV-|GT-|SCH-|SGH-|SPH-|LG-F160|LG-F100|LG-F180|LG-F200|EK-|IM-A|LG-F240|LG-F260/.test(a)&&!/SHW-M420|SHW-M200|GT-S7562/.test(a)),e(this,"isHWAccelerable",[c,f],c)},b.isTransitional=function(){var a=!1,c=b.agent(),d=c.browser.name;if(/chrome|firefox|sbrowser/.test(d))a=!0;else switch(c.os.name){case"ios":a=/safari|inapp/.test(d)&&parseInt(c.os.version,10)<6;break;case"window":a=/safari/.test(d)||/ie/.test(d)&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/safari/.test(d)}return e(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return e(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return f(a)},b.cancelAnimationFrame=function(a){g(a)},a.extend(a.easing,{easeOutCubic:function(a){return 1-Math.pow(1-a,3)}})}),eg.module("class",[eg],function(a){a.Class=function(a){var b=function(){"function"==typeof a.construct&&a.construct.apply(this,arguments)};return b.prototype=a,b.prototype.instance=function(){return this},b.prototype.constructor=b,b},a.Class.extend=function(a,b){var c=function(){a.apply(this,arguments),"function"==typeof b.construct&&b.construct.apply(this,arguments)},d=function(){};d.prototype=a.prototype;var e=new d;for(var f in b)e[f]=b[f];return e.constructor=c,c.prototype=e,c}}),eg.module("component",[eg],function(a){a.Component=a.Class({construct:function(){this.eventHandler={},this.options={}},option:function(a,b){if(arguments.length>=2)return this.options[a]=b,this;if("string"==typeof a)return this.options[a];if(0===arguments.length)return this.options;for(var c in a)this.options[c]=a[c];return this},trigger:function(a,b){b=b||{};var c=this.eventHandler[a]||[],d=c.length>0;if(!d)return!0;c=c.concat(),b.eventType=a;var e,f,g,h=!1,i=[b];for(b.stop=function(){h=!0},(f=arguments.length)>2&&(i=i.concat(Array.prototype.slice.call(arguments,2,f))),e=0;g=c[e];e++)g.apply(this,i);return!h},hasOn:function(a){return!!this.eventHandler[a]},on:function(a,b){if("object"==typeof a&&"undefined"==typeof b){var c,d=a;for(c in d)this.on(c,d[c]);return this}if("string"==typeof a&&"function"==typeof b){var e=this.eventHandler[a];"undefined"==typeof e&&(e=this.eventHandler[a]=[]),e.push(b)}return this},off:function(a,b){if(0===arguments.length)return this.eventHandler={},this;if("undefined"==typeof b){if("string"==typeof a)return this.eventHandler[a]=void 0,this;var c=a;for(var d in c)this.off(d,c[d]);return this}var e=this.eventHandler[a];if(e){var f,g;for(f=0,g;g=e[f];f++)if(g===b){e=e.splice(f,1);break}}return this}})}),eg.module("rotate",["jQuery",eg,window,document],function(a,b,c,d){function e(){var a,b,e,f=m();return"resize"===f?(a=d.documentElement.clientWidth,e=-1===h?aa?!0:a===h?i:!1):(b=c.orientation,0===b||180===b?e=!0:(90===b||-90===b)&&(e=!1)),e}function f(){var b=e();l&&i!==b&&(i=b,h=d.documentElement.clientWidth,a(c).trigger("rotate",{isVertical:i}))}function g(a){var b,e,i=m();if("resize"===i)c.setTimeout(function(){f()},0);else{if(b=300,"android"===k.os.name&&(e=d.documentElement.clientWidth,"orientationchange"===a.type&&e===h))return c.setTimeout(function(){g(a)},500),!1;c.clearTimeout(j),j=c.setTimeout(function(){f()},b)}}var h=-1,i=null,j=null,k=b.agent(),l=/android|ios/.test(k.os.name);if(!l)return void(b.isPortrait=function(){});var m=function(){var a;return a="android"===k.os.name&&"2.1"===k.os.version?"resize":"onorientationchange"in c?"orientationchange":"resize",m=function(){return a},a};return a.event.special.rotate={setup:function(){i=e(),h=d.documentElement.clientWidth,a(c).on(m(),g)},teardown:function(){a(c).off(m(),g)},trigger:function(a){a.isVertical=i}},b.isPortrait=e,{orientationChange:m,isVertical:e,triggerRotate:f,handler:g}}),eg.module("scrollEnd",["jQuery",eg,window],function(a,b,c){function d(){var a=n,c=b.agent(),d=c.os,e=parseInt(d.version,10),f=c.browser;return f.webview||("ios"===d.name&&7>=e?a=p:"android"===d.name&&"default"===f.name&&2.3>=e&&(a=p)),a}function e(){a(c).on("scroll",g),a(c).on("orientationchange",f)}function f(){l=!0}function g(){if(l)return void(l=!1);switch(r){case p:h();break;case n:i()}}function h(){a(c).trigger("scrollend",{top:c.pageYOffset,left:c.pageXOffset})}function i(){clearTimeout(k),k=setTimeout(function(){return l?void(l=!1):void h()},q)}function j(){a(c).off("scroll",g),a(c).off("orientationchange",f)}var k,l=!1,m=3,n=2,o=1,p=0,q=250,r=d();return a.event.special.scrollend={setup:function(){e()},teardown:function(){j()}},{getDeviceType:d,CHROME:m,TIMERBASE:n,TOUCHBASE:o,SCROLLBASE:p}}),eg.module("transform",["jQuery",window],function(a){function b(a,b){var c=a,d=a.match(/((-|\+)*[0-9]+)%/);return d&&d.length>=1?c=b*(parseFloat(d[1])/100)+"px":-1===a.indexOf("px")&&(c=a+"px"),c}function c(a,c,d){for(var e,f="",g=a.split(")"),h=0,i=g.length-1;i>h;h++){var j=g[h];if((e=j.match(/(translate([XYZ]|3d)?|rotate)\(([^)]*)/))&&e.length>1)if("rotate"===e[1])-1===e[3].indexOf("deg")&&(j=e[1]+"("+e[3]+"deg");else switch(e[2]){case"X":j=e[1]+"("+b(e[3],c);break;case"Y":j=e[1]+"("+b(e[3],d);break;case"Z":break;default:for(var k=e[3].split(","),l=[c,d,100],m=0,n=k.length;n>m;m++)k[m]=b(k[m],l[m]);j=e[1]+"("+k.join(",")}j=" "+j+")",f+=j}return f=f.replace("%","").replace("+=","")}function d(a){var b=a.match(/((-|\+)*[\d|\.]+)(px|deg|rad)*/);return b&&b.length>=1?{num:parseFloat(b[1]),unit:b[3]}:void 0}function e(b){for(var c=b.split(")"),e=[],f=0,g=c.length-1;g>f;f++){var h=i(c[f]);h[1]=a.map(h[1],d),e.push(h)}return function(b){var c="",d=0;return a.each(e,function(f){d=e[f][0].indexOf("scale")>=0?1:0;var g=a.map(e[f][1],function(a){var c=a.num;return 1===d&&(c-=1),d+c*b+(a.unit||"")}).join(",");c+=e[f][0]+"("+g+") "}),c}}function f(b,d,f){var h,i,l,m=f.indexOf("+=")>=0;return f=c(f,parseFloat(a.css(b,"width"))||0,parseFloat(a.css(b,"height"))||0),m?(h=d&&"none"!==d?d:"matrix(1, 0, 0, 1, 0, 0)",i=e(f)):(h=j(d),l=j("none"),h[1].lengthl[1].length&&(l=k(l)),i=e(f)),function(a){var b=[],c="";if(m)return h+i(a);if(1===a)c=g(l);else{for(var d,e,f=0,j=h[1].length;j>f;f++)d=parseFloat(h[1][f]),e=parseFloat(l[1][f]),b.push(d+(e-d)*a);c=g([h[0],b])}return c+i(a)}}function g(b){var c,d=[];if(a.isArray(b))return c=b[0],c+"("+b[1].join(h(c)+",")+h(c)+")";for(c in b)d.push(c);return a.map(d,function(a){return a+"("+b[a]+h(a)+")"}).join(" ")}function h(a){return a.indexOf("translate")>=0?"px":a.indexOf("rotate")>=0?"deg":""}function i(b){var c,d,e=b.match(/(\b\w+?)\((\s*[^\)]+)/),f=["",""];return e&&e.length>2&&(c=e[1],d=e[2].split(","),d=a.map(d,function(b){return a.trim(b)}),f=[a.trim(c),d]),f}function j(a){var b;return a&&"none"!==a?(a=a.replace(/\s/g,""),b=a.match(/(matrix)(3d)*\((.*)\)/),[b[1]+(b[2]||""),b[3].split(",")]):["matrix",["1","0","0","1","0","0"]]}function k(a){var b=a[0],c=a[1];return"matrix3d"===b?a:[b+"3d",[c[0],c[1],"0","0",c[2],c[3],"0","0","0","0","1","0",c[4],c[5],"0","1"]]}return a.fx.step.transform=function(b){b.rateFn=b.rateFn||f(b.elem,b.start,b.end),a.style(b.elem,"transform",b.rateFn(b.pos))},{toMatrix:j,toMatrix3d:k}}),eg.module("cssPrefix",["jQuery",document],function(a,b){if(!a.cssHooks)throw new Error("jQuery 1.4.3+ is needed for this plugin to work");var c=(a.fn.jquery.match(/^\d\.\d+/)||[])[0];if(c&&!(+c.replace(/\D/,"")>=18)){var d=["Webkit","Moz","O","ms"],e=["transitionProperty","transitionDuration","transition","transform","transitionTimingFunction"],f=function(){for(var a=(b.head||b.getElementsByTagName("head")[0]).style,c=0,e=d.length;e>c;c++)if(d[c]+"Transition"in a)return d[c]}();if(f){for(var g=function(b){var c=b.charAt(0).toUpperCase()+b.slice(1),d=f+c,e="ms"===f?"Ms"+c:d;a.cssHooks[c]=a.cssHooks[f.toLowerCase()+c]=a.cssHooks[b]={get:function(b,c){return c?a.css(b,e):b.style[d]},set:function(a,b){a.style[d]=b}}},h=0,i=e.length;i>h;h++)g(e[h]);return{vendorPrefix:f,setCssHooks:g}}}}),eg.module("pauseResume",["jQuery"],function(a){function b(a,b,c,d){this.el=b,this.opt=d,this.start=-1,this.elapsed=0,this.paused=!1,this.uuid=n++,this.easingNames=[],this.prop=c,this.type=a}function c(a,b,c){return function(b){return a=a&&"auto"!==a?parseFloat(a):0,a+b*c}}function d(a,c,d,e){var f;f=new b(a,c,d,e),c.__aniProps=c.__aniProps||[],0===c.__aniProps.length&&f.init(),c.__aniProps.push(f)}function e(a){var b=a.__aniProps.shift();b&&b.clearEasingFn(),a.__aniProps[0]&&a.__aniProps[0].init()}function f(a){return a.__aniProps&&0!==a.__aniProps.length?a.__aniProps[0].paused?"paused":"inprogress":"empty"}function g(a,b,c,d){return function(e){var f=a+b*e;return c(d(f))}}function h(a,b){var c=j(a[0],a[1]),d=i(b[0],b[1]);return function(a){return d(c(a))}}function i(a,b){return a=+a,b=+b,function(c){return a*(1-c)+b*c}}function j(a,b){return b=(b-=a=+a)||1/b,function(c){return(c-a)/b}}var k=a.fn.animate,l=a.fn.stop,m=a.fn.delay,n=1;b.prototype.init=function(){var b;this.start=a.now(),this.elapsed=0;for(var d in this.prop){var e,f,g=this.prop[d];"transform"!==d&&("string"!=typeof g||(e=g.search(/[+|-]=/))<0||(f="-"===g.charAt(e)?-1:1,b=a.css(this.el,d),this.prop[d]=g.replace(/([-|+])*([\d|\.])+/g,c(b,d,f)).replace(/[-|+]+=/g,"")))}},b.prototype.addEasingFn=function(a){this.easingNames.push(a)},b.prototype.clearEasingFn=function(){for(var b;b=this.easingNames.shift();)delete a.easing[b];this.easingNames=[]},a.fn.animate=function(b,c,e,f){return this.each(function(){var g=a.speed(c,e,f),h=g.old;g.complete=function(){var a=this.__aniProps.shift();a.clearEasingFn(),h&&"function"==typeof h&&h.call(this),this.__aniProps[0]&&this.__aniProps[0].init()},d("animate",this,b,g),k.call(a(this),b,g)})},a.fn.delay=function(b,c){var f,g=arguments[2];return c&&"fx"!==c?m.call(this,b,c):(f=parseInt(b,10),f=isNaN(f)?0:f,this.each(function(){g||d("delay",this,null,{duration:f});var c=this;m.call(a(this),b).queue(function(a){a(),e(c)})}))},a.fn.pause=function(){return this.each(function(){var b,c="fx";"inprogress"===f(this)&&(a.queue(this,c||"fx",[a.noop]),l.call(a(this)),(b=this.__aniProps[0])&&(b.elapsed+=a.now()-b.start,b.paused=!0))})},a.fn.resume=function(){return this.each(function(){var b,c,d="fx";if("paused"===f(this))for(a.queue(this,d||"fx",[]),c=0;b=this.__aniProps[c];){if(b.elapsed>0&&b.opt.easing){var e=b.elapsed/b.opt.duration,i=1-e,j=a.easing[b.opt.easing],l=j(e),m=h([l,1],[0,1]),n=b.opt.easing+"_"+b.uuid;a.easing[n]=g(e,i,m,j),b.opt.easing=n,b.addEasingFn(n)}b.paused=!1,b.opt.duration-=b.elapsed,(b.opt.duration>0||0===b.elapsed)&&(0===c&&b.init(),"delay"===b.type?a(this).delay(b.opt.duration,"fx",!0):k.call(a(this),b.prop,b.opt)),c++}})},a.fn.stop=function(a,b){var c=b;return l.apply(this,arguments),"string"!=typeof a&&(c=a),this.each(function(){var a;if("empty"!==f(this))if(c){for(;a=this.__aniProps.shift();)a.clearEasingFn();this.__aniProps=[]}else a=this.__aniProps.shift(),a&&a.clearEasingFn()})},jQuery.expr.filters.paused=function(a){return"paused"===f(a)}}),eg.module("persist",["jQuery",window,document],function(a,b,c){function d(a){if(a){var b="__tmp__"+p;try{return a.setItem(b,p),a.getItem(b)===p}catch(c){return!1}}}function e(a){s=s||a.originalEvent&&a.originalEvent.persisted,!s&&t?r.trigger("persist"):f()}function f(){j(null)}function g(){var c,d=v?v.getItem(b.location.href+p):m.state;if(null===d)return{};var e,f="string"==typeof d&&d.length>0&&"null"!==d;try{if(c=o.parse(d),e=!("object"!==a.type(c)||c instanceof Array),!f||!e)throw new Error}catch(g){h(),c={}}return c}function h(){console.warn("window.history or session/localStorage has no valid format data to be handled in persist.")}function i(a){var b=g()[a];return("null"===b||"undefined"==typeof b)&&(b=null),b}function j(a){if(v)a?v.setItem(b.location.href+p,o.stringify(a)):v.removeItem(b.location.href+p);else try{m.replaceState(null===a?null:o.stringify(a),c.title,b.location.href)}catch(d){console.warn(d.message)}a?r.attr(p,!0):r.attr(p,null)}function k(a,b){var c=g();c[a]=b,j(c)}var l=b.performance,m=b.history,n=function(){var a=b.navigator.userAgent,c=a?a.match(/Android\s([^\;]*)/i):null;return!(/iPhone|iPad/.test(a)||(c?parseFloat(c.pop())<4.4:!0))}(),o=b.JSON,p="___persist___",q="KEY"+p,r=a(b),s=r.attr(p)===!0,t=l&&l.navigation&&l.navigation.type===(l.navigation.TYPE_BACK_FORWARD||2),u="replaceState"in m&&"state"in m,v=function(){return d(b.sessionStorage)?b.sessionStorage:d(b.localStorage)?b.localStorage:void 0}();return u||v?o?(a.persist=function(a){var b,c;return"string"==typeof a?(b=a,c=2===arguments.length?arguments[1]:null):(b=q,c=1===arguments.length?a:null),c&&k(b,c),i(b)},a.persist.isNeeded=function(){return n},!t&&f(),a.event.special.persist={setup:function(){r.on("pageshow",e)},teardown:function(){r.off("pageshow",e)},trigger:function(a){a.state=i(q)}},{isBackForwardNavigated:t,onPageshow:e,reset:f,getState:g,setState:j,GLOBALKEY:q}):void console.warn("The JSON object is not supported in your browser.\r\nFor work around use polyfill which can be found at:\r\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#Polyfill"):void 0}),eg.module("visible",["jQuery",eg,document],function(a,b,c){var d={change:"change"};b.Visible=b.Class.extend(b.Component,{_events:function(){return d},construct:function(b,d,e){this._prefix=e||"",this.options={targetClass:"check_visible",expandSize:0},a.extend(this.options,d),this._wrapper=a(b)[0]||c,this._getAreaRect=this._wrapper.nodeType&&1===this._wrapper.nodeType?this._getWrapperRect:this._getWindowRect,this._targets=[],this._timer=null,this._supportElementsByClassName=function(){var a,b=c.createElement("div");return b.getElementsByClassName?(a=b.getElementsByClassName("dummy"),b.innerHTML="",1===a.length):!1}(),this.refresh()},refresh:function(){return this._supportElementsByClassName?(this._targets=this._wrapper.getElementsByClassName(this.options.targetClass),this.refresh=function(){return this}):this.refresh=function(){return this._targets=a(this._wrapper).find("."+this.options.targetClass).get(),this},this.refresh()},check:function(b){return"undefined"==typeof b&&(b=-1),clearTimeout(this._timer),0>b?this._check():this._timer=setTimeout(a.proxy(function(){this._check(),this._timer=null},this),b),this},_getWrapperRect:function(){return this._wrapper.getBoundingClientRect()},_getWindowRect:function(){return{top:0,left:0,bottom:c.documentElement.clientHeight||c.body.clientHeight,right:c.documentElement.clientWidth||c.body.clientWidth}},_reviseElements:function(b,c){return this._reviseElements=this._supportElementsByClassName?function(){return!0}:function(b,c){return a(b).hasClass(this.options.targetClass)?!0:(b.__VISIBLE__=null,this._targets.splice(c,1),!1)},this._reviseElements(b,c)},_check:function(){var b=parseInt(this.options.expandSize,10),c=[],e=[],f=this._getAreaRect();f=a.extend({},f),f.top-=b,f.left-=b,f.bottom+=b,f.right+=b;for(var g,h,i,j,k=this._targets.length-1;g=this._targets[k];k--)h=g.getBoundingClientRect(),(0!==h.width||0!==h.height)&&this._reviseElements(g,k)&&(j=!!g.__VISIBLE__,g.__VISIBLE__=i=!(h.bottomc[0]&&(a[0]=(a[0]-b[0])%(c[0]-b[0]+1)+b[0]),d[2]&&a[1]>c[1]&&(a[1]=(a[1]-b[1])%(c[1]-b[1]+1)+b[1]),d[3]&&a[0]c[0]||a[1]>c[1]},_isOutToOut:function(a,b){var c=this.options.min,d=this.options.max;return(a[0]d[0]||a[1]d[1])&&(b[0]d[0]||b[1]d[1])},_panstart:function(a){if(this._subOptions.interruptable||!this._status.prevented){this._setInterrupt(!0);var b=this._pos;this._grab(),this.trigger("hold",{pos:b.concat(),hammerEvent:a}),this._status.moveDistance=b.concat(),this._status.grabOutside=this._isOutside(b,this.options.min,this.options.max)}},_panmove:function(a){if(this._isInterrupting()&&this._status.moveDistance){var b,c,d,e=this._pos,g=this.options.min,h=this.options.max,i=this.options.bounce,j=this.options.margin,k=this._subOptions.direction,l=this._subOptions.scale,m=this._getDirection(a.angle),n=[j[0]+i[0],j[1]+i[1],j[2]+i[2],j[3]+i[3]],o=!1,p=this._status.curHammer.session.prevInput;if(p?(a.offsetX=a.deltaX-p.deltaX,a.offsetY=a.deltaY-p.deltaY):a.offsetX=a.offsetY=0,(k===f.DIRECTION_ALL||k&f.DIRECTION_HORIZONTAL&&m&f.DIRECTION_HORIZONTAL)&&(this._status.moveDistance[0]+=a.offsetX*l[0],o=!0),(k===f.DIRECTION_ALL||k&f.DIRECTION_VERTICAL&&m&f.DIRECTION_VERTICAL)&&(this._status.moveDistance[1]+=a.offsetY*l[1],o=!0),o&&(a.srcEvent.preventDefault(),a.srcEvent.stopPropagation()),a.preventSystemEvent=o,e[0]=this._status.moveDistance[0],e[1]=this._status.moveDistance[1],e=this._getCircularPos(e,g,h),this._status.grabOutside&&!this._isOutside(e,g,h)&&(this._status.grabOutside=!1),this._status.grabOutside)c=g[0]-n[3],d=h[0]+n[1],b=e[0],e[0]=b>d?d:c>b?c:b,c=g[1]-n[0],d=h[1]+n[2],b=e[1],e[1]=b>d?d:c>b?c:b;else{var q=this._initSlope();e[1]h[1]&&(b=(e[1]-h[1])/(n[2]*q),e[1]=h[1]+this._easing(b)*n[2]),e[0]h[0]&&(b=(e[0]-h[0])/(n[1]*q),e[0]=h[0]+this._easing(b)*n[1])}this._triggerChange(e,!0,a)}},_panend:function(a){var b=this._pos;if(this._isInterrupting()&&this._status.moveDistance){if(0===a.distance)this._setInterrupt(!1),this.trigger("release",{depaPos:b.concat(),destPos:b.concat(),hammerEvent:a||null});else{var c=this._subOptions.direction,d=this._subOptions.scale,e=Math.abs(a.velocityX),g=Math.abs(a.velocityY);!(c&f.DIRECTION_HORIZONTAL)&&(e=0),!(c&f.DIRECTION_VERTICAL)&&(g=0);var h=this._getNextOffsetPos([e*(a.deltaX<0?-1:1)*d[0],g*(a.deltaY<0?-1:1)*d[1]]),i=[b[0]+h[0],b[1]+h[1]];i=this._getPointOfIntersection(b,i),this.trigger("release",{depaPos:b.concat(),destPos:i,hammerEvent:a||null}),b[0]!==i[0]||b[1]!==i[1]?this._animateTo(i,null,a||null):this._setInterrupt(!1)}this._status.moveDistance=null}},_isInterrupting:function(){return this._subOptions.interruptable||this._status.prevented},_getDirection:function(a){var b=this._subOptions.thresholdAngle;return 0>b||b>90?f.DIRECTION_NONE:(a=Math.abs(a),a>b&&180-b>a?f.DIRECTION_VERTICAL:f.DIRECTION_HORIZONTAL)},_getNextOffsetPos:function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]),c=Math.abs(b/-this.options.deceleration);return[a[0]/2*c,a[1]/2*c]},_getDurationFromPos:function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]),c=Math.sqrt(b/this.options.deceleration*2);return 100>c?0:c},_getPointOfIntersection:function(a,b){var c,d,e=this.options.circular,f=this.options.bounce,g=this.options.min,h=this.options.max,i=[g[0]-f[3],g[1]-f[0]],j=[h[0]+f[1],h[1]+f[2]];return b=[b[0],b[1]],c=b[0]-a[0],d=b[1]-a[1],e[3]||(b[0]=Math.max(i[0],b[0])),e[1]||(b[0]=Math.min(j[0],b[0])),b[1]=c?a[1]+d/c*(b[0]-a[0]):b[1],e[0]||(b[1]=Math.max(i[1],b[1])),e[2]||(b[1]=Math.min(j[1],b[1])),b[0]=d?a[0]+c/d*(b[1]-a[1]):b[0],[Math.min(h[0],Math.max(g[0],b[0])),Math.min(h[1],Math.max(g[1],b[1]))]},_isCircular:function(a){var b=this.options.circular,c=this.options.min,d=this.options.max;return b[0]&&a[1]d[0]||b[2]&&a[1]>d[1]||b[3]&&a[0]b?b:this.options.maximumDuration,{depaPos:d.concat(),destPos:e.concat(),isBounce:this._isOutside(e,this.options.min,this.options.max),isCircular:this._isCircular(a),duration:b,distance:f,hammerEvent:c||null,done:this._animationEnd}},_restore:function(a,b){var c=this._pos,d=this.options.min,e=this.options.max;this._animate(this._prepareParam([Math.min(e[0],Math.max(d[0],c[0])),Math.min(e[1],Math.max(d[1],c[1]))],null,b),a)},_animationEnd:function(){this._status.animationParam=null,this._pos=this._getCircularPos([Math.round(this._pos[0]),Math.round(this._pos[1])]),this._setInterrupt(!1),this.trigger("animationEnd")},_animate:function(a,c){if(a.startTime=(new Date).getTime(),this._status.animationParam=a,a.duration){var d=this._status.animationParam,e=this;!function f(){return e._raf=null,e._frame(d)>=1?void c():void(e._raf=b.requestAnimationFrame(f))}()}else this._triggerChange(a.destPos,!1),c()},_animateTo:function(a,b,c){var d=this._prepareParam(a,b,c),e=this.trigger("animationStart",d);if(d.isCircular&&!e)throw new Error("You can't stop the 'animation' event when 'circular' is true.");if(e){var f=this,g=[],h=function(){var a=g.shift();a&&a.call(this)};(d.depaPos[0]!==d.destPos[0]||d.depaPos[1]!==d.destPos[1])&&g.push(function(){f._animate(d,h)}),this._isOutside(d.destPos,this.options.min,this.options.max)&&g.push(function(){f._restore(h,c)}),g.push(function(){f._animationEnd()}),h()}},_frame:function(a){for(var b=new Date-a.startTime,c=this._easing(b/a.duration),d=[a.depaPos[0],a.depaPos[1]],e=0;2>e;e++)d[e]!==a.destPos[e]&&(d[e]+=(a.destPos[e]-d[e])*c);return d=this._getCircularPos(d),this._triggerChange(d,!1),c},_reviseOptions:function(){var b,c=this;a.each(["bounce","margin","circular"],function(d,e){b=c.options[e],null!=b&&(c.options[e]=a.isArray(b)?2===b.length?b.concat(b):b.concat():/string|number|boolean/.test(typeof b)?[b,b,b,b]:null)})},_triggerChange:function(a,b,c){this._pos=a.concat(),this.trigger("change",{pos:a.concat(),holding:b,hammerEvent:c||null})},get:function(){return this._pos.concat()},setTo:function(a,b,c){this._grab();var d=this._pos.concat(),e=this.options.circular,f=this.options.min,g=this.options.max;return a===d[0]&&b===d[1]?this:(this._setInterrupt(!0),a!==d[0]&&(e[3]||(a=Math.max(f[0],a)),e[1]||(a=Math.min(g[0],a))),b!==d[1]&&(e[0]||(b=Math.max(f[1],b)),e[2]||(b=Math.min(g[1],b))),c?this._animateTo([a,b],c):(this._pos=this._getCircularPos([a,b]),this._triggerChange(this._pos,!1),this._setInterrupt(!1)),this)},setBy:function(a,b,c){return this.setTo(null!=a?this._pos[0]+a:this._pos[0],null!=b?this._pos[1]+b:this._pos[1],c)},_easing:function(a){return a>1?1:this.options.easing(a,a,0,1,1)},_initSlope:function(){var b,c=this.options.easing,d=!1;for(b in a.easing)if(a.easing[b]===c){d=!~b.indexOf("Out");break}return d?c(.9999,.9999,0,1,1)/.9999:c(1e-5,1e-5,0,1,1)/1e-5},_setInterrupt:function(a){!this._subOptions.interruptable&&(this._status.prevented=a)},destroy:function(){this.off();for(var a in this._hammers)this._hammers[a].inst.destroy(),this._hammers[a]=null}});return f._KEY="__MOVABLECOORD__",f.DIRECTION_NONE=1,f.DIRECTION_LEFT=2,f.DIRECTION_RIGHT=4,f.DIRECTION_UP=8,f.DIRECTION_DOWN=16,f.DIRECTION_HORIZONTAL=6,f.DIRECTION_VERTICAL=24,f.DIRECTION_ALL=f.DIRECTION_HORIZONTAL|f.DIRECTION_VERTICAL,{MovableCoord:b.MovableCoord}}),eg.module("flicking",["jQuery",eg,window,document,eg.MovableCoord],function(a,b,c,d,e){var f={beforeFlickStart:"beforeFlickStart",beforeRestore:"beforeRestore",flick:"flick",flickEnd:"flickEnd",restore:"restore"},g=d.documentElement.style;g="transform"in g||"webkitTransform"in g;var h=c.CSS&&c.CSS.supports&&c.CSS.supports("will-change","transform"),i=b.agent().os;i="android"===i.name&&/^2\./.test(i.version),b.Flicking=b.Class.extend(b.Component,{_events:function(){return f},construct:function(c,d,e){this.$wrapper=a(c);var f=this.$wrapper.children();if(!f.length)throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized."); + +this._setOptions(d),this._setConfig(f,e),!b._hasClickBug()&&(this._setPointerEvents=a.noop),this._build(),this._bindEvents(!0),this._applyPanelsCss(),this._arrangePanels(),this.options.hwAccelerable&&h&&this._setHint(),this._adjustContainerCss("end")},_setOptions:function(c){var d={previewPadding:[0,0],bounce:[10,10]};a.extend(this.options={hwAccelerable:b.isHWAccelerable(),prefix:"eg-flick",deceleration:6e-4,horizontal:!0,circular:!1,previewPadding:d.previewPadding,bounce:d.bounce,threshold:40,duration:100,panelEffect:a.easing.easeOutCubic,defaultIndex:0,inputType:["touch","mouse"]},c);var e=this;a.each(d,function(b,c){var d=e.options[b];a.isNumeric(d)?d=[d,d]:a.isArray(d)||(d=c),e.options[b]=d})},_setConfig:function(b,c){var d=this.options,f=d.previewPadding;b.eq(0).hasClass(d.prefix+"-container")&&(this.$container=b,b=b.children()),this._conf={panel:{$list:b,index:0,no:0,currIndex:0,currNo:0,size:0,count:0,origCount:0,changed:!1,animating:!1,minCount:f[0]+f[1]>0?5:3},touch:{holdPos:[0,0],destPos:[0,0],distance:0,direction:null,lastPos:0,holding:!1},customEvent:{flick:!0,restore:!1,restoreCall:!1},origPanelStyle:{wrapper:{className:this.$wrapper.attr("class")||null,style:this.$wrapper.attr("style")||null},list:b.map(function(b,c){return{className:a(c).attr("class")||null,style:a(c).attr("style")||null}})},inputEvent:!1,useLayerHack:d.hwAccelerable&&!h,dirData:[],indexToMove:0,eventPrefix:c||"",$dummyAnchor:null},a([["LEFT","RIGHT"],["UP","DOWN"]][+!d.horizontal]).each(a.proxy(function(a,b){this._conf.dirData.push(e["DIRECTION_"+b])},this))},_build:function(){var a,b=this._conf.panel,c=this.options,d=b.$list,f=c.previewPadding.concat(),g=c.prefix,h=c.horizontal,i=b.count=b.origCount=d.length,j=c.bounce;this._setPadding(f,!0);var k=this._getDataByDirection([b.size,"100%"]);a="position:relative;z-index:2000;width:100%;height:100%;"+(h?"":"top:0;"),this.$container?this.$container.attr("style",a):this.$container=d.wrapAll("
").parent(),d.addClass(g+"-panel").css({position:"absolute",width:k[0],height:k[1],boxSizing:"border-box",top:0,left:0}),this._addClonePanels()&&(i=b.count=(b.$list=this.$container.children()).length),this._mcInst=new e({min:[0,0],max:this._getDataByDirection([b.size*(i-1),0]),margin:0,circular:!1,easing:c.panelEffect,deceleration:c.deceleration,bounce:this._getDataByDirection([0,j[1],0,j[0]])}),this._setDefaultPanel(c.defaultIndex)},_setPadding:function(b,c){var d=this.options.horizontal,e=this._conf.panel,f=b[0]+b[1],g={};(f||!c)&&(g.padding=(d?"0 "+b.reverse().join("px 0 "):b.join("px 0 "))+"px"),c&&(g.overflow="hidden",g.boxSizing="border-box"),!a.isEmptyObject(g)&&this.$wrapper.css(g),e.size=this.$wrapper[d?"width":"height"]()},_addClonePanels:function(){var a,b=this._conf.panel,c=b.origCount,d=b.minCount-c,e=b.$list;if(this.options.circular&&c0&&e>=a&&this._movePanelPosition(a,!0),c=this._getBasePositionIndex(),this._movePanelPosition(c,!1),this._setPanelNo({no:a,currNo:a})):a>0&&e>=a&&(this._setPanelNo({index:a,no:a,currIndex:a,currNo:a}),b=[-(d.size*a),0],this._setTranslate(b),this._setMovableCoord("setTo",[Math.abs(b[0]),Math.abs(b[1])],!0,0))},_arrangePanels:function(a,b){var c,d=this._conf,e=d.panel,f=d.touch,g=d.dirData;this.options.circular&&(d.customEvent.flick=!1,a&&(b&&(f.direction=g[+!Boolean(b>0)]),this._arrangePanelPosition(f.direction,b)),c=this._getBasePositionIndex(),this._setPanelNo({index:c,currIndex:c}),d.customEvent.flick=!!this._setMovableCoord("setTo",[e.size*e.index,0],!0,0)),this._applyPanelsPos()},_applyPanelsPos:function(){this._conf.panel.$list.each(a.proxy(this._applyPanelsCss,this))},_setMoveStyle:function(){return g?function(a,c){a.css("transform",b.translate(c[0],c[1],this._conf.useLayerHack))}:function(a,b){a.css({left:b[0],top:b[1]})}}(),_applyPanelsCss:function(){var b=this._conf,c="__dummy_anchor";i?(b.$dummyAnchor=a("."+c),!b.$dummyAnchor.length&&this.$wrapper.append(b.$dummyAnchor=a("")),this._applyPanelsCss=function(b,c){var d=this._getDataByDirection([this._conf.panel.size*b+"px",0]);a(c).css({left:d[0],top:d[1]})}):this._applyPanelsCss=function(b,c){var d=this._getDataByDirection([g?100*b+"%":this._conf.panel.size*b+"px",0]);this._setMoveStyle(a(c),d)}},_adjustContainerCss:function(a,c){var d,e=this._conf,f=e.panel,g=this.options,h=g.horizontal,j=g.previewPadding[0],k=this.$container;i&&(c||(c=[-f.size*f.index,0]),"start"===a?(k=k[0].style,d=parseInt(k[h?"left":"top"],10),h?d&&(k.left=0):d!==j&&(k.top=j+"px"),this._setTranslate([-c[+!g.horizontal],0])):"end"===a&&(!h&&(c[0]+=j),c=this._getCoordsValue(c),k.css({left:c.x,top:c.y,transform:b.translate(0,0,e.useLayerHack)}),e.$dummyAnchor[0].focus()))},_setMovableCoord:function(a,b,c,d){return c&&(b=this._getDataByDirection(b)),this._mcInst[a](b[0],b[1],d)},_setHint:function(){var a="transform";this.$container.css("willChange",a),this._conf.panel.$list.css("willChange",a)},_getDataByDirection:function(a){return a=a.concat(),!this.options.horizontal&&a.reverse(),a},_arrangePanelPosition:function(a,b){var c=a===this._conf.dirData[0];this._movePanelPosition(Math.abs(b||1),c)},_getBasePositionIndex:function(){return Math.floor(this._conf.panel.count/2-.1)},_bindEvents:function(b){var c=this.options,d=this.$wrapper,f=this._mcInst;b?f.bind(d,{scale:this._getDataByDirection([-1,0]),direction:e["DIRECTION_"+(c.horizontal?"HORIZONTAL":"VERTICAL")],interruptable:!1,inputType:c.inputType}).on({hold:a.proxy(this._holdHandler,this),change:a.proxy(this._changeHandler,this),release:a.proxy(this._releaseHandler,this),animationStart:a.proxy(this._animationStartHandler,this),animationEnd:a.proxy(this._animationEndHandler,this)}):f.unbind(d).off(),this._conf.inputEvent=!!b},_holdHandler:function(a){var b=this._conf;b.touch.holdPos=a.pos,b.touch.holding=!0,b.panel.changed=!1,this._adjustContainerCss("start",a.pos)},_changeHandler:function(b){var c,d,e=this._conf,g=e.touch,h=+!this.options.horizontal,i=b.pos[h],j=g.holdPos[h],k=null;this._setPointerEvents(b),b.hammerEvent?(c=b.hammerEvent.direction,d=b.hammerEvent[this.options.horizontal?"deltaX":"deltaY"],~a.inArray(c,e.dirData)||(c=e.dirData[+(Math.abs(g.lastPos)<=d)]),g.lastPos=d):g.lastPos=null,e.customEvent.flick&&(k=this._triggerEvent(f.flick,{pos:b.pos,holding:b.holding,direction:c||g.direction,distance:i-(j||(g.holdPos[h]=i))})),(k||null===k)&&this._setTranslate([-i,0])},_releaseHandler:function(a){var b=this._conf.touch,c=a.destPos,d=+!this.options.horizontal,e=b.holdPos[d],f=this._conf.panel.size;b.distance=a.depaPos[d]-b.holdPos[d],b.direction=this._conf.dirData[+!Boolean(b.holdPos[d]=0?a.currIndex:a.index-b,d=a.currNo>=0?a.currNo:a.no-b;this._setPanelNo({index:c,no:d})},_setPanelNo:function(b){var c=this._conf.panel,d=c.origCount-1,e=this._getNumByDirection();a.isPlainObject(b)?a.each(b,function(a,b){c[a]=b}):(c.currIndex=c.index,c.currNo=c.no,c.index+=e,c.no+=e),c.no>d?c.no=0:c.no<0&&(c.no=d)},_setPointerEvents:function(a){var b,c=this.$container.css("pointerEvents");a&&a.holding&&a.hammerEvent&&a.hammerEvent.preventSystemEvent&&"none"!==c?b="none":a||"auto"===c||(b="auto"),b&&this.$container.css("pointerEvents",b)},_getCoordsValue:function(a){return a=this._getDataByDirection(a),{x:this._getUnitValue(a[0]),y:this._getUnitValue(a[1])}},_setTranslate:function(a){a=this._getCoordsValue(a),this._setMoveStyle(this.$container,[a.x,a.y])},_getUnitValue:function(a){var b=/(?:[a-z]{2,}|%)$/;return(parseInt(a,10)||0)+(String(a).match(b)||"px")},_isMovable:function(){var a,b,c=this.options,d=this._mcInst,e=Math.abs(this._conf.touch.distance)>=c.threshold;return!c.circular&&e&&(a=this._getDataByDirection(d.options.max)[0],b=this._getDataByDirection(d.get())[0],0>b||b>a)?!1:e},_triggerEvent:function(b,c){var d=this._conf,e=d.panel;return b===f.flickEnd&&(e.currNo=e.no,e.currIndex=e.index),this.trigger(d.eventPrefix+b,a.extend({eventType:b,index:e.currIndex,no:e.currNo,direction:d.touch.direction},c))},_getElement:function(b,c,d){var e,f,g,h=this._conf.panel,i=this.options.circular,j=h.currIndex,k=b===this._conf.dirData[0],l=null;return d?(e=h.count,f=j):(e=h.origCount,f=h.currNo),g=f,k?e-1>f?f++:i&&(f=0):f>0?f--:i&&(f=e-1),g!==f&&(l=c?a(h.$list[k?j+1:j-1]):f),l},_setValueToMove:function(a){var b=this._conf;b.touch.distance=this.options.threshold+1,b.touch.direction=b.dirData[+!a]},_getNumValue:function(a,b){return isNaN(a=parseInt(a,10))?b:a},getIndex:function(a){return this._conf.panel[a?"currIndex":"currNo"]},getElement:function(){var b=this._conf.panel;return a(b.$list[b.currIndex])},getNextElement:function(){return this._getElement(this._conf.dirData[0],!0)},getNextIndex:function(a){return this._getElement(this._conf.dirData[0],!1,a)},getAllElements:function(){return this._conf.panel.$list},getPrevElement:function(){return this._getElement(this._conf.dirData[1],!0)},getPrevIndex:function(a){return this._getElement(this._conf.dirData[1],!1,a)},getTotalCount:function(a){return this._conf.panel[a?"count":"origCount"]},isPlaying:function(){return this._conf.panel.animating},_movePanel:function(a,b){var c=this._conf,d=c.panel,e=this.options;return d.animating||c.touch.holding?void 0:(this._setValueToMove(a),(e.circular||null!=this[a?"getNextIndex":"getPrevIndex"]())&&this._movePanelByPhase("setBy",[d.size*(a?1:-1),0],b),this)},_movePanelByPhase:function(a,b,c){c=this._getNumValue(c,this.options.duration),this._setPhaseValue("start")!==!1&&(this._setMovableCoord(a,b,!0,c),!c&&this._setPhaseValue("end"))},next:function(a){return this._movePanel(!0,a)},prev:function(a){return this._movePanel(!1,a)},moveTo:function(a,b){var c,d,e=this._conf,f=e.panel,g=this.options.circular,h=f.index;return a=this._getNumValue(a,-1),0>a||a>=f.origCount||a===f.no||f.animating||e.touch.holding?this:(g?(c=a-f.no,d=c>0,Math.abs(c)>(d?f.count-(h+1):h)&&(c+=(d?-1:1)*f.count),this._setPanelNo({no:a})):(c=a-h,this._setPanelNo({index:a,no:a})),this._conf.indexToMove=c,this._setValueToMove(d),this._movePanelByPhase(g?"setBy":"setTo",[f.size*(g?c:a),0],b),this)},_checkPadding:function(){var b=this.options,c=b.previewPadding.concat(),d=this.$wrapper.css("padding").split(" ");b.horizontal&&d.reverse(),d=2===d.length?[d[0],d[0]]:[d[0],d[2]],d=a.map(d,function(a){return parseInt(a,10)}),(2===c.length&&c[0]!==d[0]||c[1]!==d[1])&&this._setPadding(c)},resize:function(){var a,b,c=this._conf,d=this.options,e=c.panel,f=d.horizontal;return~~d.previewPadding.join("")?(this._checkPadding(),a=e.size):f&&(a=e.size=this.$wrapper.width()),b=this._getDataByDirection([a*(e.count-1),0]),f&&this.$container.width(b[0]+a),e.$list.css(f?"width":"height",a),this._mcInst.options.max=b,this._setMovableCoord("setTo",[a*e.index,0],!0,0),i&&(this._applyPanelsPos(),this._adjustContainerCss("end")),this},restore:function(a){var b,c=this._conf,d=c.panel,e=this._getDataByDirection(this._mcInst.get());return e[0]!==d.currIndex*d.size?(c.customEvent.restoreCall=!0,a=this._getNumValue(a,this.options.duration),this._revertPanelNo(),b=this._getDataByDirection([d.size*d.index,0]),this._triggerBeforeRestore({depaPos:e,destPos:b}),this._setMovableCoord("setTo",b,!0,a),a||(this._adjustContainerCss("end"),this._triggerRestore())):d.changed&&(this._revertPanelNo(),c.touch.distance=c.indexToMove=0),this},_setInputEvent:function(a){var b=this._conf.inputEvent;return a^b&&this._bindEvents(a),this},enableInput:function(){return this._setInputEvent(!0)},disableInput:function(){return this._setInputEvent()},destroy:function(){var b=this._conf,c=b.origPanelStyle,d=c.wrapper,e=c.list;this.$wrapper.attr("class",d.className).attr("style",d.style),this.$container.children().unwrap().each(function(b,c){var d=a(c);return b>e.length-1?!!d.remove():void d.attr("class",e[b].className).attr("style",e[b].style)}),this.disableInput(),this.off();for(var f in this)this[f]=null}})}),eg.module("infiniteGrid",["jQuery",eg,window,document],function(a,b,c,d){var e={layoutComplete:"layoutComplete",append:"append",prepend:"prepend"};b.InfiniteGrid=b.Class.extend(b.Component,{_events:function(){return e},construct:function(b,e,f){this.options=a.extend({isEqualSize:!1,defaultGroupKey:null,count:30,threshold:300},e),this.$el=b instanceof a?b:a(b),this.el=this.$el.get(0),this.el.style.position="relative",this._prefix=f||"",this._isIos=/iPhone|iPad/.test(c.navigator.userAgent),this._isIE10lower=!!(d.documentMode&&d.documentMode<10),this._appendCols=this._prependCols=[],this.$view=a(c),this._reset(),this._refreshViewport(),this.el.children.length>0&&(this.items=this._itemize(a.makeArray(this.el.children),this.options.defaultGroupKey,!0),this.layout(this.items,!0)),this._onScroll=a.proxy(this._onScroll,this),this._onResize=a.proxy(this._onResize,this),this.$view.on("scroll",this._onScroll).on("resize",this._onResize)},_getScrollTop:function(){return d.body.scrollTop||d.documentElement.scrollTop},_onScroll:function(){if(!this.isProcessing()){var b=this._getScrollTop(),c=this._prevScrollTop;if(!(this._isIos&&0===b||c===b)){var d,f;if(b>c){if(a.isEmptyObject(this._bottomElement)&&(this._bottomElement=this.getBottomElement(),null==this._bottomElement))return;d=this._bottomElement,f=d.getBoundingClientRect(),f.top<=this._clientHeight+this.options.threshold&&this.trigger(this._prefix+e.append,{scrollTop:b})}else if(this.isRecycling()&&this._removedContent>0){if(a.isEmptyObject(this._topElement)&&(this._topElement=this.getTopElement(),null==this._topElement))return;if(d=this._topElement,f=d.getBoundingClientRect(),f.bottom>=-this.options.threshold){var g=this.fit();g>0&&(b-=g,this.$view.scrollTop(b)),this.trigger(this._prefix+e.prepend,{scrollTop:b})}}this._prevScrollTop=b}}},_onResize:function(){this._resizeTimeout&&clearTimeout(this._resizeTimeout);var a=this;this._resizeTimeout=setTimeout(function(){a._refreshViewport(),a.$el.innerWidth()!==a._containerWidth&&a.layout(a.items,!0),a._resizeTimeout=null},100)},_refreshViewport:function(){this._clientHeight=this.$view.height()},getStatus:function(){var b,c={};for(b in this)!this.hasOwnProperty(b)||!/^_/.test(b)||"function"==typeof this[b]||this[b]instanceof Element||(c[b]=this[b]);return{prop:c,options:a.extend({},this.options),items:a.map(this.items,function(b){var c=a.extend({},b);return delete c.el,c}),html:this.el.innerHTML,cssText:this.el.style.cssText}},setStatus:function(b){return b&&b.cssText&&b.html&&b.prop&&b.items?(this.el.style.cssText=b.cssText,this.el.innerHTML=b.html,a.extend(this,b.prop),this._topElement=this._bottomElement=null,this.items=a.map(this.el.children,function(a,c){return b.items[c].el=a,b.items[c]}),this):this},isProcessing:function(){return this._isProcessing},isRecycling:function(){return this.options.count>0&&this._isRecycling},getGroupKeys:function(){return a.map(this.items,function(a){return a.groupKey})},layout:function(b,c){return b=b||this.items,c="undefined"==typeof c?!0:c,this._isProcessing=!0,c&&(b=a.map(b,function(a){return a.isAppend=!0,a})),this._waitResource(b,c),this},_layoutItems:function(b){var c=this;a.each(a.map(b,function(a){return a.position=c._getItemLayoutPosition(a),a}),function(a,b){if(b.el){var c=b.el.style;c.left=b.position.x+"px",c.top=b.position.y+"px"}})},append:function(b,c){return this._isProcessing||0===b.length?void 0:(b=a(b),this._isProcessing=!0,this.isRecycling()||(this._isRecycling=this.items.length+b.length>=this.options.count),this._insert(b,c,!0),b.length)},prepend:function(b,c){return this.isRecycling()&&0!==this._removedContent&&!this._isProcessing&&0!==b.length?(b=a(b),this._isProcessing=!0,this._fit(),b.length>this._removedContent&&(b=b.slice(0,this._removedContent)),this._insert(b,c,!1),b.length):void 0},clear:function(){return this.el.innerHTML="",this.el.style.height="",this._reset(),this},_getTopItem:function(){var b=null,c=1/0;return a.each(this._getColItems(!1),function(a,d){d&&d.position.yc&&(c=d.position.y+d.size.height,b=d)}),b},getBottomElement:function(){var a=this._getBottomItem();return a&&a.el},_postLayout:function(a){if(this._isProcessing&&!(a.length<=0)){var b=this._getContainerSize();this.el.style.width=b.width+"px",this.el.style.height=b.height+"px",this._topElement=this.getTopElement(),this._bottomElement=this.getBottomElement();var c=0,d=a[0].isAppend;d||(this._isFitted=!1,this._fit(!0),c=a.length>=this.items.length?0:this.items[a.length].position.y,c>0&&(this._prevScrollTop=this._getScrollTop()+c,this.$view.scrollTop(this._prevScrollTop))),this._isProcessing=!1,this.trigger(this._prefix+e.layoutComplete,{target:a.concat(),isAppend:d,distance:c,croppedCount:this._removedContent})}},_insert:function(b,c,d){if(0!==b.length){var e=b.toArray(),f=a(e),g=-this._clientHeight+"px";a.each(e,function(a,b){b.style.position="absolute",b.style.top=g});var h=this._itemize(e,c,d);d?this.items=this.items.concat(h):(this.items=h.concat(this.items),h=h.reverse()),this.isRecycling()&&this._adjustRange(d,f),this.$el[d?"append":"prepend"](f),this.layout(h,!1)}},_waitResource:function(b,c){var d=this._checkImageLoaded(),e=this,f=function(){e._isProcessing&&((c||!e._appendCols.length)&&(a.each(b,function(a,b){b.el.style.position="absolute"}),e._measureColumns()),e._layoutItems(b),e._postLayout(b))};d.length>0?this._waitImageLoaded(d,f):setTimeout(function(){f&&f()},0)},_adjustRange:function(b,c){var d,e,f=this.items.length-this.options.count;0>=f||(e=this._getDelimiterIndex(b,f))<0||(b?(d=this.items.splice(0,e),this._isFitted=!1):d=this.items.splice(e,this.items.length-e),a.each(d,function(a,b){e=c.index(b.el),-1!==e?c.splice(e,1):b.el.parentNode.removeChild(b.el)}),this._removedContent+=b?d.length:-d.length)},_getDelimiterIndex:function(a,b){var c,d=this.items.length,e=0,f=a?b-1:d-b,g=f+(a?1:-1),h=this.items[f].groupKey;if(null!=h&&h===this.items[g].groupKey)if(a){for(c=f;c>0&&h===this.items[c].groupKey;c--);e=0===c?-1:c+1}else{for(c=f;d>c&&h===this.items[c].groupKey;c++);e=c===d?-1:c}else e=a?g:f;return e},_fit:function(b){if(this.options.count<=0)return this._fit=function(){return!1},this._isFitted=!0,!1;if(this._isFitted)return!1;var c=this._updateCols();a.each(this.items,function(a,d){d.position.y-=c,b&&(d.el.style.top=d.position.y+"px")}),this._updateCols(!0);var d=this._getContainerSize().height;return b&&(this.el.style.height=d+"px"),this._isFitted=!0,!0},fit:function(){var a=this._getTopItem(),b=a?a.position.y:0;return this._fit(!0),b},_reset:function(){this._isProcessing=!1,this._topElement=null,this._bottomElement=null,this._isFitted=!0,this._isRecycling=!1,this._removedContent=0,this._prevScrollTop=0,this._equalItemSize=0,this._resizeTimeout=null,this._resetCols(this._appendCols.length||0),this.items=[]},_checkImageLoaded:function(){return this.$el.find("img").filter(function(b,c){return c.nodeType&&-1!==a.inArray(c.nodeType,[1,9,11])?!c.complete:void 0}).toArray()},_waitImageLoaded:function(b,c){var d,e=b.length,f=function(b){e--,a(b.target).off("load error"),0>=e&&c&&c()},g=this;a.each(b,function(b,c){if(d=a(c),g._isIE10lower){var e=c.getAttribute("src");c.setAttribute("src",""),c.setAttribute("src",e)}d.on("load error",f)})},_measureColumns:function(){this.el.style.width=null,this._containerWidth=this.$el.innerWidth(),this._columnWidth=this._getColumnWidth()||this._containerWidth;var a=this._containerWidth/this._columnWidth,b=this._columnWidth-this._containerWidth%this._columnWidth;a=Math.max(Math[b&&1>=b?"round":"floor"](a),1),this._resetCols(a||0)},_resetCols:function(a){a="undefined"==typeof a?0:a;for(var b=[];a--;)b.push(0);this._appendCols=b.concat(),this._prependCols=b.concat()},_getContainerSize:function(){return{height:Math.max.apply(Math,this._appendCols),width:this._containerWidth}},_getColumnWidth:function(){var b=this.items[0]&&this.items[0].el,c=0;if(b){var d=a(b);c=d.innerWidth(),this.options.isEqualSize&&(this._equalItemSize={width:c,height:d.innerHeight()})}return c},_updateCols:function(a){for(var b,c=a?this._appendCols:this._prependCols,d=this._getColItems(a),e=this._isFitted||a?0:this._getMinY(d),f=0,g=c.length;g>f;f++)c[f]=(b=d[f])?b.position.y+(a?b.size.height:-e):0;return e},_getMinY:function(b){return Math.min.apply(Math,a.map(b,function(a){return a?a.position.y:0}))},_getColIdx:function(a){return parseInt(a.position.x/parseInt(this._columnWidth,10),10)},_getColItems:function(a){for(var b,c,d=this._appendCols.length,e=new Array(d),f=0,g=a?this.items.length-1:0;b=this.items[g];){if(c=this._getColIdx(b),!e[c]&&(e[c]=b,++f===d))return e;g+=a?-1:1}return e},_itemize:function(b,c,d){return a.map(b,function(a){return{el:a,position:{x:0,y:0},isAppend:"undefined"==typeof d?!0:d,groupKey:"undefined"==typeof c?null:c}})},_getItemLayoutPosition:function(b){if(b.el){var c=a(b.el);b.size=this._equalItemSize||{width:c.innerWidth(),height:c.innerHeight()};var d,e=b.isAppend,f=e?this._appendCols:this._prependCols,g=Math[e?"min":"max"].apply(Math,f);if(e)d=a.inArray(g,f);else for(var h=f.length;h-->=0;)if(f[h]===g){d=h;break}return f[d]=g+(e?b.size.height:-b.size.height),{x:this._columnWidth*d,y:e?g:g-b.size.height}}},destroy:function(){this.off(),this.$view.off("resize",this._onResize).off("scroll",this._onScroll),this._reset()}})}); \ No newline at end of file diff --git a/dist/pkgd/eg.pkgd.min.js b/dist/pkgd/eg.pkgd.min.js new file mode 100644 index 00000000..98d03b38 --- /dev/null +++ b/dist/pkgd/eg.pkgd.min.js @@ -0,0 +1,38 @@ +/** +* Copyright (c) 2015 NAVER corp. +* egjs projects are licensed under the MIT license +* https://naver.github.io/egjs/license.txt +* +* egjs JavaScript library +* http://naver.github.io/egjs +* +* @version 1.3.0 +* @SHA-1 13e6ef5 (1.3.0-rc) +* +* For custom build use egjs-cli +* https://github.com/naver/egjs-cli +*/ +/** +* All-in-one packaged file for ease use of 'egjs' with below dependencies. +* NOTE: This is not an official distribution file and is only for user convenience. +* +* bower_components/hammer.js/hammer.js +* src/module.js +* src/agent.js +* src/eg.js +* src/class.js +* src/component.js +* src/customEvent/rotate.js +* src/customEvent/scrollEnd.js +* src/hook/transform.js +* src/hook/cssPrefix.js +* src/hook/pauseResume.js +* src/plugin/persist.js +* src/visible.js +* src/movableCoord.js +* src/flicking.js +* src/infiniteGrid.js +*/ +!function(a,b,c,d){function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&la(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==oa?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;dc[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=ra(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=qa(j.x)>qa(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};(b.eventType===Ea||f.eventType===Ga)&&(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Ha&&(i>Da||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=qa(l.x)>qa(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;ce;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:pa(c/b),y:pa(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Ia:qa(a)>=qa(b)?0>a?Ja:Ka:0>b?La:Ma}function H(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Ra)+I(a[1],a[0],Ra)}function K(a,b){return H(b[0],b[1],Ra)/H(a[0],a[1],Ra)}function L(){this.evEl=Ta,this.evWin=Ua,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Xa,this.evWin=Ya,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=$a,this.evWin=_a,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Ga|Ha)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=bb,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches),d=this.targetIds;if(b&(Ea|Fa)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=s(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return o(a.target,i)}),b===Ea)for(e=0;e-1&&d.splice(a,1)};setTimeout(e,cb)}}function U(a){for(var b=a.srcEvent.clientX,c=a.srcEvent.clientY,d=0;d=f&&db>=g)return!0}return!1}function V(a,b){this.manager=a,this.set(b)}function W(a){if(p(a,jb))return jb;var b=p(a,kb),c=p(a,lb);return b&&c?jb:b||c?b?kb:lb:p(a,ib)?ib:hb}function X(){if(!fb)return!1;var b={},c=a.CSS&&a.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(d){b[d]=c?a.CSS.supports("touch-action",d):!0}),b}function Y(a){this.options=la({},this.defaults,a||{}),this.id=v(),this.manager=null,this.options.enable=l(this.options.enable,!0),this.state=nb,this.simultaneous={},this.requireFail=[]}function Z(a){return a&sb?"cancel":a&qb?"end":a&pb?"move":a&ob?"start":""}function $(a){return a==Ma?"down":a==La?"up":a==Ja?"left":a==Ka?"right":""}function _(a,b){var c=b.manager;return c?c.get(a):a}function aa(){Y.apply(this,arguments)}function ba(){aa.apply(this,arguments),this.pX=null,this.pY=null}function ca(){aa.apply(this,arguments)}function da(){Y.apply(this,arguments),this._timer=null,this._input=null}function ea(){aa.apply(this,arguments)}function fa(){aa.apply(this,arguments)}function ga(){Y.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function ha(a,b){return b=b||{},b.recognizers=l(b.recognizers,ha.defaults.preset),new ia(a,b)}function ia(a,b){this.options=la({},ha.defaults,b||{}),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=a,this.input=y(this),this.touchAction=new V(this,this.options.touchAction),ja(this,!0),g(this.options.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function ja(a,b){var c=a.element;if(c.style){var d;g(a.options.cssProps,function(e,f){d=u(c.style,f),b?(a.oldCssProps[d]=c.style[d],c.style[d]=e):c.style[d]=a.oldCssProps[d]||""}),b||(a.oldCssProps={})}}function ka(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var la,ma=["","webkit","Moz","MS","ms","o"],na=b.createElement("div"),oa="function",pa=Math.round,qa=Math.abs,ra=Date.now;la="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;ch&&(b.push(a),h=b.length-1):e&(Ga|Ha)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Za={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},$a="touchstart",_a="touchstart touchmove touchend touchcancel";i(N,x,{handler:function(a){var b=Za[a.type];if(b===Ea&&(this.started=!0),this.started){var c=O.call(this,a,b);b&(Ga|Ha)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}}});var ab={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},bb="touchstart touchmove touchend touchcancel";i(P,x,{handler:function(a){var b=ab[a.type],c=Q.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}});var cb=2500,db=25;i(R,x,{handler:function(a,b,c){var d=c.pointerType==za,e=c.pointerType==Ba;if(!(e&&c.sourceCapabilities&&c.sourceCapabilities.firesTouchEvents)){if(d)S.call(this,b,c);else if(e&&U.call(this,c))return;this.callback(a,b,c)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var eb=u(na.style,"touchAction"),fb=eb!==d,gb="compute",hb="auto",ib="manipulation",jb="none",kb="pan-x",lb="pan-y",mb=X();V.prototype={set:function(a){a==gb&&(a=this.compute()),fb&&this.manager.element.style&&mb[a]&&(this.manager.element.style[eb]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){k(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),W(a.join(" "))},preventDefaults:function(a){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=p(d,jb)&&!mb[jb],f=p(d,lb)&&!mb[lb],g=p(d,kb)&&!mb[kb];if(e){var h=1===a.pointers.length,i=a.distance<2,j=a.deltaTime<250;if(h&&i&&j)return}return g&&f?void 0:e||f&&c&Na||g&&c&Oa?this.preventSrc(b):void 0},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var nb=1,ob=2,pb=4,qb=8,rb=qb,sb=16,tb=32;Y.prototype={defaults:{},set:function(a){return la(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=_(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=_(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=_(a,this),-1===r(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=_(a,this);var b=r(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(b,a)}var c=this,d=this.state;qb>d&&b(c.options.event+Z(d)),b(c.options.event),a.additionalEvent&&b(a.additionalEvent),d>=qb&&b(c.options.event+Z(d))},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=tb)},canEmit:function(){for(var a=0;af?Ja:Ka,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Ia:0>g?La:Ma,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return aa.prototype.attrTest.call(this,a)&&(this.state&ob||!(this.state&ob)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=$(a.direction);b&&(a.additionalEvent=this.options.event+b),this._super.emit.call(this,a)}}),i(ca,aa,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&ob)},emit:function(a){if(1!==a.scale){var b=a.scale<1?"in":"out";a.additionalEvent=this.options.event+b}this._super.emit.call(this,a)}}),i(da,Y,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[hb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distanceb.time;if(this._input=a,!d||!c||a.eventType&(Ga|Ha)&&!f)this.reset();else if(a.eventType&Ea)this.reset(),this._timer=e(function(){this.state=rb,this.tryEmit()},b.time,this);else if(a.eventType&Ga)return rb;return tb},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===rb&&(a&&a.eventType&Ga?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=ra(),this.manager.emit(this.options.event,this._input)))}}),i(ea,aa,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&ob)}}),i(fa,aa,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Na|Oa,pointers:1},getTouchAction:function(){return ba.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Na|Oa)?b=a.overallVelocity:c&Na?b=a.overallVelocityX:c&Oa&&(b=a.overallVelocityY),this._super.attrTest.call(this,a)&&c&a.offsetDirection&&a.distance>this.options.threshold&&a.maxPointers==this.options.pointers&&qa(b)>this.options.velocity&&a.eventType&Ga},emit:function(a){var b=$(a.offsetDirection);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),i(ga,Y,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ib]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance2?a+1+"th":m[a]}function e(a,b){var c;for(c in b)a=a.replace(new RegExp("{{"+c+"}}","gi"),b[c]);return a}function f(a,b){for(var f,g,h,i,j,m,n,o,p=0,q=b.length,r=[],s=[],t=c.require;q>p;p++)g=b[p],h={index:d(p),name:g,componentName:a},i="string"==typeof b[p],j=void 0===b[p],m=i&&(f=k[b[p]]),n=i&&f&&!c[b[p]],o=n&&t&&t.specified&&t.specified(b[p]),i||j?o&&t.defined(b[p])?(g=t(b[p]),s.push(g)):!o||t.defined(b[p])?n&&t&&t.specified&&!t.specified(b[p])?(h.url=f.url,r.push(e(l[1],h))):!n||t?m&&c[b[p]]?(g=c[b[p]],s.push(g)):!i||f?void 0!==b[p]||r.push(e(l[4],h)):r.push(e(l[3],h)):(h.url=f.url,r.push(e(l[2],h))):(h.url=f.url,r.push(e(l[0],h))):s.push(g);return[s,r]}function g(a){return a.charAt(0).toUpperCase()+a.slice(1)}function h(a){var c,d,e,f=g(a);if(!(i[f]&&i[f].prototype&&i[f].prototype._events))return!1;if(j.fn[a])throw new Error("The name '"+f+"' has already been used and registered as plugin. Try with different one.");j.fn[a]=function(c){var d,e;return"string"==typeof c?(d=this.data(b+"-"+a),"instance"===c?d:(e=d[c].apply(d,Array.prototype.slice.call(arguments,1)),e===d?this:e)):((void 0===c||j.isPlainObject(c))&&this.data(b+"-"+a,new i[f](this,c||{},a+":")),this)},e={trigger:"trigger",add:"on",remove:"off"},c=i[f].prototype._events();for(var h in c){d=j.event.special[a+":"+c[h]]={},d.setup=function(){return!0};for(var k in e)d[k]=function(c){return function(d,e){return j(this).data(b+"-"+a)[c](d.type,"trigger"===c?e:d.handler),!1}}(e[k])}}var i;c[b]||(c[b]={}),i=c[b];var j=c[a],k={jQuery:{url:"http://jquery.com/"},Hammer:{url:"http://hammerjs.github.io/"}},l=["[egjs] The {{name}} library must be loaded before {{componentName}}.",'[egjs] For AMD environment (like RequireJS), "{{name}}" must be declared, which is required by {{componentName}}.',"[egjs] The {{index}} argument of {{componentName}} is missing.\r\nDownload {{name}} from [{{url}}].","[egjs] The {{name}} parameter of {{componentName}} is not valid.\r\nPlease check and try again.","[egjs] The {{index}} argument of {{componentName}} is undefined.\r\nPlease check and try again."],m=["1st","2nd","3rd"],n=function(a){(n=c.console&&c.console.warn?function(a){c.console.warn(a)}:function(){})(a)};i.module||(i.module=function(a,b,d){var e=f(a,b);e[1].length?n(e[1].join("\r\n")):(d.apply(c,e[0]),h(a))})}("jQuery","eg",window),eg.module("agent",[eg],function(a){function b(a){return j(a,n.defaultString.browser)}function c(a){var b,c;return a?(c=h(a).versionSearch||a,b=d(c,m)):void 0}function d(a,b){var c,d,e=n.defaultString.browser.version,f=new RegExp("("+a+")","i").exec(b);return f?(d=f.index,a=f[0],d>-1&&(c=d+a.length+1,e=b.substring(c).split(" ")[0].replace(/_/g,".").replace(/\;|\)/g,"")),e):e}function e(a){return j(a,n.defaultString.os)}function f(a){var b,c,d,e,f=m,h=g(a)||{},i=n.defaultString.os.version;return a?h.versionAlias?h.versionAlias:(c=h.versionSearch||a,d=new RegExp("("+c+")\\s([\\d_\\.]+|\\d_0)","i"),e=d.exec(f),e&&(b=d.exec(f)[2].replace(/_/g,".").replace(/\;|\)/g,"")),b||i):void 0}function g(a){return i(n.os,a)}function h(a){return i(n.browser,a)}function i(a,b){for(var c,d,e,f=0;e=a[f];f++)if(c=e.criteria,d=new RegExp(e.identity,"i").test(b),c?d&&k(m,c):d)return e}function j(a,b){for(var c,d=0;c=a[d];d++)if(k(m,c.criteria))return c.identity||b.name;return b.name}function k(a,b){return b&&b.test?!!b.test(a):a.indexOf(b)>-1}function l(){for(var a,b,c=m,e=n.webview,f=!1,g=0;b=e[g];g++)if(k(c,b.criteria)&&(a=d(b.browserVersionSearch,c),k(c,b.webviewToken)||k(a,b.webviewBrowserVersion))){f=!0;break}return f}var m,n={browser:[{criteria:"PhantomJS",identity:"PhantomJS"},{criteria:/Edge/,identity:"Edge",versionSearch:"Edge"},{criteria:/MSIE|Trident|Windows Phone/,identity:"IE",versionSearch:"IEMobile|MSIE|rv"},{criteria:/SAMSUNG|SamsungBrowser/,identity:"SBrowser",versionSearch:"Chrome"},{criteria:/Chrome|CriOS/,identity:"Chrome"},{criteria:/Android/,identity:"default"},{criteria:/iPhone|iPad/,identity:"Safari",versionSearch:"Version"},{criteria:"Apple",identity:"Safari",versionSearch:"Version"},{criteria:"Firefox",identity:"Firefox"}],os:[{criteria:/Windows Phone|Windows NT/,identity:"Window",versionSearch:"Windows Phone|Windows NT"},{criteria:"Windows 2000",identity:"Window",versionAlias:"5.0"},{criteria:/iPhone|iPad/,identity:"iOS",versionSearch:"iPhone OS|CPU OS"},{criteria:"Mac",versionSearch:"OS X",identity:"MAC"},{criteria:/Android/,identity:"Android"}],webview:[{criteria:/iPhone|iPad/,browserVersionSearch:"Version",webviewBrowserVersion:/-1/},{criteria:/iPhone|iPad|Android/,webviewToken:/NAVER|DAUM|; wv/}],defaultString:{browser:{version:"-1",name:"default"},os:{version:"-1",name:"unknown"}}};a.Agent={create:function(a){this.ua=m=a;var d={os:{},browser:{}};return d.browser.name=b(n.browser),d.browser.version=c(d.browser.name),d.os.name=e(n.os),d.os.version=f(d.os.name),d.browser.webview=l(),d.browser.name=d.browser.name.toLowerCase(),d.os.name=d.os.name.toLowerCase(),d}}}),eg.module("eg",["jQuery",eg,window,eg.Agent],function(a,b,c,d){function e(a,b,c,d){var e=a.hook[b];return e&&(d=e.apply(a,c)),a[b]=function(){var e=a.hook[b];return e?e.apply(a,c):d},d}var f=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,g=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(f&&!g){var h={},i=f;f=function(a){function b(){h[c]&&a()}var c=i(b);return h[c]=!0,c},g=function(a){delete h[a]}}else f&&g||(f=function(a){return c.setTimeout(a,16)},g=c.clearTimeout);b.VERSION="1.3.0",b.hook={},b.agent=function(){var a=d.create(c.navigator.userAgent);return e(this,"agent",[a],a)},b.translate=function(a,b,c){return c=c||!1,"translate"+(c?"3d(":"(")+a+","+b+(c?",0)":")")},b.isHWAccelerable=function(){var a,c=!1,f=b.agent(),g=f.os.version,h=f.browser.name,i=f.browser.version;return-1!==h.indexOf("chrome")?c=i>="25":/ie|edge|firefox|safari|inapp/.test(h)?c=!0:-1!==f.os.name.indexOf("android")&&(a=(d.ua.match(/\(.*\)/)||[null])[0],c=g>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||g>="4.0.3"&&/SHW-|SHV-|GT-|SCH-|SGH-|SPH-|LG-F160|LG-F100|LG-F180|LG-F200|EK-|IM-A|LG-F240|LG-F260/.test(a)&&!/SHW-M420|SHW-M200|GT-S7562/.test(a)),e(this,"isHWAccelerable",[c,f],c)},b.isTransitional=function(){var a=!1,c=b.agent(),d=c.browser.name;if(/chrome|firefox|sbrowser/.test(d))a=!0;else switch(c.os.name){case"ios":a=/safari|inapp/.test(d)&&parseInt(c.os.version,10)<6;break;case"window":a=/safari/.test(d)||/ie/.test(d)&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/safari/.test(d)}return e(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return e(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return f(a)},b.cancelAnimationFrame=function(a){g(a)},a.extend(a.easing,{easeOutCubic:function(a){return 1-Math.pow(1-a,3)}})}),eg.module("class",[eg],function(a){a.Class=function(a){var b=function(){"function"==typeof a.construct&&a.construct.apply(this,arguments)};return b.prototype=a,b.prototype.instance=function(){return this},b.prototype.constructor=b,b},a.Class.extend=function(a,b){var c=function(){a.apply(this,arguments),"function"==typeof b.construct&&b.construct.apply(this,arguments)},d=function(){};d.prototype=a.prototype;var e=new d;for(var f in b)e[f]=b[f];return e.constructor=c,c.prototype=e,c}}),eg.module("component",[eg],function(a){a.Component=a.Class({construct:function(){this.eventHandler={},this.options={}},option:function(a,b){if(arguments.length>=2)return this.options[a]=b,this;if("string"==typeof a)return this.options[a];if(0===arguments.length)return this.options;for(var c in a)this.options[c]=a[c];return this},trigger:function(a,b){b=b||{};var c=this.eventHandler[a]||[],d=c.length>0;if(!d)return!0;c=c.concat(),b.eventType=a;var e,f,g,h=!1,i=[b];for(b.stop=function(){h=!0},(f=arguments.length)>2&&(i=i.concat(Array.prototype.slice.call(arguments,2,f))),e=0;g=c[e];e++)g.apply(this,i);return!h},hasOn:function(a){return!!this.eventHandler[a]},on:function(a,b){if("object"==typeof a&&"undefined"==typeof b){var c,d=a;for(c in d)this.on(c,d[c]);return this}if("string"==typeof a&&"function"==typeof b){var e=this.eventHandler[a];"undefined"==typeof e&&(e=this.eventHandler[a]=[]),e.push(b)}return this},off:function(a,b){if(0===arguments.length)return this.eventHandler={},this;if("undefined"==typeof b){if("string"==typeof a)return this.eventHandler[a]=void 0,this;var c=a;for(var d in c)this.off(d,c[d]);return this}var e=this.eventHandler[a];if(e){var f,g;for(f=0,g;g=e[f];f++)if(g===b){e=e.splice(f,1);break}}return this}})}),eg.module("rotate",["jQuery",eg,window,document],function(a,b,c,d){function e(){var a,b,e,f=m();return"resize"===f?(a=d.documentElement.clientWidth,e=-1===h?aa?!0:a===h?i:!1):(b=c.orientation,0===b||180===b?e=!0:(90===b||-90===b)&&(e=!1)),e}function f(){var b=e();l&&i!==b&&(i=b,h=d.documentElement.clientWidth,a(c).trigger("rotate",{isVertical:i}))}function g(a){var b,e,i=m();if("resize"===i)c.setTimeout(function(){f()},0);else{if(b=300,"android"===k.os.name&&(e=d.documentElement.clientWidth,"orientationchange"===a.type&&e===h))return c.setTimeout(function(){g(a)},500),!1;c.clearTimeout(j),j=c.setTimeout(function(){f()},b)}}var h=-1,i=null,j=null,k=b.agent(),l=/android|ios/.test(k.os.name);if(!l)return void(b.isPortrait=function(){});var m=function(){var a;return a="android"===k.os.name&&"2.1"===k.os.version?"resize":"onorientationchange"in c?"orientationchange":"resize",m=function(){return a},a};return a.event.special.rotate={setup:function(){i=e(),h=d.documentElement.clientWidth,a(c).on(m(),g)},teardown:function(){a(c).off(m(),g)},trigger:function(a){a.isVertical=i}},b.isPortrait=e,{orientationChange:m,isVertical:e,triggerRotate:f,handler:g}}),eg.module("scrollEnd",["jQuery",eg,window],function(a,b,c){function d(){var a=n,c=b.agent(),d=c.os,e=parseInt(d.version,10),f=c.browser;return f.webview||("ios"===d.name&&7>=e?a=p:"android"===d.name&&"default"===f.name&&2.3>=e&&(a=p)),a}function e(){a(c).on("scroll",g),a(c).on("orientationchange",f)}function f(){l=!0}function g(){if(l)return void(l=!1);switch(r){case p:h();break;case n:i()}}function h(){a(c).trigger("scrollend",{top:c.pageYOffset,left:c.pageXOffset})}function i(){clearTimeout(k),k=setTimeout(function(){return l?void(l=!1):void h()},q)}function j(){a(c).off("scroll",g),a(c).off("orientationchange",f)}var k,l=!1,m=3,n=2,o=1,p=0,q=250,r=d();return a.event.special.scrollend={setup:function(){e()},teardown:function(){j()}},{getDeviceType:d,CHROME:m,TIMERBASE:n,TOUCHBASE:o,SCROLLBASE:p}}),eg.module("transform",["jQuery",window],function(a){function b(a,b){var c=a,d=a.match(/((-|\+)*[0-9]+)%/);return d&&d.length>=1?c=b*(parseFloat(d[1])/100)+"px":-1===a.indexOf("px")&&(c=a+"px"),c}function c(a,c,d){for(var e,f="",g=a.split(")"),h=0,i=g.length-1;i>h;h++){var j=g[h];if((e=j.match(/(translate([XYZ]|3d)?|rotate)\(([^)]*)/))&&e.length>1)if("rotate"===e[1])-1===e[3].indexOf("deg")&&(j=e[1]+"("+e[3]+"deg");else switch(e[2]){case"X":j=e[1]+"("+b(e[3],c);break;case"Y":j=e[1]+"("+b(e[3],d);break;case"Z":break;default:for(var k=e[3].split(","),l=[c,d,100],m=0,n=k.length;n>m;m++)k[m]=b(k[m],l[m]);j=e[1]+"("+k.join(",")}j=" "+j+")",f+=j}return f=f.replace("%","").replace("+=","")}function d(a){var b=a.match(/((-|\+)*[\d|\.]+)(px|deg|rad)*/);return b&&b.length>=1?{num:parseFloat(b[1]), +unit:b[3]}:void 0}function e(b){for(var c=b.split(")"),e=[],f=0,g=c.length-1;g>f;f++){var h=i(c[f]);h[1]=a.map(h[1],d),e.push(h)}return function(b){var c="",d=0;return a.each(e,function(f){d=e[f][0].indexOf("scale")>=0?1:0;var g=a.map(e[f][1],function(a){var c=a.num;return 1===d&&(c-=1),d+c*b+(a.unit||"")}).join(",");c+=e[f][0]+"("+g+") "}),c}}function f(b,d,f){var h,i,l,m=f.indexOf("+=")>=0;return f=c(f,parseFloat(a.css(b,"width"))||0,parseFloat(a.css(b,"height"))||0),m?(h=d&&"none"!==d?d:"matrix(1, 0, 0, 1, 0, 0)",i=e(f)):(h=j(d),l=j("none"),h[1].lengthl[1].length&&(l=k(l)),i=e(f)),function(a){var b=[],c="";if(m)return h+i(a);if(1===a)c=g(l);else{for(var d,e,f=0,j=h[1].length;j>f;f++)d=parseFloat(h[1][f]),e=parseFloat(l[1][f]),b.push(d+(e-d)*a);c=g([h[0],b])}return c+i(a)}}function g(b){var c,d=[];if(a.isArray(b))return c=b[0],c+"("+b[1].join(h(c)+",")+h(c)+")";for(c in b)d.push(c);return a.map(d,function(a){return a+"("+b[a]+h(a)+")"}).join(" ")}function h(a){return a.indexOf("translate")>=0?"px":a.indexOf("rotate")>=0?"deg":""}function i(b){var c,d,e=b.match(/(\b\w+?)\((\s*[^\)]+)/),f=["",""];return e&&e.length>2&&(c=e[1],d=e[2].split(","),d=a.map(d,function(b){return a.trim(b)}),f=[a.trim(c),d]),f}function j(a){var b;return a&&"none"!==a?(a=a.replace(/\s/g,""),b=a.match(/(matrix)(3d)*\((.*)\)/),[b[1]+(b[2]||""),b[3].split(",")]):["matrix",["1","0","0","1","0","0"]]}function k(a){var b=a[0],c=a[1];return"matrix3d"===b?a:[b+"3d",[c[0],c[1],"0","0",c[2],c[3],"0","0","0","0","1","0",c[4],c[5],"0","1"]]}return a.fx.step.transform=function(b){b.rateFn=b.rateFn||f(b.elem,b.start,b.end),a.style(b.elem,"transform",b.rateFn(b.pos))},{toMatrix:j,toMatrix3d:k}}),eg.module("cssPrefix",["jQuery",document],function(a,b){if(!a.cssHooks)throw new Error("jQuery 1.4.3+ is needed for this plugin to work");var c=(a.fn.jquery.match(/^\d\.\d+/)||[])[0];if(c&&!(+c.replace(/\D/,"")>=18)){var d=["Webkit","Moz","O","ms"],e=["transitionProperty","transitionDuration","transition","transform","transitionTimingFunction"],f=function(){for(var a=(b.head||b.getElementsByTagName("head")[0]).style,c=0,e=d.length;e>c;c++)if(d[c]+"Transition"in a)return d[c]}();if(f){for(var g=function(b){var c=b.charAt(0).toUpperCase()+b.slice(1),d=f+c,e="ms"===f?"Ms"+c:d;a.cssHooks[c]=a.cssHooks[f.toLowerCase()+c]=a.cssHooks[b]={get:function(b,c){return c?a.css(b,e):b.style[d]},set:function(a,b){a.style[d]=b}}},h=0,i=e.length;i>h;h++)g(e[h]);return{vendorPrefix:f,setCssHooks:g}}}}),eg.module("pauseResume",["jQuery"],function(a){function b(a,b,c,d){this.el=b,this.opt=d,this.start=-1,this.elapsed=0,this.paused=!1,this.uuid=n++,this.easingNames=[],this.prop=c,this.type=a}function c(a,b,c){return function(b){return a=a&&"auto"!==a?parseFloat(a):0,a+b*c}}function d(a,c,d,e){var f;f=new b(a,c,d,e),c.__aniProps=c.__aniProps||[],0===c.__aniProps.length&&f.init(),c.__aniProps.push(f)}function e(a){var b=a.__aniProps.shift();b&&b.clearEasingFn(),a.__aniProps[0]&&a.__aniProps[0].init()}function f(a){return a.__aniProps&&0!==a.__aniProps.length?a.__aniProps[0].paused?"paused":"inprogress":"empty"}function g(a,b,c,d){return function(e){var f=a+b*e;return c(d(f))}}function h(a,b){var c=j(a[0],a[1]),d=i(b[0],b[1]);return function(a){return d(c(a))}}function i(a,b){return a=+a,b=+b,function(c){return a*(1-c)+b*c}}function j(a,b){return b=(b-=a=+a)||1/b,function(c){return(c-a)/b}}var k=a.fn.animate,l=a.fn.stop,m=a.fn.delay,n=1;b.prototype.init=function(){var b;this.start=a.now(),this.elapsed=0;for(var d in this.prop){var e,f,g=this.prop[d];"transform"!==d&&("string"!=typeof g||(e=g.search(/[+|-]=/))<0||(f="-"===g.charAt(e)?-1:1,b=a.css(this.el,d),this.prop[d]=g.replace(/([-|+])*([\d|\.])+/g,c(b,d,f)).replace(/[-|+]+=/g,"")))}},b.prototype.addEasingFn=function(a){this.easingNames.push(a)},b.prototype.clearEasingFn=function(){for(var b;b=this.easingNames.shift();)delete a.easing[b];this.easingNames=[]},a.fn.animate=function(b,c,e,f){return this.each(function(){var g=a.speed(c,e,f),h=g.old;g.complete=function(){var a=this.__aniProps.shift();a.clearEasingFn(),h&&"function"==typeof h&&h.call(this),this.__aniProps[0]&&this.__aniProps[0].init()},d("animate",this,b,g),k.call(a(this),b,g)})},a.fn.delay=function(b,c){var f,g=arguments[2];return c&&"fx"!==c?m.call(this,b,c):(f=parseInt(b,10),f=isNaN(f)?0:f,this.each(function(){g||d("delay",this,null,{duration:f});var c=this;m.call(a(this),b).queue(function(a){a(),e(c)})}))},a.fn.pause=function(){return this.each(function(){var b,c="fx";"inprogress"===f(this)&&(a.queue(this,c||"fx",[a.noop]),l.call(a(this)),(b=this.__aniProps[0])&&(b.elapsed+=a.now()-b.start,b.paused=!0))})},a.fn.resume=function(){return this.each(function(){var b,c,d="fx";if("paused"===f(this))for(a.queue(this,d||"fx",[]),c=0;b=this.__aniProps[c];){if(b.elapsed>0&&b.opt.easing){var e=b.elapsed/b.opt.duration,i=1-e,j=a.easing[b.opt.easing],l=j(e),m=h([l,1],[0,1]),n=b.opt.easing+"_"+b.uuid;a.easing[n]=g(e,i,m,j),b.opt.easing=n,b.addEasingFn(n)}b.paused=!1,b.opt.duration-=b.elapsed,(b.opt.duration>0||0===b.elapsed)&&(0===c&&b.init(),"delay"===b.type?a(this).delay(b.opt.duration,"fx",!0):k.call(a(this),b.prop,b.opt)),c++}})},a.fn.stop=function(a,b){var c=b;return l.apply(this,arguments),"string"!=typeof a&&(c=a),this.each(function(){var a;if("empty"!==f(this))if(c){for(;a=this.__aniProps.shift();)a.clearEasingFn();this.__aniProps=[]}else a=this.__aniProps.shift(),a&&a.clearEasingFn()})},jQuery.expr.filters.paused=function(a){return"paused"===f(a)}}),eg.module("persist",["jQuery",window,document],function(a,b,c){function d(a){if(a){var b="__tmp__"+p;try{return a.setItem(b,p),a.getItem(b)===p}catch(c){return!1}}}function e(a){s=s||a.originalEvent&&a.originalEvent.persisted,!s&&t?r.trigger("persist"):f()}function f(){j(null)}function g(){var c,d=v?v.getItem(b.location.href+p):m.state;if(null===d)return{};var e,f="string"==typeof d&&d.length>0&&"null"!==d;try{if(c=o.parse(d),e=!("object"!==a.type(c)||c instanceof Array),!f||!e)throw new Error}catch(g){h(),c={}}return c}function h(){console.warn("window.history or session/localStorage has no valid format data to be handled in persist.")}function i(a){var b=g()[a];return("null"===b||"undefined"==typeof b)&&(b=null),b}function j(a){if(v)a?v.setItem(b.location.href+p,o.stringify(a)):v.removeItem(b.location.href+p);else try{m.replaceState(null===a?null:o.stringify(a),c.title,b.location.href)}catch(d){console.warn(d.message)}a?r.attr(p,!0):r.attr(p,null)}function k(a,b){var c=g();c[a]=b,j(c)}var l=b.performance,m=b.history,n=function(){var a=b.navigator.userAgent,c=a?a.match(/Android\s([^\;]*)/i):null;return!(/iPhone|iPad/.test(a)||(c?parseFloat(c.pop())<4.4:!0))}(),o=b.JSON,p="___persist___",q="KEY"+p,r=a(b),s=r.attr(p)===!0,t=l&&l.navigation&&l.navigation.type===(l.navigation.TYPE_BACK_FORWARD||2),u="replaceState"in m&&"state"in m,v=function(){return d(b.sessionStorage)?b.sessionStorage:d(b.localStorage)?b.localStorage:void 0}();return u||v?o?(a.persist=function(a){var b,c;return"string"==typeof a?(b=a,c=2===arguments.length?arguments[1]:null):(b=q,c=1===arguments.length?a:null),c&&k(b,c),i(b)},a.persist.isNeeded=function(){return n},!t&&f(),a.event.special.persist={setup:function(){r.on("pageshow",e)},teardown:function(){r.off("pageshow",e)},trigger:function(a){a.state=i(q)}},{isBackForwardNavigated:t,onPageshow:e,reset:f,getState:g,setState:j,GLOBALKEY:q}):void console.warn("The JSON object is not supported in your browser.\r\nFor work around use polyfill which can be found at:\r\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#Polyfill"):void 0}),eg.module("visible",["jQuery",eg,document],function(a,b,c){var d={change:"change"};b.Visible=b.Class.extend(b.Component,{_events:function(){return d},construct:function(b,d,e){this._prefix=e||"",this.options={targetClass:"check_visible",expandSize:0},a.extend(this.options,d),this._wrapper=a(b)[0]||c,this._getAreaRect=this._wrapper.nodeType&&1===this._wrapper.nodeType?this._getWrapperRect:this._getWindowRect,this._targets=[],this._timer=null,this._supportElementsByClassName=function(){var a,b=c.createElement("div");return b.getElementsByClassName?(a=b.getElementsByClassName("dummy"),b.innerHTML="",1===a.length):!1}(),this.refresh()},refresh:function(){return this._supportElementsByClassName?(this._targets=this._wrapper.getElementsByClassName(this.options.targetClass),this.refresh=function(){return this}):this.refresh=function(){return this._targets=a(this._wrapper).find("."+this.options.targetClass).get(),this},this.refresh()},check:function(b){return"undefined"==typeof b&&(b=-1),clearTimeout(this._timer),0>b?this._check():this._timer=setTimeout(a.proxy(function(){this._check(),this._timer=null},this),b),this},_getWrapperRect:function(){return this._wrapper.getBoundingClientRect()},_getWindowRect:function(){return{top:0,left:0,bottom:c.documentElement.clientHeight||c.body.clientHeight,right:c.documentElement.clientWidth||c.body.clientWidth}},_reviseElements:function(b,c){return this._reviseElements=this._supportElementsByClassName?function(){return!0}:function(b,c){return a(b).hasClass(this.options.targetClass)?!0:(b.__VISIBLE__=null,this._targets.splice(c,1),!1)},this._reviseElements(b,c)},_check:function(){var b=parseInt(this.options.expandSize,10),c=[],e=[],f=this._getAreaRect();f=a.extend({},f),f.top-=b,f.left-=b,f.bottom+=b,f.right+=b;for(var g,h,i,j,k=this._targets.length-1;g=this._targets[k];k--)h=g.getBoundingClientRect(),(0!==h.width||0!==h.height)&&this._reviseElements(g,k)&&(j=!!g.__VISIBLE__,g.__VISIBLE__=i=!(h.bottomc[0]&&(a[0]=(a[0]-b[0])%(c[0]-b[0]+1)+b[0]),d[2]&&a[1]>c[1]&&(a[1]=(a[1]-b[1])%(c[1]-b[1]+1)+b[1]),d[3]&&a[0]c[0]||a[1]>c[1]},_isOutToOut:function(a,b){var c=this.options.min,d=this.options.max;return(a[0]d[0]||a[1]d[1])&&(b[0]d[0]||b[1]d[1])},_panstart:function(a){if(this._subOptions.interruptable||!this._status.prevented){this._setInterrupt(!0);var b=this._pos;this._grab(),this.trigger("hold",{pos:b.concat(),hammerEvent:a}),this._status.moveDistance=b.concat(),this._status.grabOutside=this._isOutside(b,this.options.min,this.options.max)}},_panmove:function(a){if(this._isInterrupting()&&this._status.moveDistance){var b,c,d,e=this._pos,g=this.options.min,h=this.options.max,i=this.options.bounce,j=this.options.margin,k=this._subOptions.direction,l=this._subOptions.scale,m=this._getDirection(a.angle),n=[j[0]+i[0],j[1]+i[1],j[2]+i[2],j[3]+i[3]],o=!1,p=this._status.curHammer.session.prevInput;if(p?(a.offsetX=a.deltaX-p.deltaX,a.offsetY=a.deltaY-p.deltaY):a.offsetX=a.offsetY=0,(k===f.DIRECTION_ALL||k&f.DIRECTION_HORIZONTAL&&m&f.DIRECTION_HORIZONTAL)&&(this._status.moveDistance[0]+=a.offsetX*l[0],o=!0),(k===f.DIRECTION_ALL||k&f.DIRECTION_VERTICAL&&m&f.DIRECTION_VERTICAL)&&(this._status.moveDistance[1]+=a.offsetY*l[1],o=!0),o&&(a.srcEvent.preventDefault(),a.srcEvent.stopPropagation()),a.preventSystemEvent=o,e[0]=this._status.moveDistance[0],e[1]=this._status.moveDistance[1],e=this._getCircularPos(e,g,h),this._status.grabOutside&&!this._isOutside(e,g,h)&&(this._status.grabOutside=!1),this._status.grabOutside)c=g[0]-n[3],d=h[0]+n[1],b=e[0],e[0]=b>d?d:c>b?c:b,c=g[1]-n[0],d=h[1]+n[2],b=e[1],e[1]=b>d?d:c>b?c:b;else{var q=this._initSlope();e[1]h[1]&&(b=(e[1]-h[1])/(n[2]*q),e[1]=h[1]+this._easing(b)*n[2]),e[0]h[0]&&(b=(e[0]-h[0])/(n[1]*q),e[0]=h[0]+this._easing(b)*n[1])}this._triggerChange(e,!0,a)}},_panend:function(a){var b=this._pos;if(this._isInterrupting()&&this._status.moveDistance){if(0===a.distance)this._setInterrupt(!1),this.trigger("release",{depaPos:b.concat(),destPos:b.concat(),hammerEvent:a||null});else{var c=this._subOptions.direction,d=this._subOptions.scale,e=Math.abs(a.velocityX),g=Math.abs(a.velocityY);!(c&f.DIRECTION_HORIZONTAL)&&(e=0),!(c&f.DIRECTION_VERTICAL)&&(g=0);var h=this._getNextOffsetPos([e*(a.deltaX<0?-1:1)*d[0],g*(a.deltaY<0?-1:1)*d[1]]),i=[b[0]+h[0],b[1]+h[1]];i=this._getPointOfIntersection(b,i),this.trigger("release",{depaPos:b.concat(),destPos:i,hammerEvent:a||null}),b[0]!==i[0]||b[1]!==i[1]?this._animateTo(i,null,a||null):this._setInterrupt(!1)}this._status.moveDistance=null}},_isInterrupting:function(){return this._subOptions.interruptable||this._status.prevented},_getDirection:function(a){var b=this._subOptions.thresholdAngle;return 0>b||b>90?f.DIRECTION_NONE:(a=Math.abs(a),a>b&&180-b>a?f.DIRECTION_VERTICAL:f.DIRECTION_HORIZONTAL)},_getNextOffsetPos:function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]),c=Math.abs(b/-this.options.deceleration);return[a[0]/2*c,a[1]/2*c]},_getDurationFromPos:function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]),c=Math.sqrt(b/this.options.deceleration*2);return 100>c?0:c},_getPointOfIntersection:function(a,b){var c,d,e=this.options.circular,f=this.options.bounce,g=this.options.min,h=this.options.max,i=[g[0]-f[3],g[1]-f[0]],j=[h[0]+f[1],h[1]+f[2]];return b=[b[0],b[1]],c=b[0]-a[0],d=b[1]-a[1],e[3]||(b[0]=Math.max(i[0],b[0])),e[1]||(b[0]=Math.min(j[0],b[0])),b[1]=c?a[1]+d/c*(b[0]-a[0]):b[1],e[0]||(b[1]=Math.max(i[1],b[1])),e[2]||(b[1]=Math.min(j[1],b[1])),b[0]=d?a[0]+c/d*(b[1]-a[1]):b[0],[Math.min(h[0],Math.max(g[0],b[0])),Math.min(h[1],Math.max(g[1],b[1]))]},_isCircular:function(a){var b=this.options.circular,c=this.options.min,d=this.options.max;return b[0]&&a[1]d[0]||b[2]&&a[1]>d[1]||b[3]&&a[0]b?b:this.options.maximumDuration,{depaPos:d.concat(),destPos:e.concat(),isBounce:this._isOutside(e,this.options.min,this.options.max),isCircular:this._isCircular(a),duration:b,distance:f,hammerEvent:c||null,done:this._animationEnd}},_restore:function(a,b){var c=this._pos,d=this.options.min,e=this.options.max;this._animate(this._prepareParam([Math.min(e[0],Math.max(d[0],c[0])),Math.min(e[1],Math.max(d[1],c[1]))],null,b),a)},_animationEnd:function(){this._status.animationParam=null,this._pos=this._getCircularPos([Math.round(this._pos[0]),Math.round(this._pos[1])]),this._setInterrupt(!1),this.trigger("animationEnd")},_animate:function(a,c){if(a.startTime=(new Date).getTime(),this._status.animationParam=a,a.duration){var d=this._status.animationParam,e=this;!function f(){return e._raf=null,e._frame(d)>=1?void c():void(e._raf=b.requestAnimationFrame(f))}()}else this._triggerChange(a.destPos,!1),c()},_animateTo:function(a,b,c){var d=this._prepareParam(a,b,c),e=this.trigger("animationStart",d);if(d.isCircular&&!e)throw new Error("You can't stop the 'animation' event when 'circular' is true.");if(e){var f=this,g=[],h=function(){var a=g.shift();a&&a.call(this)};(d.depaPos[0]!==d.destPos[0]||d.depaPos[1]!==d.destPos[1])&&g.push(function(){f._animate(d,h)}),this._isOutside(d.destPos,this.options.min,this.options.max)&&g.push(function(){f._restore(h,c)}),g.push(function(){f._animationEnd()}),h()}},_frame:function(a){for(var b=new Date-a.startTime,c=this._easing(b/a.duration),d=[a.depaPos[0],a.depaPos[1]],e=0;2>e;e++)d[e]!==a.destPos[e]&&(d[e]+=(a.destPos[e]-d[e])*c);return d=this._getCircularPos(d),this._triggerChange(d,!1),c},_reviseOptions:function(){var b,c=this;a.each(["bounce","margin","circular"],function(d,e){b=c.options[e],null!=b&&(c.options[e]=a.isArray(b)?2===b.length?b.concat(b):b.concat():/string|number|boolean/.test(typeof b)?[b,b,b,b]:null)})},_triggerChange:function(a,b,c){this._pos=a.concat(),this.trigger("change",{pos:a.concat(),holding:b,hammerEvent:c||null})},get:function(){return this._pos.concat()},setTo:function(a,b,c){this._grab();var d=this._pos.concat(),e=this.options.circular,f=this.options.min,g=this.options.max;return a===d[0]&&b===d[1]?this:(this._setInterrupt(!0),a!==d[0]&&(e[3]||(a=Math.max(f[0],a)),e[1]||(a=Math.min(g[0],a))),b!==d[1]&&(e[0]||(b=Math.max(f[1],b)),e[2]||(b=Math.min(g[1],b))),c?this._animateTo([a,b],c):(this._pos=this._getCircularPos([a,b]),this._triggerChange(this._pos,!1),this._setInterrupt(!1)),this)},setBy:function(a,b,c){return this.setTo(null!=a?this._pos[0]+a:this._pos[0],null!=b?this._pos[1]+b:this._pos[1],c)},_easing:function(a){return a>1?1:this.options.easing(a,a,0,1,1)},_initSlope:function(){var b,c=this.options.easing,d=!1;for(b in a.easing)if(a.easing[b]===c){d=!~b.indexOf("Out");break}return d?c(.9999,.9999,0,1,1)/.9999:c(1e-5,1e-5,0,1,1)/1e-5},_setInterrupt:function(a){!this._subOptions.interruptable&&(this._status.prevented=a)},destroy:function(){this.off();for(var a in this._hammers)this._hammers[a].inst.destroy(),this._hammers[a]=null}});return f._KEY="__MOVABLECOORD__",f.DIRECTION_NONE=1,f.DIRECTION_LEFT=2,f.DIRECTION_RIGHT=4,f.DIRECTION_UP=8,f.DIRECTION_DOWN=16,f.DIRECTION_HORIZONTAL=6,f.DIRECTION_VERTICAL=24,f.DIRECTION_ALL=f.DIRECTION_HORIZONTAL|f.DIRECTION_VERTICAL,{MovableCoord:b.MovableCoord}}),eg.module("flicking",["jQuery",eg,window,document,eg.MovableCoord],function(a,b,c,d,e){var f={beforeFlickStart:"beforeFlickStart",beforeRestore:"beforeRestore",flick:"flick",flickEnd:"flickEnd",restore:"restore"},g=d.documentElement.style;g="transform"in g||"webkitTransform"in g;var h=c.CSS&&c.CSS.supports&&c.CSS.supports("will-change","transform"),i=b.agent().os;i="android"===i.name&&/^2\./.test(i.version),b.Flicking=b.Class.extend(b.Component,{_events:function(){return f},construct:function(c,d,e){this.$wrapper=a(c);var f=this.$wrapper.children();if(!f.length)throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized.");this._setOptions(d),this._setConfig(f,e),!b._hasClickBug()&&(this._setPointerEvents=a.noop),this._build(),this._bindEvents(!0),this._applyPanelsCss(),this._arrangePanels(),this.options.hwAccelerable&&h&&this._setHint(),this._adjustContainerCss("end")},_setOptions:function(c){var d={previewPadding:[0,0],bounce:[10,10]};a.extend(this.options={hwAccelerable:b.isHWAccelerable(),prefix:"eg-flick",deceleration:6e-4,horizontal:!0,circular:!1,previewPadding:d.previewPadding,bounce:d.bounce,threshold:40,duration:100,panelEffect:a.easing.easeOutCubic,defaultIndex:0,inputType:["touch","mouse"]},c);var e=this;a.each(d,function(b,c){var d=e.options[b];a.isNumeric(d)?d=[d,d]:a.isArray(d)||(d=c),e.options[b]=d})},_setConfig:function(b,c){var d=this.options,f=d.previewPadding;b.eq(0).hasClass(d.prefix+"-container")&&(this.$container=b,b=b.children()),this._conf={panel:{$list:b,index:0,no:0,currIndex:0,currNo:0,size:0,count:0,origCount:0,changed:!1,animating:!1,minCount:f[0]+f[1]>0?5:3},touch:{holdPos:[0,0],destPos:[0,0],distance:0,direction:null,lastPos:0,holding:!1},customEvent:{flick:!0,restore:!1,restoreCall:!1},origPanelStyle:{wrapper:{className:this.$wrapper.attr("class")||null,style:this.$wrapper.attr("style")||null},list:b.map(function(b,c){return{className:a(c).attr("class")||null,style:a(c).attr("style")||null}})},inputEvent:!1,useLayerHack:d.hwAccelerable&&!h,dirData:[],indexToMove:0,eventPrefix:c||"",$dummyAnchor:null},a([["LEFT","RIGHT"],["UP","DOWN"]][+!d.horizontal]).each(a.proxy(function(a,b){this._conf.dirData.push(e["DIRECTION_"+b])},this))},_build:function(){var a,b=this._conf.panel,c=this.options,d=b.$list,f=c.previewPadding.concat(),g=c.prefix,h=c.horizontal,i=b.count=b.origCount=d.length,j=c.bounce;this._setPadding(f,!0);var k=this._getDataByDirection([b.size,"100%"]);a="position:relative;z-index:2000;width:100%;height:100%;"+(h?"":"top:0;"),this.$container?this.$container.attr("style",a):this.$container=d.wrapAll("
").parent(),d.addClass(g+"-panel").css({position:"absolute",width:k[0],height:k[1],boxSizing:"border-box",top:0,left:0}),this._addClonePanels()&&(i=b.count=(b.$list=this.$container.children()).length),this._mcInst=new e({min:[0,0],max:this._getDataByDirection([b.size*(i-1),0]),margin:0,circular:!1,easing:c.panelEffect,deceleration:c.deceleration,bounce:this._getDataByDirection([0,j[1],0,j[0]])}),this._setDefaultPanel(c.defaultIndex)},_setPadding:function(b,c){var d=this.options.horizontal,e=this._conf.panel,f=b[0]+b[1],g={};(f||!c)&&(g.padding=(d?"0 "+b.reverse().join("px 0 "):b.join("px 0 "))+"px"),c&&(g.overflow="hidden",g.boxSizing="border-box"),!a.isEmptyObject(g)&&this.$wrapper.css(g),e.size=this.$wrapper[d?"width":"height"]()},_addClonePanels:function(){var a,b=this._conf.panel,c=b.origCount,d=b.minCount-c,e=b.$list;if(this.options.circular&&c0&&e>=a&&this._movePanelPosition(a,!0),c=this._getBasePositionIndex(),this._movePanelPosition(c,!1),this._setPanelNo({no:a,currNo:a})):a>0&&e>=a&&(this._setPanelNo({index:a,no:a,currIndex:a,currNo:a}),b=[-(d.size*a),0],this._setTranslate(b),this._setMovableCoord("setTo",[Math.abs(b[0]),Math.abs(b[1])],!0,0))},_arrangePanels:function(a,b){var c,d=this._conf,e=d.panel,f=d.touch,g=d.dirData;this.options.circular&&(d.customEvent.flick=!1,a&&(b&&(f.direction=g[+!Boolean(b>0)]),this._arrangePanelPosition(f.direction,b)),c=this._getBasePositionIndex(),this._setPanelNo({index:c,currIndex:c}),d.customEvent.flick=!!this._setMovableCoord("setTo",[e.size*e.index,0],!0,0)),this._applyPanelsPos()},_applyPanelsPos:function(){this._conf.panel.$list.each(a.proxy(this._applyPanelsCss,this))},_setMoveStyle:function(){return g?function(a,c){a.css("transform",b.translate(c[0],c[1],this._conf.useLayerHack))}:function(a,b){a.css({left:b[0],top:b[1]})}}(),_applyPanelsCss:function(){var b=this._conf,c="__dummy_anchor";i?(b.$dummyAnchor=a("."+c),!b.$dummyAnchor.length&&this.$wrapper.append(b.$dummyAnchor=a("")),this._applyPanelsCss=function(b,c){var d=this._getDataByDirection([this._conf.panel.size*b+"px",0]);a(c).css({left:d[0],top:d[1]})}):this._applyPanelsCss=function(b,c){var d=this._getDataByDirection([g?100*b+"%":this._conf.panel.size*b+"px",0]);this._setMoveStyle(a(c),d)}},_adjustContainerCss:function(a,c){var d,e=this._conf,f=e.panel,g=this.options,h=g.horizontal,j=g.previewPadding[0],k=this.$container;i&&(c||(c=[-f.size*f.index,0]),"start"===a?(k=k[0].style,d=parseInt(k[h?"left":"top"],10),h?d&&(k.left=0):d!==j&&(k.top=j+"px"),this._setTranslate([-c[+!g.horizontal],0])):"end"===a&&(!h&&(c[0]+=j),c=this._getCoordsValue(c),k.css({left:c.x,top:c.y,transform:b.translate(0,0,e.useLayerHack)}),e.$dummyAnchor[0].focus()))},_setMovableCoord:function(a,b,c,d){return c&&(b=this._getDataByDirection(b)),this._mcInst[a](b[0],b[1],d)},_setHint:function(){var a="transform";this.$container.css("willChange",a),this._conf.panel.$list.css("willChange",a)},_getDataByDirection:function(a){return a=a.concat(),!this.options.horizontal&&a.reverse(),a},_arrangePanelPosition:function(a,b){var c=a===this._conf.dirData[0];this._movePanelPosition(Math.abs(b||1),c)},_getBasePositionIndex:function(){return Math.floor(this._conf.panel.count/2-.1)},_bindEvents:function(b){var c=this.options,d=this.$wrapper,f=this._mcInst;b?f.bind(d,{scale:this._getDataByDirection([-1,0]),direction:e["DIRECTION_"+(c.horizontal?"HORIZONTAL":"VERTICAL")],interruptable:!1,inputType:c.inputType}).on({hold:a.proxy(this._holdHandler,this),change:a.proxy(this._changeHandler,this),release:a.proxy(this._releaseHandler,this),animationStart:a.proxy(this._animationStartHandler,this),animationEnd:a.proxy(this._animationEndHandler,this)}):f.unbind(d).off(),this._conf.inputEvent=!!b},_holdHandler:function(a){var b=this._conf;b.touch.holdPos=a.pos,b.touch.holding=!0,b.panel.changed=!1,this._adjustContainerCss("start",a.pos)},_changeHandler:function(b){var c,d,e=this._conf,g=e.touch,h=+!this.options.horizontal,i=b.pos[h],j=g.holdPos[h],k=null;this._setPointerEvents(b),b.hammerEvent?(c=b.hammerEvent.direction,d=b.hammerEvent[this.options.horizontal?"deltaX":"deltaY"],~a.inArray(c,e.dirData)||(c=e.dirData[+(Math.abs(g.lastPos)<=d)]),g.lastPos=d):g.lastPos=null,e.customEvent.flick&&(k=this._triggerEvent(f.flick,{pos:b.pos,holding:b.holding,direction:c||g.direction,distance:i-(j||(g.holdPos[h]=i))})),(k||null===k)&&this._setTranslate([-i,0])},_releaseHandler:function(a){var b=this._conf.touch,c=a.destPos,d=+!this.options.horizontal,e=b.holdPos[d],f=this._conf.panel.size;b.distance=a.depaPos[d]-b.holdPos[d],b.direction=this._conf.dirData[+!Boolean(b.holdPos[d]=0?a.currIndex:a.index-b,d=a.currNo>=0?a.currNo:a.no-b;this._setPanelNo({index:c,no:d})},_setPanelNo:function(b){var c=this._conf.panel,d=c.origCount-1,e=this._getNumByDirection();a.isPlainObject(b)?a.each(b,function(a,b){c[a]=b}):(c.currIndex=c.index,c.currNo=c.no,c.index+=e,c.no+=e),c.no>d?c.no=0:c.no<0&&(c.no=d)},_setPointerEvents:function(a){var b,c=this.$container.css("pointerEvents");a&&a.holding&&a.hammerEvent&&a.hammerEvent.preventSystemEvent&&"none"!==c?b="none":a||"auto"===c||(b="auto"),b&&this.$container.css("pointerEvents",b)},_getCoordsValue:function(a){return a=this._getDataByDirection(a),{x:this._getUnitValue(a[0]),y:this._getUnitValue(a[1])}},_setTranslate:function(a){a=this._getCoordsValue(a),this._setMoveStyle(this.$container,[a.x,a.y])},_getUnitValue:function(a){var b=/(?:[a-z]{2,}|%)$/;return(parseInt(a,10)||0)+(String(a).match(b)||"px")},_isMovable:function(){var a,b,c=this.options,d=this._mcInst,e=Math.abs(this._conf.touch.distance)>=c.threshold;return!c.circular&&e&&(a=this._getDataByDirection(d.options.max)[0],b=this._getDataByDirection(d.get())[0],0>b||b>a)?!1:e},_triggerEvent:function(b,c){var d=this._conf,e=d.panel;return b===f.flickEnd&&(e.currNo=e.no,e.currIndex=e.index),this.trigger(d.eventPrefix+b,a.extend({eventType:b,index:e.currIndex,no:e.currNo,direction:d.touch.direction},c))},_getElement:function(b,c,d){var e,f,g,h=this._conf.panel,i=this.options.circular,j=h.currIndex,k=b===this._conf.dirData[0],l=null;return d?(e=h.count,f=j):(e=h.origCount,f=h.currNo),g=f,k?e-1>f?f++:i&&(f=0):f>0?f--:i&&(f=e-1),g!==f&&(l=c?a(h.$list[k?j+1:j-1]):f),l},_setValueToMove:function(a){var b=this._conf;b.touch.distance=this.options.threshold+1,b.touch.direction=b.dirData[+!a]},_getNumValue:function(a,b){return isNaN(a=parseInt(a,10))?b:a},getIndex:function(a){return this._conf.panel[a?"currIndex":"currNo"]},getElement:function(){var b=this._conf.panel;return a(b.$list[b.currIndex])},getNextElement:function(){return this._getElement(this._conf.dirData[0],!0)},getNextIndex:function(a){return this._getElement(this._conf.dirData[0],!1,a)},getAllElements:function(){return this._conf.panel.$list},getPrevElement:function(){return this._getElement(this._conf.dirData[1],!0)},getPrevIndex:function(a){return this._getElement(this._conf.dirData[1],!1,a)},getTotalCount:function(a){return this._conf.panel[a?"count":"origCount"]},isPlaying:function(){return this._conf.panel.animating},_movePanel:function(a,b){var c=this._conf,d=c.panel,e=this.options;return d.animating||c.touch.holding?void 0:(this._setValueToMove(a),(e.circular||null!=this[a?"getNextIndex":"getPrevIndex"]())&&this._movePanelByPhase("setBy",[d.size*(a?1:-1),0],b), +this)},_movePanelByPhase:function(a,b,c){c=this._getNumValue(c,this.options.duration),this._setPhaseValue("start")!==!1&&(this._setMovableCoord(a,b,!0,c),!c&&this._setPhaseValue("end"))},next:function(a){return this._movePanel(!0,a)},prev:function(a){return this._movePanel(!1,a)},moveTo:function(a,b){var c,d,e=this._conf,f=e.panel,g=this.options.circular,h=f.index;return a=this._getNumValue(a,-1),0>a||a>=f.origCount||a===f.no||f.animating||e.touch.holding?this:(g?(c=a-f.no,d=c>0,Math.abs(c)>(d?f.count-(h+1):h)&&(c+=(d?-1:1)*f.count),this._setPanelNo({no:a})):(c=a-h,this._setPanelNo({index:a,no:a})),this._conf.indexToMove=c,this._setValueToMove(d),this._movePanelByPhase(g?"setBy":"setTo",[f.size*(g?c:a),0],b),this)},_checkPadding:function(){var b=this.options,c=b.previewPadding.concat(),d=this.$wrapper.css("padding").split(" ");b.horizontal&&d.reverse(),d=2===d.length?[d[0],d[0]]:[d[0],d[2]],d=a.map(d,function(a){return parseInt(a,10)}),(2===c.length&&c[0]!==d[0]||c[1]!==d[1])&&this._setPadding(c)},resize:function(){var a,b,c=this._conf,d=this.options,e=c.panel,f=d.horizontal;return~~d.previewPadding.join("")?(this._checkPadding(),a=e.size):f&&(a=e.size=this.$wrapper.width()),b=this._getDataByDirection([a*(e.count-1),0]),f&&this.$container.width(b[0]+a),e.$list.css(f?"width":"height",a),this._mcInst.options.max=b,this._setMovableCoord("setTo",[a*e.index,0],!0,0),i&&(this._applyPanelsPos(),this._adjustContainerCss("end")),this},restore:function(a){var b,c=this._conf,d=c.panel,e=this._getDataByDirection(this._mcInst.get());return e[0]!==d.currIndex*d.size?(c.customEvent.restoreCall=!0,a=this._getNumValue(a,this.options.duration),this._revertPanelNo(),b=this._getDataByDirection([d.size*d.index,0]),this._triggerBeforeRestore({depaPos:e,destPos:b}),this._setMovableCoord("setTo",b,!0,a),a||(this._adjustContainerCss("end"),this._triggerRestore())):d.changed&&(this._revertPanelNo(),c.touch.distance=c.indexToMove=0),this},_setInputEvent:function(a){var b=this._conf.inputEvent;return a^b&&this._bindEvents(a),this},enableInput:function(){return this._setInputEvent(!0)},disableInput:function(){return this._setInputEvent()},destroy:function(){var b=this._conf,c=b.origPanelStyle,d=c.wrapper,e=c.list;this.$wrapper.attr("class",d.className).attr("style",d.style),this.$container.children().unwrap().each(function(b,c){var d=a(c);return b>e.length-1?!!d.remove():void d.attr("class",e[b].className).attr("style",e[b].style)}),this.disableInput(),this.off();for(var f in this)this[f]=null}})}),eg.module("infiniteGrid",["jQuery",eg,window,document],function(a,b,c,d){var e={layoutComplete:"layoutComplete",append:"append",prepend:"prepend"};b.InfiniteGrid=b.Class.extend(b.Component,{_events:function(){return e},construct:function(b,e,f){this.options=a.extend({isEqualSize:!1,defaultGroupKey:null,count:30,threshold:300},e),this.$el=b instanceof a?b:a(b),this.el=this.$el.get(0),this.el.style.position="relative",this._prefix=f||"",this._isIos=/iPhone|iPad/.test(c.navigator.userAgent),this._isIE10lower=!!(d.documentMode&&d.documentMode<10),this._appendCols=this._prependCols=[],this.$view=a(c),this._reset(),this._refreshViewport(),this.el.children.length>0&&(this.items=this._itemize(a.makeArray(this.el.children),this.options.defaultGroupKey,!0),this.layout(this.items,!0)),this._onScroll=a.proxy(this._onScroll,this),this._onResize=a.proxy(this._onResize,this),this.$view.on("scroll",this._onScroll).on("resize",this._onResize)},_getScrollTop:function(){return d.body.scrollTop||d.documentElement.scrollTop},_onScroll:function(){if(!this.isProcessing()){var b=this._getScrollTop(),c=this._prevScrollTop;if(!(this._isIos&&0===b||c===b)){var d,f;if(b>c){if(a.isEmptyObject(this._bottomElement)&&(this._bottomElement=this.getBottomElement(),null==this._bottomElement))return;d=this._bottomElement,f=d.getBoundingClientRect(),f.top<=this._clientHeight+this.options.threshold&&this.trigger(this._prefix+e.append,{scrollTop:b})}else if(this.isRecycling()&&this._removedContent>0){if(a.isEmptyObject(this._topElement)&&(this._topElement=this.getTopElement(),null==this._topElement))return;if(d=this._topElement,f=d.getBoundingClientRect(),f.bottom>=-this.options.threshold){var g=this.fit();g>0&&(b-=g,this.$view.scrollTop(b)),this.trigger(this._prefix+e.prepend,{scrollTop:b})}}this._prevScrollTop=b}}},_onResize:function(){this._resizeTimeout&&clearTimeout(this._resizeTimeout);var a=this;this._resizeTimeout=setTimeout(function(){a._refreshViewport(),a.$el.innerWidth()!==a._containerWidth&&a.layout(a.items,!0),a._resizeTimeout=null},100)},_refreshViewport:function(){this._clientHeight=this.$view.height()},getStatus:function(){var b,c={};for(b in this)!this.hasOwnProperty(b)||!/^_/.test(b)||"function"==typeof this[b]||this[b]instanceof Element||(c[b]=this[b]);return{prop:c,options:a.extend({},this.options),items:a.map(this.items,function(b){var c=a.extend({},b);return delete c.el,c}),html:this.el.innerHTML,cssText:this.el.style.cssText}},setStatus:function(b){return b&&b.cssText&&b.html&&b.prop&&b.items?(this.el.style.cssText=b.cssText,this.el.innerHTML=b.html,a.extend(this,b.prop),this._topElement=this._bottomElement=null,this.items=a.map(this.el.children,function(a,c){return b.items[c].el=a,b.items[c]}),this):this},isProcessing:function(){return this._isProcessing},isRecycling:function(){return this.options.count>0&&this._isRecycling},getGroupKeys:function(){return a.map(this.items,function(a){return a.groupKey})},layout:function(b,c){return b=b||this.items,c="undefined"==typeof c?!0:c,this._isProcessing=!0,c&&(b=a.map(b,function(a){return a.isAppend=!0,a})),this._waitResource(b,c),this},_layoutItems:function(b){var c=this;a.each(a.map(b,function(a){return a.position=c._getItemLayoutPosition(a),a}),function(a,b){if(b.el){var c=b.el.style;c.left=b.position.x+"px",c.top=b.position.y+"px"}})},append:function(b,c){return this._isProcessing||0===b.length?void 0:(b=a(b),this._isProcessing=!0,this.isRecycling()||(this._isRecycling=this.items.length+b.length>=this.options.count),this._insert(b,c,!0),b.length)},prepend:function(b,c){return this.isRecycling()&&0!==this._removedContent&&!this._isProcessing&&0!==b.length?(b=a(b),this._isProcessing=!0,this._fit(),b.length>this._removedContent&&(b=b.slice(0,this._removedContent)),this._insert(b,c,!1),b.length):void 0},clear:function(){return this.el.innerHTML="",this.el.style.height="",this._reset(),this},_getTopItem:function(){var b=null,c=1/0;return a.each(this._getColItems(!1),function(a,d){d&&d.position.yc&&(c=d.position.y+d.size.height,b=d)}),b},getBottomElement:function(){var a=this._getBottomItem();return a&&a.el},_postLayout:function(a){if(this._isProcessing&&!(a.length<=0)){var b=this._getContainerSize();this.el.style.width=b.width+"px",this.el.style.height=b.height+"px",this._topElement=this.getTopElement(),this._bottomElement=this.getBottomElement();var c=0,d=a[0].isAppend;d||(this._isFitted=!1,this._fit(!0),c=a.length>=this.items.length?0:this.items[a.length].position.y,c>0&&(this._prevScrollTop=this._getScrollTop()+c,this.$view.scrollTop(this._prevScrollTop))),this._isProcessing=!1,this.trigger(this._prefix+e.layoutComplete,{target:a.concat(),isAppend:d,distance:c,croppedCount:this._removedContent})}},_insert:function(b,c,d){if(0!==b.length){var e=b.toArray(),f=a(e),g=-this._clientHeight+"px";a.each(e,function(a,b){b.style.position="absolute",b.style.top=g});var h=this._itemize(e,c,d);d?this.items=this.items.concat(h):(this.items=h.concat(this.items),h=h.reverse()),this.isRecycling()&&this._adjustRange(d,f),this.$el[d?"append":"prepend"](f),this.layout(h,!1)}},_waitResource:function(b,c){var d=this._checkImageLoaded(),e=this,f=function(){e._isProcessing&&((c||!e._appendCols.length)&&(a.each(b,function(a,b){b.el.style.position="absolute"}),e._measureColumns()),e._layoutItems(b),e._postLayout(b))};d.length>0?this._waitImageLoaded(d,f):setTimeout(function(){f&&f()},0)},_adjustRange:function(b,c){var d,e,f=this.items.length-this.options.count;0>=f||(e=this._getDelimiterIndex(b,f))<0||(b?(d=this.items.splice(0,e),this._isFitted=!1):d=this.items.splice(e,this.items.length-e),a.each(d,function(a,b){e=c.index(b.el),-1!==e?c.splice(e,1):b.el.parentNode.removeChild(b.el)}),this._removedContent+=b?d.length:-d.length)},_getDelimiterIndex:function(a,b){var c,d=this.items.length,e=0,f=a?b-1:d-b,g=f+(a?1:-1),h=this.items[f].groupKey;if(null!=h&&h===this.items[g].groupKey)if(a){for(c=f;c>0&&h===this.items[c].groupKey;c--);e=0===c?-1:c+1}else{for(c=f;d>c&&h===this.items[c].groupKey;c++);e=c===d?-1:c}else e=a?g:f;return e},_fit:function(b){if(this.options.count<=0)return this._fit=function(){return!1},this._isFitted=!0,!1;if(this._isFitted)return!1;var c=this._updateCols();a.each(this.items,function(a,d){d.position.y-=c,b&&(d.el.style.top=d.position.y+"px")}),this._updateCols(!0);var d=this._getContainerSize().height;return b&&(this.el.style.height=d+"px"),this._isFitted=!0,!0},fit:function(){var a=this._getTopItem(),b=a?a.position.y:0;return this._fit(!0),b},_reset:function(){this._isProcessing=!1,this._topElement=null,this._bottomElement=null,this._isFitted=!0,this._isRecycling=!1,this._removedContent=0,this._prevScrollTop=0,this._equalItemSize=0,this._resizeTimeout=null,this._resetCols(this._appendCols.length||0),this.items=[]},_checkImageLoaded:function(){return this.$el.find("img").filter(function(b,c){return c.nodeType&&-1!==a.inArray(c.nodeType,[1,9,11])?!c.complete:void 0}).toArray()},_waitImageLoaded:function(b,c){var d,e=b.length,f=function(b){e--,a(b.target).off("load error"),0>=e&&c&&c()},g=this;a.each(b,function(b,c){if(d=a(c),g._isIE10lower){var e=c.getAttribute("src");c.setAttribute("src",""),c.setAttribute("src",e)}d.on("load error",f)})},_measureColumns:function(){this.el.style.width=null,this._containerWidth=this.$el.innerWidth(),this._columnWidth=this._getColumnWidth()||this._containerWidth;var a=this._containerWidth/this._columnWidth,b=this._columnWidth-this._containerWidth%this._columnWidth;a=Math.max(Math[b&&1>=b?"round":"floor"](a),1),this._resetCols(a||0)},_resetCols:function(a){a="undefined"==typeof a?0:a;for(var b=[];a--;)b.push(0);this._appendCols=b.concat(),this._prependCols=b.concat()},_getContainerSize:function(){return{height:Math.max.apply(Math,this._appendCols),width:this._containerWidth}},_getColumnWidth:function(){var b=this.items[0]&&this.items[0].el,c=0;if(b){var d=a(b);c=d.innerWidth(),this.options.isEqualSize&&(this._equalItemSize={width:c,height:d.innerHeight()})}return c},_updateCols:function(a){for(var b,c=a?this._appendCols:this._prependCols,d=this._getColItems(a),e=this._isFitted||a?0:this._getMinY(d),f=0,g=c.length;g>f;f++)c[f]=(b=d[f])?b.position.y+(a?b.size.height:-e):0;return e},_getMinY:function(b){return Math.min.apply(Math,a.map(b,function(a){return a?a.position.y:0}))},_getColIdx:function(a){return parseInt(a.position.x/parseInt(this._columnWidth,10),10)},_getColItems:function(a){for(var b,c,d=this._appendCols.length,e=new Array(d),f=0,g=a?this.items.length-1:0;b=this.items[g];){if(c=this._getColIdx(b),!e[c]&&(e[c]=b,++f===d))return e;g+=a?-1:1}return e},_itemize:function(b,c,d){return a.map(b,function(a){return{el:a,position:{x:0,y:0},isAppend:"undefined"==typeof d?!0:d,groupKey:"undefined"==typeof c?null:c}})},_getItemLayoutPosition:function(b){if(b.el){var c=a(b.el);b.size=this._equalItemSize||{width:c.innerWidth(),height:c.innerHeight()};var d,e=b.isAppend,f=e?this._appendCols:this._prependCols,g=Math[e?"min":"max"].apply(Math,f);if(e)d=a.inArray(g,f);else for(var h=f.length;h-->=0;)if(f[h]===g){d=h;break}return f[d]=g+(e?b.size.height:-b.size.height),{x:this._columnWidth*d,y:e?g:g-b.size.height}}},destroy:function(){this.off(),this.$view.off("resize",this._onResize).off("scroll",this._onScroll),this._reset()}})}); \ No newline at end of file diff --git a/dist/pkgd/flicking.pkgd.min.js b/dist/pkgd/flicking.pkgd.min.js new file mode 100644 index 00000000..bf4b485a --- /dev/null +++ b/dist/pkgd/flicking.pkgd.min.js @@ -0,0 +1,30 @@ +/** +* Copyright (c) 2015 NAVER corp. +* egjs projects are licensed under the MIT license +* https://naver.github.io/egjs/license.txt +* +* egjs JavaScript library +* http://naver.github.io/egjs +* +* @version 1.3.0 +* @SHA-1 13e6ef5 (1.3.0-rc) +* +* For custom build use egjs-cli +* https://github.com/naver/egjs-cli +*/ +/** +* All-in-one packaged file for ease use of 'eg.flicking' with below dependencies. +* NOTE: This is not an official distribution file and is only for user convenience. +* +* bower_components/hammer.js/hammer.js +* src/module.js +* src/agent.js +* src/eg.js +* src/class.js +* src/component.js +* src/hook/cssPrefix.js +* src/movableCoord.js +* src/flicking.js +*/ +!function(a,b,c,d){function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&la(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==oa?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;dc[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=ra(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=qa(j.x)>qa(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};(b.eventType===Ea||f.eventType===Ga)&&(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Ha&&(i>Da||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=qa(l.x)>qa(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;ce;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:pa(c/b),y:pa(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Ia:qa(a)>=qa(b)?0>a?Ja:Ka:0>b?La:Ma}function H(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Ra)+I(a[1],a[0],Ra)}function K(a,b){return H(b[0],b[1],Ra)/H(a[0],a[1],Ra)}function L(){this.evEl=Ta,this.evWin=Ua,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Xa,this.evWin=Ya,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=$a,this.evWin=_a,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Ga|Ha)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=bb,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches),d=this.targetIds;if(b&(Ea|Fa)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=s(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return o(a.target,i)}),b===Ea)for(e=0;e-1&&d.splice(a,1)};setTimeout(e,cb)}}function U(a){for(var b=a.srcEvent.clientX,c=a.srcEvent.clientY,d=0;d=f&&db>=g)return!0}return!1}function V(a,b){this.manager=a,this.set(b)}function W(a){if(p(a,jb))return jb;var b=p(a,kb),c=p(a,lb);return b&&c?jb:b||c?b?kb:lb:p(a,ib)?ib:hb}function X(){if(!fb)return!1;var b={},c=a.CSS&&a.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(d){b[d]=c?a.CSS.supports("touch-action",d):!0}),b}function Y(a){this.options=la({},this.defaults,a||{}),this.id=v(),this.manager=null,this.options.enable=l(this.options.enable,!0),this.state=nb,this.simultaneous={},this.requireFail=[]}function Z(a){return a&sb?"cancel":a&qb?"end":a&pb?"move":a&ob?"start":""}function $(a){return a==Ma?"down":a==La?"up":a==Ja?"left":a==Ka?"right":""}function _(a,b){var c=b.manager;return c?c.get(a):a}function aa(){Y.apply(this,arguments)}function ba(){aa.apply(this,arguments),this.pX=null,this.pY=null}function ca(){aa.apply(this,arguments)}function da(){Y.apply(this,arguments),this._timer=null,this._input=null}function ea(){aa.apply(this,arguments)}function fa(){aa.apply(this,arguments)}function ga(){Y.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function ha(a,b){return b=b||{},b.recognizers=l(b.recognizers,ha.defaults.preset),new ia(a,b)}function ia(a,b){this.options=la({},ha.defaults,b||{}),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=a,this.input=y(this),this.touchAction=new V(this,this.options.touchAction),ja(this,!0),g(this.options.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function ja(a,b){var c=a.element;if(c.style){var d;g(a.options.cssProps,function(e,f){d=u(c.style,f),b?(a.oldCssProps[d]=c.style[d],c.style[d]=e):c.style[d]=a.oldCssProps[d]||""}),b||(a.oldCssProps={})}}function ka(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var la,ma=["","webkit","Moz","MS","ms","o"],na=b.createElement("div"),oa="function",pa=Math.round,qa=Math.abs,ra=Date.now;la="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;ch&&(b.push(a),h=b.length-1):e&(Ga|Ha)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Za={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},$a="touchstart",_a="touchstart touchmove touchend touchcancel";i(N,x,{handler:function(a){var b=Za[a.type];if(b===Ea&&(this.started=!0),this.started){var c=O.call(this,a,b);b&(Ga|Ha)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}}});var ab={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},bb="touchstart touchmove touchend touchcancel";i(P,x,{handler:function(a){var b=ab[a.type],c=Q.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}});var cb=2500,db=25;i(R,x,{handler:function(a,b,c){var d=c.pointerType==za,e=c.pointerType==Ba;if(!(e&&c.sourceCapabilities&&c.sourceCapabilities.firesTouchEvents)){if(d)S.call(this,b,c);else if(e&&U.call(this,c))return;this.callback(a,b,c)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var eb=u(na.style,"touchAction"),fb=eb!==d,gb="compute",hb="auto",ib="manipulation",jb="none",kb="pan-x",lb="pan-y",mb=X();V.prototype={set:function(a){a==gb&&(a=this.compute()),fb&&this.manager.element.style&&mb[a]&&(this.manager.element.style[eb]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){k(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),W(a.join(" "))},preventDefaults:function(a){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=p(d,jb)&&!mb[jb],f=p(d,lb)&&!mb[lb],g=p(d,kb)&&!mb[kb];if(e){var h=1===a.pointers.length,i=a.distance<2,j=a.deltaTime<250;if(h&&i&&j)return}return g&&f?void 0:e||f&&c&Na||g&&c&Oa?this.preventSrc(b):void 0},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var nb=1,ob=2,pb=4,qb=8,rb=qb,sb=16,tb=32;Y.prototype={defaults:{},set:function(a){return la(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=_(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=_(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=_(a,this),-1===r(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=_(a,this);var b=r(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(b,a)}var c=this,d=this.state;qb>d&&b(c.options.event+Z(d)),b(c.options.event),a.additionalEvent&&b(a.additionalEvent),d>=qb&&b(c.options.event+Z(d))},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=tb)},canEmit:function(){for(var a=0;af?Ja:Ka,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Ia:0>g?La:Ma,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return aa.prototype.attrTest.call(this,a)&&(this.state&ob||!(this.state&ob)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=$(a.direction);b&&(a.additionalEvent=this.options.event+b),this._super.emit.call(this,a)}}),i(ca,aa,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&ob)},emit:function(a){if(1!==a.scale){var b=a.scale<1?"in":"out";a.additionalEvent=this.options.event+b}this._super.emit.call(this,a)}}),i(da,Y,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[hb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distanceb.time;if(this._input=a,!d||!c||a.eventType&(Ga|Ha)&&!f)this.reset();else if(a.eventType&Ea)this.reset(),this._timer=e(function(){this.state=rb,this.tryEmit()},b.time,this);else if(a.eventType&Ga)return rb;return tb},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===rb&&(a&&a.eventType&Ga?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=ra(),this.manager.emit(this.options.event,this._input)))}}),i(ea,aa,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&ob)}}),i(fa,aa,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Na|Oa,pointers:1},getTouchAction:function(){return ba.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Na|Oa)?b=a.overallVelocity:c&Na?b=a.overallVelocityX:c&Oa&&(b=a.overallVelocityY),this._super.attrTest.call(this,a)&&c&a.offsetDirection&&a.distance>this.options.threshold&&a.maxPointers==this.options.pointers&&qa(b)>this.options.velocity&&a.eventType&Ga},emit:function(a){var b=$(a.offsetDirection);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),i(ga,Y,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ib]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance2?a+1+"th":m[a]}function e(a,b){var c;for(c in b)a=a.replace(new RegExp("{{"+c+"}}","gi"),b[c]);return a}function f(a,b){for(var f,g,h,i,j,m,n,o,p=0,q=b.length,r=[],s=[],t=c.require;q>p;p++)g=b[p],h={index:d(p),name:g,componentName:a},i="string"==typeof b[p],j=void 0===b[p],m=i&&(f=k[b[p]]),n=i&&f&&!c[b[p]],o=n&&t&&t.specified&&t.specified(b[p]),i||j?o&&t.defined(b[p])?(g=t(b[p]),s.push(g)):!o||t.defined(b[p])?n&&t&&t.specified&&!t.specified(b[p])?(h.url=f.url,r.push(e(l[1],h))):!n||t?m&&c[b[p]]?(g=c[b[p]],s.push(g)):!i||f?void 0!==b[p]||r.push(e(l[4],h)):r.push(e(l[3],h)):(h.url=f.url,r.push(e(l[2],h))):(h.url=f.url,r.push(e(l[0],h))):s.push(g);return[s,r]}function g(a){return a.charAt(0).toUpperCase()+a.slice(1)}function h(a){var c,d,e,f=g(a);if(!(i[f]&&i[f].prototype&&i[f].prototype._events))return!1;if(j.fn[a])throw new Error("The name '"+f+"' has already been used and registered as plugin. Try with different one.");j.fn[a]=function(c){var d,e;return"string"==typeof c?(d=this.data(b+"-"+a),"instance"===c?d:(e=d[c].apply(d,Array.prototype.slice.call(arguments,1)),e===d?this:e)):((void 0===c||j.isPlainObject(c))&&this.data(b+"-"+a,new i[f](this,c||{},a+":")),this)},e={trigger:"trigger",add:"on",remove:"off"},c=i[f].prototype._events();for(var h in c){d=j.event.special[a+":"+c[h]]={},d.setup=function(){return!0};for(var k in e)d[k]=function(c){return function(d,e){return j(this).data(b+"-"+a)[c](d.type,"trigger"===c?e:d.handler),!1}}(e[k])}}var i;c[b]||(c[b]={}),i=c[b];var j=c[a],k={jQuery:{url:"http://jquery.com/"},Hammer:{url:"http://hammerjs.github.io/"}},l=["[egjs] The {{name}} library must be loaded before {{componentName}}.",'[egjs] For AMD environment (like RequireJS), "{{name}}" must be declared, which is required by {{componentName}}.',"[egjs] The {{index}} argument of {{componentName}} is missing.\r\nDownload {{name}} from [{{url}}].","[egjs] The {{name}} parameter of {{componentName}} is not valid.\r\nPlease check and try again.","[egjs] The {{index}} argument of {{componentName}} is undefined.\r\nPlease check and try again."],m=["1st","2nd","3rd"],n=function(a){(n=c.console&&c.console.warn?function(a){c.console.warn(a)}:function(){})(a)};i.module||(i.module=function(a,b,d){var e=f(a,b);e[1].length?n(e[1].join("\r\n")):(d.apply(c,e[0]),h(a))})}("jQuery","eg",window),eg.module("agent",[eg],function(a){function b(a){return j(a,n.defaultString.browser)}function c(a){var b,c;return a?(c=h(a).versionSearch||a,b=d(c,m)):void 0}function d(a,b){var c,d,e=n.defaultString.browser.version,f=new RegExp("("+a+")","i").exec(b);return f?(d=f.index,a=f[0],d>-1&&(c=d+a.length+1,e=b.substring(c).split(" ")[0].replace(/_/g,".").replace(/\;|\)/g,"")),e):e}function e(a){return j(a,n.defaultString.os)}function f(a){var b,c,d,e,f=m,h=g(a)||{},i=n.defaultString.os.version;return a?h.versionAlias?h.versionAlias:(c=h.versionSearch||a,d=new RegExp("("+c+")\\s([\\d_\\.]+|\\d_0)","i"),e=d.exec(f),e&&(b=d.exec(f)[2].replace(/_/g,".").replace(/\;|\)/g,"")),b||i):void 0}function g(a){return i(n.os,a)}function h(a){return i(n.browser,a)}function i(a,b){for(var c,d,e,f=0;e=a[f];f++)if(c=e.criteria,d=new RegExp(e.identity,"i").test(b),c?d&&k(m,c):d)return e}function j(a,b){for(var c,d=0;c=a[d];d++)if(k(m,c.criteria))return c.identity||b.name;return b.name}function k(a,b){return b&&b.test?!!b.test(a):a.indexOf(b)>-1}function l(){for(var a,b,c=m,e=n.webview,f=!1,g=0;b=e[g];g++)if(k(c,b.criteria)&&(a=d(b.browserVersionSearch,c),k(c,b.webviewToken)||k(a,b.webviewBrowserVersion))){f=!0;break}return f}var m,n={browser:[{criteria:"PhantomJS",identity:"PhantomJS"},{criteria:/Edge/,identity:"Edge",versionSearch:"Edge"},{criteria:/MSIE|Trident|Windows Phone/,identity:"IE",versionSearch:"IEMobile|MSIE|rv"},{criteria:/SAMSUNG|SamsungBrowser/,identity:"SBrowser",versionSearch:"Chrome"},{criteria:/Chrome|CriOS/,identity:"Chrome"},{criteria:/Android/,identity:"default"},{criteria:/iPhone|iPad/,identity:"Safari",versionSearch:"Version"},{criteria:"Apple",identity:"Safari",versionSearch:"Version"},{criteria:"Firefox",identity:"Firefox"}],os:[{criteria:/Windows Phone|Windows NT/,identity:"Window",versionSearch:"Windows Phone|Windows NT"},{criteria:"Windows 2000",identity:"Window",versionAlias:"5.0"},{criteria:/iPhone|iPad/,identity:"iOS",versionSearch:"iPhone OS|CPU OS"},{criteria:"Mac",versionSearch:"OS X",identity:"MAC"},{criteria:/Android/,identity:"Android"}],webview:[{criteria:/iPhone|iPad/,browserVersionSearch:"Version",webviewBrowserVersion:/-1/},{criteria:/iPhone|iPad|Android/,webviewToken:/NAVER|DAUM|; wv/}],defaultString:{browser:{version:"-1",name:"default"},os:{version:"-1",name:"unknown"}}};a.Agent={create:function(a){this.ua=m=a;var d={os:{},browser:{}};return d.browser.name=b(n.browser),d.browser.version=c(d.browser.name),d.os.name=e(n.os),d.os.version=f(d.os.name),d.browser.webview=l(),d.browser.name=d.browser.name.toLowerCase(),d.os.name=d.os.name.toLowerCase(),d}}}),eg.module("eg",["jQuery",eg,window,eg.Agent],function(a,b,c,d){function e(a,b,c,d){var e=a.hook[b];return e&&(d=e.apply(a,c)),a[b]=function(){var e=a.hook[b];return e?e.apply(a,c):d},d}var f=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,g=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(f&&!g){var h={},i=f;f=function(a){function b(){h[c]&&a()}var c=i(b);return h[c]=!0,c},g=function(a){delete h[a]}}else f&&g||(f=function(a){return c.setTimeout(a,16)},g=c.clearTimeout);b.VERSION="1.3.0",b.hook={},b.agent=function(){var a=d.create(c.navigator.userAgent);return e(this,"agent",[a],a)},b.translate=function(a,b,c){return c=c||!1,"translate"+(c?"3d(":"(")+a+","+b+(c?",0)":")")},b.isHWAccelerable=function(){var a,c=!1,f=b.agent(),g=f.os.version,h=f.browser.name,i=f.browser.version;return-1!==h.indexOf("chrome")?c=i>="25":/ie|edge|firefox|safari|inapp/.test(h)?c=!0:-1!==f.os.name.indexOf("android")&&(a=(d.ua.match(/\(.*\)/)||[null])[0],c=g>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||g>="4.0.3"&&/SHW-|SHV-|GT-|SCH-|SGH-|SPH-|LG-F160|LG-F100|LG-F180|LG-F200|EK-|IM-A|LG-F240|LG-F260/.test(a)&&!/SHW-M420|SHW-M200|GT-S7562/.test(a)),e(this,"isHWAccelerable",[c,f],c)},b.isTransitional=function(){var a=!1,c=b.agent(),d=c.browser.name;if(/chrome|firefox|sbrowser/.test(d))a=!0;else switch(c.os.name){case"ios":a=/safari|inapp/.test(d)&&parseInt(c.os.version,10)<6;break;case"window":a=/safari/.test(d)||/ie/.test(d)&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/safari/.test(d)}return e(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return e(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return f(a)},b.cancelAnimationFrame=function(a){g(a)},a.extend(a.easing,{easeOutCubic:function(a){return 1-Math.pow(1-a,3)}})}),eg.module("class",[eg],function(a){a.Class=function(a){var b=function(){"function"==typeof a.construct&&a.construct.apply(this,arguments)};return b.prototype=a,b.prototype.instance=function(){return this},b.prototype.constructor=b,b},a.Class.extend=function(a,b){var c=function(){a.apply(this,arguments),"function"==typeof b.construct&&b.construct.apply(this,arguments)},d=function(){};d.prototype=a.prototype;var e=new d;for(var f in b)e[f]=b[f];return e.constructor=c,c.prototype=e,c}}),eg.module("component",[eg],function(a){a.Component=a.Class({construct:function(){this.eventHandler={},this.options={}},option:function(a,b){if(arguments.length>=2)return this.options[a]=b,this;if("string"==typeof a)return this.options[a];if(0===arguments.length)return this.options;for(var c in a)this.options[c]=a[c];return this},trigger:function(a,b){b=b||{};var c=this.eventHandler[a]||[],d=c.length>0;if(!d)return!0;c=c.concat(),b.eventType=a;var e,f,g,h=!1,i=[b];for(b.stop=function(){h=!0},(f=arguments.length)>2&&(i=i.concat(Array.prototype.slice.call(arguments,2,f))),e=0;g=c[e];e++)g.apply(this,i);return!h},hasOn:function(a){return!!this.eventHandler[a]},on:function(a,b){if("object"==typeof a&&"undefined"==typeof b){var c,d=a;for(c in d)this.on(c,d[c]);return this}if("string"==typeof a&&"function"==typeof b){var e=this.eventHandler[a];"undefined"==typeof e&&(e=this.eventHandler[a]=[]),e.push(b)}return this},off:function(a,b){if(0===arguments.length)return this.eventHandler={},this;if("undefined"==typeof b){if("string"==typeof a)return this.eventHandler[a]=void 0,this;var c=a;for(var d in c)this.off(d,c[d]);return this}var e=this.eventHandler[a];if(e){var f,g;for(f=0,g;g=e[f];f++)if(g===b){e=e.splice(f,1);break}}return this}})}),eg.module("cssPrefix",["jQuery",document],function(a,b){if(!a.cssHooks)throw new Error("jQuery 1.4.3+ is needed for this plugin to work");var c=(a.fn.jquery.match(/^\d\.\d+/)||[])[0];if(c&&!(+c.replace(/\D/,"")>=18)){var d=["Webkit","Moz","O","ms"],e=["transitionProperty","transitionDuration","transition","transform","transitionTimingFunction"],f=function(){for(var a=(b.head||b.getElementsByTagName("head")[0]).style,c=0,e=d.length;e>c;c++)if(d[c]+"Transition"in a)return d[c]}();if(f){for(var g=function(b){var c=b.charAt(0).toUpperCase()+b.slice(1),d=f+c,e="ms"===f?"Ms"+c:d;a.cssHooks[c]=a.cssHooks[f.toLowerCase()+c]=a.cssHooks[b]={get:function(b,c){return c?a.css(b,e):b.style[d]},set:function(a,b){a.style[d]=b}}},h=0,i=e.length;i>h;h++)g(e[h]);return{vendorPrefix:f,setCssHooks:g}}}}),eg.module("movableCoord",["jQuery",eg,window,"Hammer"],function(a,b,c,d){var e="ontouchstart"in c,f=b.MovableCoord=b.Class.extend(b.Component,{construct:function(b){a.extend(this.options={min:[0,0],max:[100,100],bounce:[10,10,10,10],margin:[0,0,0,0],circular:[!1,!1,!1,!1],easing:a.easing.easeOutCubic,maximumDuration:1/0,deceleration:6e-4},b),this._reviseOptions(),this._status={grabOutside:!1,curHammer:null,moveDistance:null,animationParam:null,prevented:!1},this._hammers={},this._pos=this.options.min.concat(),this._subOptions={},this._raf=null,this._animationEnd=a.proxy(this._animationEnd,this),this._restore=a.proxy(this._restore,this),this._panmove=a.proxy(this._panmove,this),this._panend=a.proxy(this._panend,this)},bind:function(b,c){var d=a(b),e=d.data(f._KEY),g={direction:f.DIRECTION_ALL,scale:[1,1],thresholdAngle:45,interruptable:!0,inputType:["touch","mouse"]};a.extend(g,c);var h=this._convertInputType(g.inputType);return h?(e?this._hammers[e].inst.destroy():e=Math.round(Math.random()*(new Date).getTime()),this._hammers[e]={inst:this._createHammer(d.get(0),g,h),options:g},d.data(f._KEY,e),this):this},_createHammer:function(a,b,c){try{var e=new d.Manager(a,{recognizers:[[d.Pan,{direction:b.direction,threshold:0}]],cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",userDrag:"none"},inputClass:c});return this._attachHammerEvents(e,b)}catch(f){}},_attachHammerEvents:function(b,c){return b.on("hammer.input",a.proxy(function(a){a.isFirst?(this._subOptions=c,this._status.curHammer=b,this._panstart(a)):a.isFinal&&this._panend(a)},this)).on("panstart panmove",this._panmove)},_detachHammerEvents:function(a){a.off("hammer.input panstart panmove panend")},_convertInputType:function(b){var c=!1,f=!1;return b=b||[],a.each(b,function(a,b){switch(b){case"mouse":f=!0;break;case"touch":c=e}}),c&&d.TouchInput||f&&d.MouseInput||null},unbind:function(b){var c=a(b),d=c.data(f._KEY);return d&&(this._hammers[d].inst.destroy(),delete this._hammers[d],c.data(f._KEY,null)), +this},_grab:function(){if(this._status.animationParam){this.trigger("animationEnd");var a=this._getCircularPos(this._pos);(a[0]!==this._pos[0]||a[1]!==this._pos[1])&&(this._pos=a,this._triggerChange(this._pos,!0)),this._status.animationParam=null,this._raf&&b.cancelAnimationFrame(this._raf),this._raf=null}},_getCircularPos:function(a,b,c,d){return b=b||this.options.min,c=c||this.options.max,d=d||this.options.circular,d[0]&&a[1]c[0]&&(a[0]=(a[0]-b[0])%(c[0]-b[0]+1)+b[0]),d[2]&&a[1]>c[1]&&(a[1]=(a[1]-b[1])%(c[1]-b[1]+1)+b[1]),d[3]&&a[0]c[0]||a[1]>c[1]},_isOutToOut:function(a,b){var c=this.options.min,d=this.options.max;return(a[0]d[0]||a[1]d[1])&&(b[0]d[0]||b[1]d[1])},_panstart:function(a){if(this._subOptions.interruptable||!this._status.prevented){this._setInterrupt(!0);var b=this._pos;this._grab(),this.trigger("hold",{pos:b.concat(),hammerEvent:a}),this._status.moveDistance=b.concat(),this._status.grabOutside=this._isOutside(b,this.options.min,this.options.max)}},_panmove:function(a){if(this._isInterrupting()&&this._status.moveDistance){var b,c,d,e=this._pos,g=this.options.min,h=this.options.max,i=this.options.bounce,j=this.options.margin,k=this._subOptions.direction,l=this._subOptions.scale,m=this._getDirection(a.angle),n=[j[0]+i[0],j[1]+i[1],j[2]+i[2],j[3]+i[3]],o=!1,p=this._status.curHammer.session.prevInput;if(p?(a.offsetX=a.deltaX-p.deltaX,a.offsetY=a.deltaY-p.deltaY):a.offsetX=a.offsetY=0,(k===f.DIRECTION_ALL||k&f.DIRECTION_HORIZONTAL&&m&f.DIRECTION_HORIZONTAL)&&(this._status.moveDistance[0]+=a.offsetX*l[0],o=!0),(k===f.DIRECTION_ALL||k&f.DIRECTION_VERTICAL&&m&f.DIRECTION_VERTICAL)&&(this._status.moveDistance[1]+=a.offsetY*l[1],o=!0),o&&(a.srcEvent.preventDefault(),a.srcEvent.stopPropagation()),a.preventSystemEvent=o,e[0]=this._status.moveDistance[0],e[1]=this._status.moveDistance[1],e=this._getCircularPos(e,g,h),this._status.grabOutside&&!this._isOutside(e,g,h)&&(this._status.grabOutside=!1),this._status.grabOutside)c=g[0]-n[3],d=h[0]+n[1],b=e[0],e[0]=b>d?d:c>b?c:b,c=g[1]-n[0],d=h[1]+n[2],b=e[1],e[1]=b>d?d:c>b?c:b;else{var q=this._initSlope();e[1]h[1]&&(b=(e[1]-h[1])/(n[2]*q),e[1]=h[1]+this._easing(b)*n[2]),e[0]h[0]&&(b=(e[0]-h[0])/(n[1]*q),e[0]=h[0]+this._easing(b)*n[1])}this._triggerChange(e,!0,a)}},_panend:function(a){var b=this._pos;if(this._isInterrupting()&&this._status.moveDistance){if(0===a.distance)this._setInterrupt(!1),this.trigger("release",{depaPos:b.concat(),destPos:b.concat(),hammerEvent:a||null});else{var c=this._subOptions.direction,d=this._subOptions.scale,e=Math.abs(a.velocityX),g=Math.abs(a.velocityY);!(c&f.DIRECTION_HORIZONTAL)&&(e=0),!(c&f.DIRECTION_VERTICAL)&&(g=0);var h=this._getNextOffsetPos([e*(a.deltaX<0?-1:1)*d[0],g*(a.deltaY<0?-1:1)*d[1]]),i=[b[0]+h[0],b[1]+h[1]];i=this._getPointOfIntersection(b,i),this.trigger("release",{depaPos:b.concat(),destPos:i,hammerEvent:a||null}),b[0]!==i[0]||b[1]!==i[1]?this._animateTo(i,null,a||null):this._setInterrupt(!1)}this._status.moveDistance=null}},_isInterrupting:function(){return this._subOptions.interruptable||this._status.prevented},_getDirection:function(a){var b=this._subOptions.thresholdAngle;return 0>b||b>90?f.DIRECTION_NONE:(a=Math.abs(a),a>b&&180-b>a?f.DIRECTION_VERTICAL:f.DIRECTION_HORIZONTAL)},_getNextOffsetPos:function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]),c=Math.abs(b/-this.options.deceleration);return[a[0]/2*c,a[1]/2*c]},_getDurationFromPos:function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]),c=Math.sqrt(b/this.options.deceleration*2);return 100>c?0:c},_getPointOfIntersection:function(a,b){var c,d,e=this.options.circular,f=this.options.bounce,g=this.options.min,h=this.options.max,i=[g[0]-f[3],g[1]-f[0]],j=[h[0]+f[1],h[1]+f[2]];return b=[b[0],b[1]],c=b[0]-a[0],d=b[1]-a[1],e[3]||(b[0]=Math.max(i[0],b[0])),e[1]||(b[0]=Math.min(j[0],b[0])),b[1]=c?a[1]+d/c*(b[0]-a[0]):b[1],e[0]||(b[1]=Math.max(i[1],b[1])),e[2]||(b[1]=Math.min(j[1],b[1])),b[0]=d?a[0]+c/d*(b[1]-a[1]):b[0],[Math.min(h[0],Math.max(g[0],b[0])),Math.min(h[1],Math.max(g[1],b[1]))]},_isCircular:function(a){var b=this.options.circular,c=this.options.min,d=this.options.max;return b[0]&&a[1]d[0]||b[2]&&a[1]>d[1]||b[3]&&a[0]b?b:this.options.maximumDuration,{depaPos:d.concat(),destPos:e.concat(),isBounce:this._isOutside(e,this.options.min,this.options.max),isCircular:this._isCircular(a),duration:b,distance:f,hammerEvent:c||null,done:this._animationEnd}},_restore:function(a,b){var c=this._pos,d=this.options.min,e=this.options.max;this._animate(this._prepareParam([Math.min(e[0],Math.max(d[0],c[0])),Math.min(e[1],Math.max(d[1],c[1]))],null,b),a)},_animationEnd:function(){this._status.animationParam=null,this._pos=this._getCircularPos([Math.round(this._pos[0]),Math.round(this._pos[1])]),this._setInterrupt(!1),this.trigger("animationEnd")},_animate:function(a,c){if(a.startTime=(new Date).getTime(),this._status.animationParam=a,a.duration){var d=this._status.animationParam,e=this;!function f(){return e._raf=null,e._frame(d)>=1?void c():void(e._raf=b.requestAnimationFrame(f))}()}else this._triggerChange(a.destPos,!1),c()},_animateTo:function(a,b,c){var d=this._prepareParam(a,b,c),e=this.trigger("animationStart",d);if(d.isCircular&&!e)throw new Error("You can't stop the 'animation' event when 'circular' is true.");if(e){var f=this,g=[],h=function(){var a=g.shift();a&&a.call(this)};(d.depaPos[0]!==d.destPos[0]||d.depaPos[1]!==d.destPos[1])&&g.push(function(){f._animate(d,h)}),this._isOutside(d.destPos,this.options.min,this.options.max)&&g.push(function(){f._restore(h,c)}),g.push(function(){f._animationEnd()}),h()}},_frame:function(a){for(var b=new Date-a.startTime,c=this._easing(b/a.duration),d=[a.depaPos[0],a.depaPos[1]],e=0;2>e;e++)d[e]!==a.destPos[e]&&(d[e]+=(a.destPos[e]-d[e])*c);return d=this._getCircularPos(d),this._triggerChange(d,!1),c},_reviseOptions:function(){var b,c=this;a.each(["bounce","margin","circular"],function(d,e){b=c.options[e],null!=b&&(c.options[e]=a.isArray(b)?2===b.length?b.concat(b):b.concat():/string|number|boolean/.test(typeof b)?[b,b,b,b]:null)})},_triggerChange:function(a,b,c){this._pos=a.concat(),this.trigger("change",{pos:a.concat(),holding:b,hammerEvent:c||null})},get:function(){return this._pos.concat()},setTo:function(a,b,c){this._grab();var d=this._pos.concat(),e=this.options.circular,f=this.options.min,g=this.options.max;return a===d[0]&&b===d[1]?this:(this._setInterrupt(!0),a!==d[0]&&(e[3]||(a=Math.max(f[0],a)),e[1]||(a=Math.min(g[0],a))),b!==d[1]&&(e[0]||(b=Math.max(f[1],b)),e[2]||(b=Math.min(g[1],b))),c?this._animateTo([a,b],c):(this._pos=this._getCircularPos([a,b]),this._triggerChange(this._pos,!1),this._setInterrupt(!1)),this)},setBy:function(a,b,c){return this.setTo(null!=a?this._pos[0]+a:this._pos[0],null!=b?this._pos[1]+b:this._pos[1],c)},_easing:function(a){return a>1?1:this.options.easing(a,a,0,1,1)},_initSlope:function(){var b,c=this.options.easing,d=!1;for(b in a.easing)if(a.easing[b]===c){d=!~b.indexOf("Out");break}return d?c(.9999,.9999,0,1,1)/.9999:c(1e-5,1e-5,0,1,1)/1e-5},_setInterrupt:function(a){!this._subOptions.interruptable&&(this._status.prevented=a)},destroy:function(){this.off();for(var a in this._hammers)this._hammers[a].inst.destroy(),this._hammers[a]=null}});return f._KEY="__MOVABLECOORD__",f.DIRECTION_NONE=1,f.DIRECTION_LEFT=2,f.DIRECTION_RIGHT=4,f.DIRECTION_UP=8,f.DIRECTION_DOWN=16,f.DIRECTION_HORIZONTAL=6,f.DIRECTION_VERTICAL=24,f.DIRECTION_ALL=f.DIRECTION_HORIZONTAL|f.DIRECTION_VERTICAL,{MovableCoord:b.MovableCoord}}),eg.module("flicking",["jQuery",eg,window,document,eg.MovableCoord],function(a,b,c,d,e){var f={beforeFlickStart:"beforeFlickStart",beforeRestore:"beforeRestore",flick:"flick",flickEnd:"flickEnd",restore:"restore"},g=d.documentElement.style;g="transform"in g||"webkitTransform"in g;var h=c.CSS&&c.CSS.supports&&c.CSS.supports("will-change","transform"),i=b.agent().os;i="android"===i.name&&/^2\./.test(i.version),b.Flicking=b.Class.extend(b.Component,{_events:function(){return f},construct:function(c,d,e){this.$wrapper=a(c);var f=this.$wrapper.children();if(!f.length)throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized.");this._setOptions(d),this._setConfig(f,e),!b._hasClickBug()&&(this._setPointerEvents=a.noop),this._build(),this._bindEvents(!0),this._applyPanelsCss(),this._arrangePanels(),this.options.hwAccelerable&&h&&this._setHint(),this._adjustContainerCss("end")},_setOptions:function(c){var d={previewPadding:[0,0],bounce:[10,10]};a.extend(this.options={hwAccelerable:b.isHWAccelerable(),prefix:"eg-flick",deceleration:6e-4,horizontal:!0,circular:!1,previewPadding:d.previewPadding,bounce:d.bounce,threshold:40,duration:100,panelEffect:a.easing.easeOutCubic,defaultIndex:0,inputType:["touch","mouse"]},c);var e=this;a.each(d,function(b,c){var d=e.options[b];a.isNumeric(d)?d=[d,d]:a.isArray(d)||(d=c),e.options[b]=d})},_setConfig:function(b,c){var d=this.options,f=d.previewPadding;b.eq(0).hasClass(d.prefix+"-container")&&(this.$container=b,b=b.children()),this._conf={panel:{$list:b,index:0,no:0,currIndex:0,currNo:0,size:0,count:0,origCount:0,changed:!1,animating:!1,minCount:f[0]+f[1]>0?5:3},touch:{holdPos:[0,0],destPos:[0,0],distance:0,direction:null,lastPos:0,holding:!1},customEvent:{flick:!0,restore:!1,restoreCall:!1},origPanelStyle:{wrapper:{className:this.$wrapper.attr("class")||null,style:this.$wrapper.attr("style")||null},list:b.map(function(b,c){return{className:a(c).attr("class")||null,style:a(c).attr("style")||null}})},inputEvent:!1,useLayerHack:d.hwAccelerable&&!h,dirData:[],indexToMove:0,eventPrefix:c||"",$dummyAnchor:null},a([["LEFT","RIGHT"],["UP","DOWN"]][+!d.horizontal]).each(a.proxy(function(a,b){this._conf.dirData.push(e["DIRECTION_"+b])},this))},_build:function(){var a,b=this._conf.panel,c=this.options,d=b.$list,f=c.previewPadding.concat(),g=c.prefix,h=c.horizontal,i=b.count=b.origCount=d.length,j=c.bounce;this._setPadding(f,!0);var k=this._getDataByDirection([b.size,"100%"]);a="position:relative;z-index:2000;width:100%;height:100%;"+(h?"":"top:0;"),this.$container?this.$container.attr("style",a):this.$container=d.wrapAll("
").parent(),d.addClass(g+"-panel").css({position:"absolute",width:k[0],height:k[1],boxSizing:"border-box",top:0,left:0}),this._addClonePanels()&&(i=b.count=(b.$list=this.$container.children()).length),this._mcInst=new e({min:[0,0],max:this._getDataByDirection([b.size*(i-1),0]),margin:0,circular:!1,easing:c.panelEffect,deceleration:c.deceleration,bounce:this._getDataByDirection([0,j[1],0,j[0]])}),this._setDefaultPanel(c.defaultIndex)},_setPadding:function(b,c){var d=this.options.horizontal,e=this._conf.panel,f=b[0]+b[1],g={};(f||!c)&&(g.padding=(d?"0 "+b.reverse().join("px 0 "):b.join("px 0 "))+"px"),c&&(g.overflow="hidden",g.boxSizing="border-box"),!a.isEmptyObject(g)&&this.$wrapper.css(g),e.size=this.$wrapper[d?"width":"height"]()},_addClonePanels:function(){var a,b=this._conf.panel,c=b.origCount,d=b.minCount-c,e=b.$list;if(this.options.circular&&c0&&e>=a&&this._movePanelPosition(a,!0),c=this._getBasePositionIndex(),this._movePanelPosition(c,!1),this._setPanelNo({no:a,currNo:a})):a>0&&e>=a&&(this._setPanelNo({index:a,no:a,currIndex:a,currNo:a}),b=[-(d.size*a),0],this._setTranslate(b),this._setMovableCoord("setTo",[Math.abs(b[0]),Math.abs(b[1])],!0,0))},_arrangePanels:function(a,b){var c,d=this._conf,e=d.panel,f=d.touch,g=d.dirData;this.options.circular&&(d.customEvent.flick=!1,a&&(b&&(f.direction=g[+!Boolean(b>0)]),this._arrangePanelPosition(f.direction,b)),c=this._getBasePositionIndex(),this._setPanelNo({index:c,currIndex:c}),d.customEvent.flick=!!this._setMovableCoord("setTo",[e.size*e.index,0],!0,0)),this._applyPanelsPos()},_applyPanelsPos:function(){this._conf.panel.$list.each(a.proxy(this._applyPanelsCss,this))},_setMoveStyle:function(){return g?function(a,c){a.css("transform",b.translate(c[0],c[1],this._conf.useLayerHack))}:function(a,b){a.css({left:b[0],top:b[1]})}}(),_applyPanelsCss:function(){var b=this._conf,c="__dummy_anchor";i?(b.$dummyAnchor=a("."+c),!b.$dummyAnchor.length&&this.$wrapper.append(b.$dummyAnchor=a("")),this._applyPanelsCss=function(b,c){var d=this._getDataByDirection([this._conf.panel.size*b+"px",0]);a(c).css({left:d[0],top:d[1]})}):this._applyPanelsCss=function(b,c){var d=this._getDataByDirection([g?100*b+"%":this._conf.panel.size*b+"px",0]);this._setMoveStyle(a(c),d)}},_adjustContainerCss:function(a,c){var d,e=this._conf,f=e.panel,g=this.options,h=g.horizontal,j=g.previewPadding[0],k=this.$container;i&&(c||(c=[-f.size*f.index,0]),"start"===a?(k=k[0].style,d=parseInt(k[h?"left":"top"],10),h?d&&(k.left=0):d!==j&&(k.top=j+"px"),this._setTranslate([-c[+!g.horizontal],0])):"end"===a&&(!h&&(c[0]+=j),c=this._getCoordsValue(c),k.css({left:c.x,top:c.y,transform:b.translate(0,0,e.useLayerHack)}),e.$dummyAnchor[0].focus()))},_setMovableCoord:function(a,b,c,d){return c&&(b=this._getDataByDirection(b)),this._mcInst[a](b[0],b[1],d)},_setHint:function(){var a="transform";this.$container.css("willChange",a),this._conf.panel.$list.css("willChange",a)},_getDataByDirection:function(a){return a=a.concat(),!this.options.horizontal&&a.reverse(),a},_arrangePanelPosition:function(a,b){var c=a===this._conf.dirData[0];this._movePanelPosition(Math.abs(b||1),c)},_getBasePositionIndex:function(){return Math.floor(this._conf.panel.count/2-.1)},_bindEvents:function(b){var c=this.options,d=this.$wrapper,f=this._mcInst;b?f.bind(d,{scale:this._getDataByDirection([-1,0]),direction:e["DIRECTION_"+(c.horizontal?"HORIZONTAL":"VERTICAL")],interruptable:!1,inputType:c.inputType}).on({hold:a.proxy(this._holdHandler,this),change:a.proxy(this._changeHandler,this),release:a.proxy(this._releaseHandler,this),animationStart:a.proxy(this._animationStartHandler,this),animationEnd:a.proxy(this._animationEndHandler,this)}):f.unbind(d).off(),this._conf.inputEvent=!!b},_holdHandler:function(a){var b=this._conf;b.touch.holdPos=a.pos,b.touch.holding=!0,b.panel.changed=!1,this._adjustContainerCss("start",a.pos)},_changeHandler:function(b){var c,d,e=this._conf,g=e.touch,h=+!this.options.horizontal,i=b.pos[h],j=g.holdPos[h],k=null;this._setPointerEvents(b),b.hammerEvent?(c=b.hammerEvent.direction,d=b.hammerEvent[this.options.horizontal?"deltaX":"deltaY"],~a.inArray(c,e.dirData)||(c=e.dirData[+(Math.abs(g.lastPos)<=d)]),g.lastPos=d):g.lastPos=null,e.customEvent.flick&&(k=this._triggerEvent(f.flick,{pos:b.pos,holding:b.holding,direction:c||g.direction,distance:i-(j||(g.holdPos[h]=i))})),(k||null===k)&&this._setTranslate([-i,0])},_releaseHandler:function(a){var b=this._conf.touch,c=a.destPos,d=+!this.options.horizontal,e=b.holdPos[d],f=this._conf.panel.size;b.distance=a.depaPos[d]-b.holdPos[d],b.direction=this._conf.dirData[+!Boolean(b.holdPos[d]=0?a.currIndex:a.index-b,d=a.currNo>=0?a.currNo:a.no-b;this._setPanelNo({index:c,no:d})},_setPanelNo:function(b){var c=this._conf.panel,d=c.origCount-1,e=this._getNumByDirection();a.isPlainObject(b)?a.each(b,function(a,b){c[a]=b}):(c.currIndex=c.index,c.currNo=c.no,c.index+=e,c.no+=e),c.no>d?c.no=0:c.no<0&&(c.no=d)},_setPointerEvents:function(a){var b,c=this.$container.css("pointerEvents");a&&a.holding&&a.hammerEvent&&a.hammerEvent.preventSystemEvent&&"none"!==c?b="none":a||"auto"===c||(b="auto"),b&&this.$container.css("pointerEvents",b)},_getCoordsValue:function(a){return a=this._getDataByDirection(a),{x:this._getUnitValue(a[0]),y:this._getUnitValue(a[1])}},_setTranslate:function(a){a=this._getCoordsValue(a),this._setMoveStyle(this.$container,[a.x,a.y])},_getUnitValue:function(a){var b=/(?:[a-z]{2,}|%)$/;return(parseInt(a,10)||0)+(String(a).match(b)||"px")},_isMovable:function(){var a,b,c=this.options,d=this._mcInst,e=Math.abs(this._conf.touch.distance)>=c.threshold;return!c.circular&&e&&(a=this._getDataByDirection(d.options.max)[0],b=this._getDataByDirection(d.get())[0],0>b||b>a)?!1:e},_triggerEvent:function(b,c){var d=this._conf,e=d.panel;return b===f.flickEnd&&(e.currNo=e.no,e.currIndex=e.index),this.trigger(d.eventPrefix+b,a.extend({eventType:b,index:e.currIndex,no:e.currNo,direction:d.touch.direction},c))},_getElement:function(b,c,d){var e,f,g,h=this._conf.panel,i=this.options.circular,j=h.currIndex,k=b===this._conf.dirData[0],l=null;return d?(e=h.count,f=j):(e=h.origCount,f=h.currNo),g=f,k?e-1>f?f++:i&&(f=0):f>0?f--:i&&(f=e-1),g!==f&&(l=c?a(h.$list[k?j+1:j-1]):f),l},_setValueToMove:function(a){var b=this._conf;b.touch.distance=this.options.threshold+1,b.touch.direction=b.dirData[+!a]},_getNumValue:function(a,b){return isNaN(a=parseInt(a,10))?b:a},getIndex:function(a){return this._conf.panel[a?"currIndex":"currNo"]},getElement:function(){var b=this._conf.panel;return a(b.$list[b.currIndex])},getNextElement:function(){return this._getElement(this._conf.dirData[0],!0)},getNextIndex:function(a){return this._getElement(this._conf.dirData[0],!1,a)},getAllElements:function(){return this._conf.panel.$list},getPrevElement:function(){return this._getElement(this._conf.dirData[1],!0)},getPrevIndex:function(a){return this._getElement(this._conf.dirData[1],!1,a)},getTotalCount:function(a){return this._conf.panel[a?"count":"origCount"]},isPlaying:function(){return this._conf.panel.animating},_movePanel:function(a,b){var c=this._conf,d=c.panel,e=this.options;return d.animating||c.touch.holding?void 0:(this._setValueToMove(a),(e.circular||null!=this[a?"getNextIndex":"getPrevIndex"]())&&this._movePanelByPhase("setBy",[d.size*(a?1:-1),0],b),this)},_movePanelByPhase:function(a,b,c){c=this._getNumValue(c,this.options.duration),this._setPhaseValue("start")!==!1&&(this._setMovableCoord(a,b,!0,c),!c&&this._setPhaseValue("end"))},next:function(a){return this._movePanel(!0,a)},prev:function(a){return this._movePanel(!1,a)},moveTo:function(a,b){var c,d,e=this._conf,f=e.panel,g=this.options.circular,h=f.index;return a=this._getNumValue(a,-1),0>a||a>=f.origCount||a===f.no||f.animating||e.touch.holding?this:(g?(c=a-f.no,d=c>0,Math.abs(c)>(d?f.count-(h+1):h)&&(c+=(d?-1:1)*f.count),this._setPanelNo({no:a})):(c=a-h,this._setPanelNo({index:a,no:a})),this._conf.indexToMove=c,this._setValueToMove(d),this._movePanelByPhase(g?"setBy":"setTo",[f.size*(g?c:a),0],b),this)},_checkPadding:function(){var b=this.options,c=b.previewPadding.concat(),d=this.$wrapper.css("padding").split(" ");b.horizontal&&d.reverse(),d=2===d.length?[d[0],d[0]]:[d[0],d[2]],d=a.map(d,function(a){return parseInt(a,10)}),(2===c.length&&c[0]!==d[0]||c[1]!==d[1])&&this._setPadding(c)},resize:function(){var a,b,c=this._conf,d=this.options,e=c.panel,f=d.horizontal;return~~d.previewPadding.join("")?(this._checkPadding(),a=e.size):f&&(a=e.size=this.$wrapper.width()),b=this._getDataByDirection([a*(e.count-1),0]),f&&this.$container.width(b[0]+a),e.$list.css(f?"width":"height",a),this._mcInst.options.max=b,this._setMovableCoord("setTo",[a*e.index,0],!0,0),i&&(this._applyPanelsPos(),this._adjustContainerCss("end")),this},restore:function(a){var b,c=this._conf,d=c.panel,e=this._getDataByDirection(this._mcInst.get());return e[0]!==d.currIndex*d.size?(c.customEvent.restoreCall=!0,a=this._getNumValue(a,this.options.duration),this._revertPanelNo(),b=this._getDataByDirection([d.size*d.index,0]),this._triggerBeforeRestore({depaPos:e,destPos:b}),this._setMovableCoord("setTo",b,!0,a),a||(this._adjustContainerCss("end"),this._triggerRestore())):d.changed&&(this._revertPanelNo(),c.touch.distance=c.indexToMove=0),this},_setInputEvent:function(a){var b=this._conf.inputEvent;return a^b&&this._bindEvents(a),this},enableInput:function(){return this._setInputEvent(!0)},disableInput:function(){return this._setInputEvent()},destroy:function(){var b=this._conf,c=b.origPanelStyle,d=c.wrapper,e=c.list;this.$wrapper.attr("class",d.className).attr("style",d.style),this.$container.children().unwrap().each(function(b,c){var d=a(c);return b>e.length-1?!!d.remove():void d.attr("class",e[b].className).attr("style",e[b].style)}),this.disableInput(),this.off();for(var f in this)this[f]=null}})}); \ No newline at end of file diff --git a/dist/pkgd/infiniteGrid.pkgd.min.js b/dist/pkgd/infiniteGrid.pkgd.min.js new file mode 100644 index 00000000..45414b01 --- /dev/null +++ b/dist/pkgd/infiniteGrid.pkgd.min.js @@ -0,0 +1,26 @@ +/** +* Copyright (c) 2015 NAVER corp. +* egjs projects are licensed under the MIT license +* https://naver.github.io/egjs/license.txt +* +* egjs JavaScript library +* http://naver.github.io/egjs +* +* @version 1.3.0 +* @SHA-1 13e6ef5 (1.3.0-rc) +* +* For custom build use egjs-cli +* https://github.com/naver/egjs-cli +*/ +/** +* All-in-one packaged file for ease use of 'eg.infiniteGrid' with below dependencies. +* NOTE: This is not an official distribution file and is only for user convenience. +* +* src/module.js +* src/eg.js +* src/class.js +* src/component.js +* src/plugin/persist.js +* src/infiniteGrid.js +*/ +!function(a,b,c){function d(a){return a>2?a+1+"th":m[a]}function e(a,b){var c;for(c in b)a=a.replace(new RegExp("{{"+c+"}}","gi"),b[c]);return a}function f(a,b){for(var f,g,h,i,j,m,n,o,p=0,q=b.length,r=[],s=[],t=c.require;q>p;p++)g=b[p],h={index:d(p),name:g,componentName:a},i="string"==typeof b[p],j=void 0===b[p],m=i&&(f=k[b[p]]),n=i&&f&&!c[b[p]],o=n&&t&&t.specified&&t.specified(b[p]),i||j?o&&t.defined(b[p])?(g=t(b[p]),s.push(g)):!o||t.defined(b[p])?n&&t&&t.specified&&!t.specified(b[p])?(h.url=f.url,r.push(e(l[1],h))):!n||t?m&&c[b[p]]?(g=c[b[p]],s.push(g)):!i||f?void 0!==b[p]||r.push(e(l[4],h)):r.push(e(l[3],h)):(h.url=f.url,r.push(e(l[2],h))):(h.url=f.url,r.push(e(l[0],h))):s.push(g);return[s,r]}function g(a){return a.charAt(0).toUpperCase()+a.slice(1)}function h(a){var c,d,e,f=g(a);if(!(i[f]&&i[f].prototype&&i[f].prototype._events))return!1;if(j.fn[a])throw new Error("The name '"+f+"' has already been used and registered as plugin. Try with different one.");j.fn[a]=function(c){var d,e;return"string"==typeof c?(d=this.data(b+"-"+a),"instance"===c?d:(e=d[c].apply(d,Array.prototype.slice.call(arguments,1)),e===d?this:e)):((void 0===c||j.isPlainObject(c))&&this.data(b+"-"+a,new i[f](this,c||{},a+":")),this)},e={trigger:"trigger",add:"on",remove:"off"},c=i[f].prototype._events();for(var h in c){d=j.event.special[a+":"+c[h]]={},d.setup=function(){return!0};for(var k in e)d[k]=function(c){return function(d,e){return j(this).data(b+"-"+a)[c](d.type,"trigger"===c?e:d.handler),!1}}(e[k])}}var i;c[b]||(c[b]={}),i=c[b];var j=c[a],k={jQuery:{url:"http://jquery.com/"},Hammer:{url:"http://hammerjs.github.io/"}},l=["[egjs] The {{name}} library must be loaded before {{componentName}}.",'[egjs] For AMD environment (like RequireJS), "{{name}}" must be declared, which is required by {{componentName}}.',"[egjs] The {{index}} argument of {{componentName}} is missing.\r\nDownload {{name}} from [{{url}}].","[egjs] The {{name}} parameter of {{componentName}} is not valid.\r\nPlease check and try again.","[egjs] The {{index}} argument of {{componentName}} is undefined.\r\nPlease check and try again."],m=["1st","2nd","3rd"],n=function(a){(n=c.console&&c.console.warn?function(a){c.console.warn(a)}:function(){})(a)};i.module||(i.module=function(a,b,d){var e=f(a,b);e[1].length?n(e[1].join("\r\n")):(d.apply(c,e[0]),h(a))})}("jQuery","eg",window),eg.module("eg",["jQuery",eg,window,eg.Agent],function(a,b,c,d){function e(a,b,c,d){var e=a.hook[b];return e&&(d=e.apply(a,c)),a[b]=function(){var e=a.hook[b];return e?e.apply(a,c):d},d}var f=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,g=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(f&&!g){var h={},i=f;f=function(a){function b(){h[c]&&a()}var c=i(b);return h[c]=!0,c},g=function(a){delete h[a]}}else f&&g||(f=function(a){return c.setTimeout(a,16)},g=c.clearTimeout);b.VERSION="1.3.0",b.hook={},b.agent=function(){var a=d.create(c.navigator.userAgent);return e(this,"agent",[a],a)},b.translate=function(a,b,c){return c=c||!1,"translate"+(c?"3d(":"(")+a+","+b+(c?",0)":")")},b.isHWAccelerable=function(){var a,c=!1,f=b.agent(),g=f.os.version,h=f.browser.name,i=f.browser.version;return-1!==h.indexOf("chrome")?c=i>="25":/ie|edge|firefox|safari|inapp/.test(h)?c=!0:-1!==f.os.name.indexOf("android")&&(a=(d.ua.match(/\(.*\)/)||[null])[0],c=g>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||g>="4.0.3"&&/SHW-|SHV-|GT-|SCH-|SGH-|SPH-|LG-F160|LG-F100|LG-F180|LG-F200|EK-|IM-A|LG-F240|LG-F260/.test(a)&&!/SHW-M420|SHW-M200|GT-S7562/.test(a)),e(this,"isHWAccelerable",[c,f],c)},b.isTransitional=function(){var a=!1,c=b.agent(),d=c.browser.name;if(/chrome|firefox|sbrowser/.test(d))a=!0;else switch(c.os.name){case"ios":a=/safari|inapp/.test(d)&&parseInt(c.os.version,10)<6;break;case"window":a=/safari/.test(d)||/ie/.test(d)&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/safari/.test(d)}return e(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return e(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return f(a)},b.cancelAnimationFrame=function(a){g(a)},a.extend(a.easing,{easeOutCubic:function(a){return 1-Math.pow(1-a,3)}})}),eg.module("class",[eg],function(a){a.Class=function(a){var b=function(){"function"==typeof a.construct&&a.construct.apply(this,arguments)};return b.prototype=a,b.prototype.instance=function(){return this},b.prototype.constructor=b,b},a.Class.extend=function(a,b){var c=function(){a.apply(this,arguments),"function"==typeof b.construct&&b.construct.apply(this,arguments)},d=function(){};d.prototype=a.prototype;var e=new d;for(var f in b)e[f]=b[f];return e.constructor=c,c.prototype=e,c}}),eg.module("component",[eg],function(a){a.Component=a.Class({construct:function(){this.eventHandler={},this.options={}},option:function(a,b){if(arguments.length>=2)return this.options[a]=b,this;if("string"==typeof a)return this.options[a];if(0===arguments.length)return this.options;for(var c in a)this.options[c]=a[c];return this},trigger:function(a,b){b=b||{};var c=this.eventHandler[a]||[],d=c.length>0;if(!d)return!0;c=c.concat(),b.eventType=a;var e,f,g,h=!1,i=[b];for(b.stop=function(){h=!0},(f=arguments.length)>2&&(i=i.concat(Array.prototype.slice.call(arguments,2,f))),e=0;g=c[e];e++)g.apply(this,i);return!h},hasOn:function(a){return!!this.eventHandler[a]},on:function(a,b){if("object"==typeof a&&"undefined"==typeof b){var c,d=a;for(c in d)this.on(c,d[c]);return this}if("string"==typeof a&&"function"==typeof b){var e=this.eventHandler[a];"undefined"==typeof e&&(e=this.eventHandler[a]=[]),e.push(b)}return this},off:function(a,b){if(0===arguments.length)return this.eventHandler={},this;if("undefined"==typeof b){if("string"==typeof a)return this.eventHandler[a]=void 0,this;var c=a;for(var d in c)this.off(d,c[d]);return this}var e=this.eventHandler[a];if(e){var f,g;for(f=0,g;g=e[f];f++)if(g===b){e=e.splice(f,1);break}}return this}})}),eg.module("persist",["jQuery",window,document],function(a,b,c){function d(a){if(a){var b="__tmp__"+p;try{return a.setItem(b,p),a.getItem(b)===p}catch(c){return!1}}}function e(a){s=s||a.originalEvent&&a.originalEvent.persisted,!s&&t?r.trigger("persist"):f()}function f(){j(null)}function g(){var c,d=v?v.getItem(b.location.href+p):m.state;if(null===d)return{};var e,f="string"==typeof d&&d.length>0&&"null"!==d;try{if(c=o.parse(d),e=!("object"!==a.type(c)||c instanceof Array),!f||!e)throw new Error}catch(g){h(),c={}}return c}function h(){console.warn("window.history or session/localStorage has no valid format data to be handled in persist.")}function i(a){var b=g()[a];return("null"===b||"undefined"==typeof b)&&(b=null),b}function j(a){if(v)a?v.setItem(b.location.href+p,o.stringify(a)):v.removeItem(b.location.href+p);else try{m.replaceState(null===a?null:o.stringify(a),c.title,b.location.href)}catch(d){console.warn(d.message)}a?r.attr(p,!0):r.attr(p,null)}function k(a,b){var c=g();c[a]=b,j(c)}var l=b.performance,m=b.history,n=function(){var a=b.navigator.userAgent,c=a?a.match(/Android\s([^\;]*)/i):null;return!(/iPhone|iPad/.test(a)||(c?parseFloat(c.pop())<4.4:!0))}(),o=b.JSON,p="___persist___",q="KEY"+p,r=a(b),s=r.attr(p)===!0,t=l&&l.navigation&&l.navigation.type===(l.navigation.TYPE_BACK_FORWARD||2),u="replaceState"in m&&"state"in m,v=function(){return d(b.sessionStorage)?b.sessionStorage:d(b.localStorage)?b.localStorage:void 0}();return u||v?o?(a.persist=function(a){var b,c;return"string"==typeof a?(b=a,c=2===arguments.length?arguments[1]:null):(b=q,c=1===arguments.length?a:null),c&&k(b,c),i(b)},a.persist.isNeeded=function(){return n},!t&&f(),a.event.special.persist={setup:function(){r.on("pageshow",e)},teardown:function(){r.off("pageshow",e)},trigger:function(a){a.state=i(q)}},{isBackForwardNavigated:t,onPageshow:e,reset:f,getState:g,setState:j,GLOBALKEY:q}):void console.warn("The JSON object is not supported in your browser.\r\nFor work around use polyfill which can be found at:\r\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#Polyfill"):void 0}),eg.module("infiniteGrid",["jQuery",eg,window,document],function(a,b,c,d){var e={layoutComplete:"layoutComplete",append:"append",prepend:"prepend"};b.InfiniteGrid=b.Class.extend(b.Component,{_events:function(){return e},construct:function(b,e,f){this.options=a.extend({isEqualSize:!1,defaultGroupKey:null,count:30,threshold:300},e),this.$el=b instanceof a?b:a(b),this.el=this.$el.get(0),this.el.style.position="relative",this._prefix=f||"",this._isIos=/iPhone|iPad/.test(c.navigator.userAgent),this._isIE10lower=!!(d.documentMode&&d.documentMode<10),this._appendCols=this._prependCols=[],this.$view=a(c),this._reset(),this._refreshViewport(),this.el.children.length>0&&(this.items=this._itemize(a.makeArray(this.el.children),this.options.defaultGroupKey,!0),this.layout(this.items,!0)),this._onScroll=a.proxy(this._onScroll,this),this._onResize=a.proxy(this._onResize,this),this.$view.on("scroll",this._onScroll).on("resize",this._onResize)},_getScrollTop:function(){return d.body.scrollTop||d.documentElement.scrollTop},_onScroll:function(){if(!this.isProcessing()){var b=this._getScrollTop(),c=this._prevScrollTop;if(!(this._isIos&&0===b||c===b)){var d,f;if(b>c){if(a.isEmptyObject(this._bottomElement)&&(this._bottomElement=this.getBottomElement(),null==this._bottomElement))return;d=this._bottomElement,f=d.getBoundingClientRect(),f.top<=this._clientHeight+this.options.threshold&&this.trigger(this._prefix+e.append,{scrollTop:b})}else if(this.isRecycling()&&this._removedContent>0){if(a.isEmptyObject(this._topElement)&&(this._topElement=this.getTopElement(),null==this._topElement))return;if(d=this._topElement,f=d.getBoundingClientRect(),f.bottom>=-this.options.threshold){var g=this.fit();g>0&&(b-=g,this.$view.scrollTop(b)),this.trigger(this._prefix+e.prepend,{scrollTop:b})}}this._prevScrollTop=b}}},_onResize:function(){this._resizeTimeout&&clearTimeout(this._resizeTimeout);var a=this;this._resizeTimeout=setTimeout(function(){a._refreshViewport(),a.$el.innerWidth()!==a._containerWidth&&a.layout(a.items,!0),a._resizeTimeout=null},100)},_refreshViewport:function(){this._clientHeight=this.$view.height()},getStatus:function(){var b,c={};for(b in this)!this.hasOwnProperty(b)||!/^_/.test(b)||"function"==typeof this[b]||this[b]instanceof Element||(c[b]=this[b]);return{prop:c,options:a.extend({},this.options),items:a.map(this.items,function(b){var c=a.extend({},b);return delete c.el,c}),html:this.el.innerHTML,cssText:this.el.style.cssText}},setStatus:function(b){return b&&b.cssText&&b.html&&b.prop&&b.items?(this.el.style.cssText=b.cssText,this.el.innerHTML=b.html,a.extend(this,b.prop),this._topElement=this._bottomElement=null,this.items=a.map(this.el.children,function(a,c){return b.items[c].el=a,b.items[c]}),this):this},isProcessing:function(){return this._isProcessing},isRecycling:function(){return this.options.count>0&&this._isRecycling},getGroupKeys:function(){return a.map(this.items,function(a){return a.groupKey})},layout:function(b,c){return b=b||this.items,c="undefined"==typeof c?!0:c,this._isProcessing=!0,c&&(b=a.map(b,function(a){return a.isAppend=!0,a})),this._waitResource(b,c),this},_layoutItems:function(b){var c=this;a.each(a.map(b,function(a){return a.position=c._getItemLayoutPosition(a),a}),function(a,b){if(b.el){var c=b.el.style;c.left=b.position.x+"px",c.top=b.position.y+"px"}})},append:function(b,c){return this._isProcessing||0===b.length?void 0:(b=a(b),this._isProcessing=!0,this.isRecycling()||(this._isRecycling=this.items.length+b.length>=this.options.count),this._insert(b,c,!0),b.length)},prepend:function(b,c){return this.isRecycling()&&0!==this._removedContent&&!this._isProcessing&&0!==b.length?(b=a(b),this._isProcessing=!0,this._fit(),b.length>this._removedContent&&(b=b.slice(0,this._removedContent)),this._insert(b,c,!1),b.length):void 0},clear:function(){return this.el.innerHTML="",this.el.style.height="",this._reset(),this},_getTopItem:function(){var b=null,c=1/0;return a.each(this._getColItems(!1),function(a,d){d&&d.position.yc&&(c=d.position.y+d.size.height,b=d)}),b},getBottomElement:function(){var a=this._getBottomItem();return a&&a.el},_postLayout:function(a){if(this._isProcessing&&!(a.length<=0)){var b=this._getContainerSize();this.el.style.width=b.width+"px",this.el.style.height=b.height+"px",this._topElement=this.getTopElement(),this._bottomElement=this.getBottomElement();var c=0,d=a[0].isAppend;d||(this._isFitted=!1,this._fit(!0),c=a.length>=this.items.length?0:this.items[a.length].position.y,c>0&&(this._prevScrollTop=this._getScrollTop()+c,this.$view.scrollTop(this._prevScrollTop))),this._isProcessing=!1,this.trigger(this._prefix+e.layoutComplete,{target:a.concat(),isAppend:d,distance:c,croppedCount:this._removedContent})}},_insert:function(b,c,d){if(0!==b.length){var e=b.toArray(),f=a(e),g=-this._clientHeight+"px";a.each(e,function(a,b){b.style.position="absolute",b.style.top=g});var h=this._itemize(e,c,d);d?this.items=this.items.concat(h):(this.items=h.concat(this.items),h=h.reverse()),this.isRecycling()&&this._adjustRange(d,f),this.$el[d?"append":"prepend"](f),this.layout(h,!1)}},_waitResource:function(b,c){var d=this._checkImageLoaded(),e=this,f=function(){e._isProcessing&&((c||!e._appendCols.length)&&(a.each(b,function(a,b){b.el.style.position="absolute"}),e._measureColumns()),e._layoutItems(b),e._postLayout(b))};d.length>0?this._waitImageLoaded(d,f):setTimeout(function(){f&&f()},0)},_adjustRange:function(b,c){var d,e,f=this.items.length-this.options.count;0>=f||(e=this._getDelimiterIndex(b,f))<0||(b?(d=this.items.splice(0,e),this._isFitted=!1):d=this.items.splice(e,this.items.length-e),a.each(d,function(a,b){e=c.index(b.el),-1!==e?c.splice(e,1):b.el.parentNode.removeChild(b.el)}),this._removedContent+=b?d.length:-d.length)},_getDelimiterIndex:function(a,b){var c,d=this.items.length,e=0,f=a?b-1:d-b,g=f+(a?1:-1),h=this.items[f].groupKey;if(null!=h&&h===this.items[g].groupKey)if(a){for(c=f;c>0&&h===this.items[c].groupKey;c--);e=0===c?-1:c+1}else{for(c=f;d>c&&h===this.items[c].groupKey;c++);e=c===d?-1:c}else e=a?g:f;return e},_fit:function(b){if(this.options.count<=0)return this._fit=function(){return!1},this._isFitted=!0,!1;if(this._isFitted)return!1;var c=this._updateCols();a.each(this.items,function(a,d){d.position.y-=c,b&&(d.el.style.top=d.position.y+"px")}),this._updateCols(!0);var d=this._getContainerSize().height;return b&&(this.el.style.height=d+"px"),this._isFitted=!0,!0},fit:function(){var a=this._getTopItem(),b=a?a.position.y:0;return this._fit(!0),b},_reset:function(){this._isProcessing=!1,this._topElement=null,this._bottomElement=null,this._isFitted=!0,this._isRecycling=!1,this._removedContent=0,this._prevScrollTop=0,this._equalItemSize=0,this._resizeTimeout=null,this._resetCols(this._appendCols.length||0),this.items=[]},_checkImageLoaded:function(){return this.$el.find("img").filter(function(b,c){return c.nodeType&&-1!==a.inArray(c.nodeType,[1,9,11])?!c.complete:void 0}).toArray()},_waitImageLoaded:function(b,c){var d,e=b.length,f=function(b){e--,a(b.target).off("load error"),0>=e&&c&&c()},g=this;a.each(b,function(b,c){if(d=a(c),g._isIE10lower){var e=c.getAttribute("src");c.setAttribute("src",""),c.setAttribute("src",e)}d.on("load error",f)})},_measureColumns:function(){this.el.style.width=null,this._containerWidth=this.$el.innerWidth(),this._columnWidth=this._getColumnWidth()||this._containerWidth;var a=this._containerWidth/this._columnWidth,b=this._columnWidth-this._containerWidth%this._columnWidth;a=Math.max(Math[b&&1>=b?"round":"floor"](a),1),this._resetCols(a||0)},_resetCols:function(a){a="undefined"==typeof a?0:a;for(var b=[];a--;)b.push(0);this._appendCols=b.concat(),this._prependCols=b.concat()},_getContainerSize:function(){return{height:Math.max.apply(Math,this._appendCols),width:this._containerWidth}},_getColumnWidth:function(){var b=this.items[0]&&this.items[0].el,c=0;if(b){var d=a(b);c=d.innerWidth(),this.options.isEqualSize&&(this._equalItemSize={width:c,height:d.innerHeight()})}return c},_updateCols:function(a){for(var b,c=a?this._appendCols:this._prependCols,d=this._getColItems(a),e=this._isFitted||a?0:this._getMinY(d),f=0,g=c.length;g>f;f++)c[f]=(b=d[f])?b.position.y+(a?b.size.height:-e):0;return e},_getMinY:function(b){return Math.min.apply(Math,a.map(b,function(a){return a?a.position.y:0}))},_getColIdx:function(a){return parseInt(a.position.x/parseInt(this._columnWidth,10),10)},_getColItems:function(a){for(var b,c,d=this._appendCols.length,e=new Array(d),f=0,g=a?this.items.length-1:0;b=this.items[g];){if(c=this._getColIdx(b),!e[c]&&(e[c]=b,++f===d))return e;g+=a?-1:1}return e},_itemize:function(b,c,d){return a.map(b,function(a){return{el:a,position:{x:0,y:0},isAppend:"undefined"==typeof d?!0:d,groupKey:"undefined"==typeof c?null:c}})},_getItemLayoutPosition:function(b){if(b.el){var c=a(b.el);b.size=this._equalItemSize||{width:c.innerWidth(),height:c.innerHeight()};var d,e=b.isAppend,f=e?this._appendCols:this._prependCols,g=Math[e?"min":"max"].apply(Math,f);if(e)d=a.inArray(g,f);else for(var h=f.length;h-->=0;)if(f[h]===g){d=h;break}return f[d]=g+(e?b.size.height:-b.size.height),{x:this._columnWidth*d,y:e?g:g-b.size.height}}},destroy:function(){this.off(),this.$view.off("resize",this._onResize).off("scroll",this._onScroll),this._reset()}})}); \ No newline at end of file diff --git a/doc/class.js.html b/doc/class.js.html new file mode 100644 index 00000000..883d7ba1 --- /dev/null +++ b/doc/class.js.html @@ -0,0 +1,652 @@ + + + + + Source: class.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Source: class.js

+ + + + +
+
+
/**
+* Copyright (c) 2015 NAVER Corp.
+* egjs projects are licensed under the MIT license
+*/
+
+eg.module("class", [eg], function(ns) {
+	"use strict";
+
+	/**
+	 *
+	 * A module used to implement an application in object-oriented programming style
+	 * @group egjs
+	 * @ko 애플리케이션을 객체지향 프로그래밍 방식으로 구현할 때 사용하는 모듈
+	 * @class
+	 * @name eg.Class
+	 *
+	 * @support {"ie": "7+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
+	 * @param {Object} def definition. Follow the rules under <a href="https://en.wikipedia.org/wiki/Literal_(computer_programming)">Literals of objects</a>. Note that "construct" is a key reserved as a constructor function. <ko>클래스를 정의하는 부분. <a href="https://en.wikipedia.org/wiki/Literal_(computer_programming)">객체 리터럴 규칙</a>을 따른다. 단, 'construct'는 생성자 함수로 예약된 키다</ko>
+	 * @param {Function} [def.construct] The constructor of the class <ko>클래스 생성자 함수 (Optional)</ko>
+	 *
+	 * @example
+	 	var Some = eg.Class({
+	 		//Class initialize
+			"construct" : function(val){
+				this.val = val;
+			},
+			"sumVal" : function(val) {
+				return this.val + val;
+			}
+	 	});
+
+	 	var some = new Some(5);
+	 	some.sumVal(5);//10
+	 */
+	ns.Class = function(def) {
+		var typeClass = function typeClass() {
+			if (typeof def.construct === "function") {
+				def.construct.apply(this, arguments);
+			}
+		};
+
+		typeClass.prototype = def;
+
+		/**
+		 * Returns an instance of a class itself.
+		 * @ko 클래스 자신의 인스턴스를 반환한다.
+		 * @method eg.Class#instance
+		 * @return {eg.Class} An instance of a class itself<ko>클래스 자신의 인스턴스</ko>
+		 */
+		typeClass.prototype.instance = function() {
+			return this;
+		};
+
+		typeClass.prototype.constructor = typeClass;
+		return typeClass;
+	};
+	/**
+	 * Extends a class.
+	 * @ko 클래스를 상속한다.
+	 * @static
+	 * @method eg.Class.extend
+	 * @param {eg.Class} oSuperClass Superclass <ko>상속하려는 클래스</ko>
+	 * @param {Object} def Class definition. Follow the rules under <a href="https://en.wikipedia.org/wiki/Literal_(computer_programming)">Literals of objects</a>. Note that "construct" is a key reserved as a constructor function. <ko>클래스를 정의하는 부분. <a href="https://en.wikipedia.org/wiki/Literal_(computer_programming)">객체 리터럴 규칙</a>을 따른다. 단, 'construct'는 생성자 함수로 예약된 키다.</ko>
+	 * @param {Function} [def.construct] The constructor of the class <ko>클래스 생성자 함수 (Optional)</ko>
+	 * @return {eg.Class} An instance of a new class <ko>새로 생성된 클래스의 인스턴스</ko>
+	 * @example
+	 	var Some = eg.Class.extend(eg.Component,{
+			"some" : function(){}
+	 	})
+	 */
+
+	ns.Class.extend = function(superClass, def) {
+		var extendClass = function extendClass() {
+			// Call a parent constructor
+			superClass.apply(this, arguments);
+
+			// Call a child constructor
+			if (typeof def.construct === "function") {
+				def.construct.apply(this, arguments);
+			}
+		};
+
+		var ExtProto = function() {};
+		ExtProto.prototype = superClass.prototype;
+
+		//extendClass.$super = oSuperClass.prototype; //'super' is supported not yet.
+
+		var extProto = new ExtProto();
+		for (var i in def) {
+			extProto[i] = def[i];
+		}
+		extProto.constructor = extendClass;
+		extendClass.prototype = extProto;
+
+		return extendClass;
+	};
+});
+
+
+ + + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:14 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/component.js.html b/doc/component.js.html new file mode 100644 index 00000000..6b763ab5 --- /dev/null +++ b/doc/component.js.html @@ -0,0 +1,777 @@ + + + + + Source: component.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Source: component.js

+ + + + +
+
+
/**
+* Copyright (c) 2015 NAVER Corp.
+* egjs projects are licensed under the MIT license
+*/
+
+eg.module("component", [eg], function(ns) {
+	"use strict";
+
+	/**
+	 * A class used to manage events and options in a component
+	 * @class
+	 * @group egjs
+	 * @name eg.Component
+	 * @ko 컴포넌트의 이벤트와 옵션을 관리할 수 있게 하는 클래스
+	 *
+	 * @support {"ie": "7+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
+	 */
+	ns.Component = ns.Class({
+		construct: function() {
+			// The reference count does not support yet.
+			// this.constructor.$count = (this.constructor.$count || 0) + 1;
+			this.eventHandler = {};
+			this.options = {};
+		},
+		/**
+		 * Sets options in a component or returns them.
+		 * @ko 컴포넌트에 옵션을 설정하거나 옵션을 반환한다
+		 * @method eg.Component#option
+		 * @param {String} key The key of the option<ko>옵션의 키</ko>
+		 * @param {Object} [value] The option value that corresponds to a given key <ko>키에 해당하는 옵션값</ko>
+		 * @return {eg.Component|Object} An instance, an option value, or an option object of a component itself.<br>- If both key and value are used to set an option, it returns an instance of a component itself.<br>- If only a key is specified for the parameter, it returns the option value corresponding to a given key.<br>- If nothing is specified, it returns an option object. <ko>컴포넌트 자신의 인스턴스나 옵션값, 옵션 객체.<br>- 키와 값으로 옵션을 설정하면 컴포넌트 자신의 인스턴스를 반환한다.<br>- 파라미터에 키만 설정하면 키에 해당하는 옵션값을 반환한다.<br>- 파라미터에 아무것도 설정하지 않으면 옵션 객체를 반환한다.</ko>
+		 * @example
+			var Some = eg.Class.extend(eg.Component);
+			var some = new Some({
+				"foo": 1,
+				"bar": 2,
+			});
+			some.option("foo"); // return 1
+			some.option("foo",3); // return some instance
+			some.option(); // return options object.
+			some.option({
+				"foo" : 10,
+				"bar" : 20,
+				"baz" : 30
+			}); // return some instance.
+		 */
+		option: function(key, value) {
+			if (arguments.length >= 2) {
+				this.options[key] = value;
+				return this;
+			}
+
+			if (typeof key === "string") {
+				return this.options[key];
+			}
+
+			if (arguments.length === 0) {
+				return this.options;
+			}
+
+			for (var i in key) {
+				this.options[i] = key[i];
+			}
+
+			return this;
+		},
+		/**
+		 * Triggers a custom event.
+		 * @ko 커스텀 이벤트를 발생시킨다
+		 * @method eg.Component#trigger
+		 * @param {String} eventName The name of the custom event to be triggered <ko>발생할 커스텀 이벤트의 이름</ko>
+		 * @param {Object} customEvent Event data to be sent when triggering a custom event <ko>커스텀 이벤트가 발생할 때 전달할 데이터</ko>
+		 * @return {Boolean} Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring. <ko>이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다.</ko>
+		 * @example
+			var Some = eg.Class.extend(eg.Component,{
+				"some": function(){
+					this.trigger("hi");// fire hi event.
+				}
+			});
+		 */
+		trigger: function(eventName, customEvent) {
+			customEvent = customEvent || {};
+			var handlerList = this.eventHandler[eventName] || [];
+			var hasHandlerList = handlerList.length > 0;
+
+			if (!hasHandlerList) {
+				return true;
+			}
+
+			// If detach method call in handler in first time then handeler list calls.
+			handlerList = handlerList.concat();
+
+			customEvent.eventType = eventName;
+
+			var isCanceled = false;
+			var arg = [customEvent];
+			var i;
+			var len;
+			var handler;
+
+			customEvent.stop = function() {
+				isCanceled = true;
+			};
+
+			if ((len = arguments.length) > 2) {
+				arg = arg.concat(Array.prototype.slice.call(arguments, 2, len));
+			}
+
+			for (i = 0; handler = handlerList[i]; i++) {
+				handler.apply(this, arg);
+			}
+
+			return !isCanceled;
+		},
+		/**
+		 * Checks whether an event has been attached to a component.
+		 * @ko 컴포넌트에 이벤트가 등록됐는지 확인한다.
+		 * @method eg.Component#hasOn
+		 * @param {String} eventName The name of the event to be attached <ko>등록 여부를 확인할 이벤트의 이름</ko>
+		 * @return {Boolean} Indicates whether the event is attached. <ko>이벤트 등록 여부</ko>
+		 * @example
+			var Some = eg.Class.extend(eg.Component,{
+				"some": function(){
+					this.hasOn("hi");// check hi event.
+				}
+			});
+		 */
+		hasOn: function(eventName) {
+			return !!this.eventHandler[eventName];
+		},
+		/**
+		 * Attaches an event to a component.
+		 * @ko 컴포넌트에 이벤트를 등록한다.
+		 * @method eg.Component#on
+		 * @param {eventName} eventName The name of the event to be attached <ko>등록할 이벤트의 이름</ko>
+		 * @param {Function} handlerToAttach The handler function of the event to be attached <ko>등록할 이벤트의 핸들러 함수</ko>
+		 * @return {eg.Component} An instance of a component itself<ko>컴포넌트 자신의 인스턴스</ko>
+		 * @example
+			var Some = eg.Class.extend(eg.Component,{
+				"hi": function(){},
+				"some": function(){
+					this.on("hi",this.hi); //attach event
+				}
+			});
+		 */
+		on: function(eventName, handlerToAttach) {
+			if (typeof eventName === "object" &&
+			typeof handlerToAttach === "undefined") {
+				var eventHash = eventName;
+				var i;
+				for (i in eventHash) {
+					this.on(i, eventHash[i]);
+				}
+				return this;
+			} else if (typeof eventName === "string" &&
+				typeof handlerToAttach === "function") {
+				var handlerList = this.eventHandler[eventName];
+
+				if (typeof handlerList === "undefined") {
+					handlerList = this.eventHandler[eventName] = [];
+				}
+
+				handlerList.push(handlerToAttach);
+			}
+
+			return this;
+		},
+		/**
+		 * Detaches an event from the component.
+		 * @ko 컴포넌트에 등록된 이벤트를 해제한다
+		 * @method eg.Component#off
+		 * @param {eventName} eventName The name of the event to be detached <ko>해제할 이벤트의 이름</ko>
+		 * @param {Function} handlerToDetach The handler function of the event to be detached <ko>해제할 이벤트의 핸들러 함수</ko>
+		 * @return {eg.Component} An instance of a component itself <ko>컴포넌트 자신의 인스턴스</ko>
+		 * @example
+			var Some = eg.Class.extend(eg.Component,{
+				"hi": function(){},
+				"some": function(){
+					this.off("hi",this.hi); //detach event
+				}
+			});
+		 */
+		off: function(eventName, handlerToDetach) {
+			// All event detach.
+			if (arguments.length === 0) {
+				this.eventHandler = {};
+				return this;
+			}
+
+			// All handler of specific event detach.
+			if (typeof handlerToDetach === "undefined") {
+				if (typeof eventName === "string") {
+					this.eventHandler[eventName] = undefined;
+					return this;
+				} else {
+					var eventHash = eventName;
+					for (var i in eventHash) {
+						this.off(i, eventHash[i]);
+					}
+					return this;
+				}
+			}
+
+			// The handler of specific event detach.
+			var handlerList = this.eventHandler[eventName];
+			if (handlerList) {
+				var k;
+				var handlerFunction;
+				for (k = 0, handlerFunction; handlerFunction = handlerList[k]; k++) {
+					if (handlerFunction === handlerToDetach) {
+						handlerList = handlerList.splice(k, 1);
+						break;
+					}
+				}
+			}
+
+			return this;
+		}
+	});
+});
+
+
+
+
+ + + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:14 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/cssPrefix.js.html b/doc/cssPrefix.js.html new file mode 100644 index 00000000..d98e99b5 --- /dev/null +++ b/doc/cssPrefix.js.html @@ -0,0 +1,636 @@ + + + + + Source: hook/cssPrefix.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Source: hook/cssPrefix.js

+ + + + +
+
+
/**
+* Copyright (c) 2015 NAVER Corp.
+* egjs projects are licensed under the MIT license
+*/
+
+eg.module("cssPrefix", ["jQuery", document], function($, doc) {
+	"use strict";
+
+	/**
+	 * Apply css prefix cssHooks
+	 * @ko 자동으로 css prefix가 적용되지 않는 jQuery 1.4.3 ~ 1.8.x에서 css prefix을 자동으로 등록하는 cssHooks이다.
+	 *
+	 * @name jQuery#cssPrefix
+	 * @method
+	 *
+	 * * @support {"ie": "10+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
+	 * @example
+	 * $("#ID").css("transform", "translate('10px', '10px');
+	 * $("#ID").css("Transform", "translate('10px', '10px');
+	 * $("#ID").css("webkitTransform", "translate('10px', '10px');
+	 * $("#ID").css("transform");
+	 * $("#ID").css("webkitTransform");
+	 */
+
+	if (!$.cssHooks) {
+		throw (new Error("jQuery 1.4.3+ is needed for this plugin to work"));
+	}
+
+	// run in jQuery 1.8.x below
+	var matchTest = ($.fn.jquery.match(/^\d\.\d+/) || [])[0];
+	if (!matchTest || +matchTest.replace(/\D/, "") >= 18) {
+		return;
+	}
+
+	var cssPrefixes = [ "Webkit", "Moz", "O", "ms" ];
+	var acts = ["transitionProperty", "transitionDuration", "transition",
+				"transform", "transitionTimingFunction"];
+
+	var vendorPrefix = (function() {
+		var bodyStyle = (doc.head || doc.getElementsByTagName("head")[0]).style;
+		for (var i = 0, len = cssPrefixes.length ; i < len ; i++) {
+			if (cssPrefixes[i] + "Transition" in bodyStyle) {
+				return cssPrefixes[i];
+			}
+		}
+	})();
+
+	// ie7, 8 - transform and transition are not supported
+	// ie9 - transition not supported
+	if (!vendorPrefix) {
+		return;
+	}
+
+	// If "ms" using "Ms" property in the get function
+	var setCssHooks = function(prop) {
+		var upperProp = prop.charAt(0).toUpperCase() + prop.slice(1);
+		var vendorProp = vendorPrefix + upperProp;
+		var getVendorProp = vendorPrefix === "ms" ? "Ms" + upperProp : vendorProp;
+
+		$.cssHooks[upperProp] =
+		$.cssHooks[vendorPrefix.toLowerCase() + upperProp] =
+		$.cssHooks[prop] = {
+			get: function(elem, computed) {
+				return computed ? $.css(elem, getVendorProp) : elem.style[vendorProp];
+			},
+			set: function(elem, value) {
+				elem.style[vendorProp] = value;
+			}
+		};
+	};
+
+	for (var n = 0, actsLen = acts.length; n < actsLen; n++) {
+		setCssHooks(acts[n]);
+	}
+
+	return {
+		vendorPrefix: vendorPrefix,
+		setCssHooks: setCssHooks
+	};
+
+});
+
+
+ + + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:13 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/eg.Class.html b/doc/eg.Class.html new file mode 100644 index 00000000..ee5131f2 --- /dev/null +++ b/doc/eg.Class.html @@ -0,0 +1,1169 @@ + + + + + Class: Class | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: Class

+ + + + +
+ +
+

+ eg. + + Class +

+ + +
+ +
+
+ + + + +
+
+

+ + new eg.Class(def) +

+ + + + +
+ + +
+
+ + +
+

A module used to implement an application in object-oriented programming style

+
+ + +
+

애플리케이션을 객체지향 프로그래밍 방식으로 구현할 때 사용하는 모듈

+
+ + + + + + + + + +
    + +
  • + +
    + def + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    definition. Follow the rules under Literals of objects. Note that "construct" is a key reserved as a constructor function.

    +

    클래스를 정의하는 부분. 객체 리터럴 규칙을 따른다. 단, 'construct'는 생성자 함수로 예약된 키다

    + +
    + + + + + +
      + +
    • + +
      + construct + + + + + optional + + + + + +
      + + +
      Type: +function + +
      + + + +
      + +

      The constructor of the class

      +

      클래스 생성자 함수 (Optional)

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + + + +
Example
+ + + +
     var Some = eg.Class({
+         //Class initialize
+        "construct" : function(val){
+            this.val = val;
+        },
+        "sumVal" : function(val) {
+            return this.val + val;
+        }
+     });
+
+     var some = new Some(5);
+     some.sumVal(5);//10
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +

Browser Support

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BrowserVersion
Desktop - Internet Explorer7+
Desktop - Chromelatest
Desktop - Firefoxlatest
Desktop - Safarilatest
Desktop - Edgelatest
iOS7+
Andorid2.1+ (except 3.x)
+ + + + +
+ + + + + + + + + + + + + + + +

Methods

+ +
+ +
+
+

+ + staticeg.Class.extend(oSuperClass, def){eg.Class} +

+ + + + +
+ + +
+
+ + +
+

Extends a class.

+
+ + +
+

클래스를 상속한다.

+
+ + + + + + + + + +
    + +
  • + +
    + oSuperClass + + + +
    + + +
    Type: +eg.Class + +
    + + + +
    + +

    Superclass

    +

    상속하려는 클래스

    + +
    + + + +
  • + +
  • + +
    + def + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    Class definition. Follow the rules under Literals of objects. Note that "construct" is a key reserved as a constructor function.

    +

    클래스를 정의하는 부분. 객체 리터럴 규칙을 따른다. 단, 'construct'는 생성자 함수로 예약된 키다.

    + +
    + + + + + +
      + +
    • + +
      + construct + + + + + optional + + + + + +
      + + +
      Type: +function + +
      + + + +
      + +

      The constructor of the class

      +

      클래스 생성자 함수 (Optional)

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Class + + + + +
An instance of a new class
+

새로 생성된 클래스의 인스턴스

+ + + +
+ + + + +
Example
+ + + +
     var Some = eg.Class.extend(eg.Component,{
+        "some" : function(){}
+     })
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + instance(){eg.Class} +

+ + + + +
+ + +
+
+ + +
+

Returns an instance of a class itself.

+
+ + +
+

클래스 자신의 인스턴스를 반환한다.

+
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Class + + + + +
An instance of a class itself
+

클래스 자신의 인스턴스

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + +
+ +
+ + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:18 GMT+0900 (KST) +
+
+
+ + + + + \ No newline at end of file diff --git a/doc/eg.Component.html b/doc/eg.Component.html new file mode 100644 index 00000000..8427d08b --- /dev/null +++ b/doc/eg.Component.html @@ -0,0 +1,1674 @@ + + + + + Class: Component | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: Component

+ + + + +
+ +
+

+ eg. + + Component +

+ + +
+ +
+
+ + + + +
+
+

+ + new eg.Component() +

+ + + + +
+ + +
+
+ + +
+

A class used to manage events and options in a component

+
+ + +
+

컴포넌트의 이벤트와 옵션을 관리할 수 있게 하는 클래스

+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +

Browser Support

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BrowserVersion
Desktop - Internet Explorer7+
Desktop - Chromelatest
Desktop - Firefoxlatest
Desktop - Safarilatest
Desktop - Edgelatest
iOS7+
Andorid2.1+ (except 3.x)
+ + + + +
+ + + + + + + + + + + + + + + +

Methods

+ +
+ +
+
+

+ + hasOn(eventName){Boolean} +

+ + + + +
+ + +
+
+ + +
+

Checks whether an event has been attached to a component.

+
+ + +
+

컴포넌트에 이벤트가 등록됐는지 확인한다.

+
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    The name of the event to be attached

    +

    등록 여부를 확인할 이벤트의 이름

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + +
Indicates whether the event is attached.
+

이벤트 등록 여부

+ + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.hasOn("hi");// check hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + off(eventName, handlerToDetach){eg.Component} +

+ + + + +
+ + +
+
+ + +
+

Detaches an event from the component.

+
+ + +
+

컴포넌트에 등록된 이벤트를 해제한다

+
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +

    The name of the event to be detached

    +

    해제할 이벤트의 이름

    + +
    + + + +
  • + +
  • + +
    + handlerToDetach + + + +
    + + +
    Type: +function + +
    + + + +
    + +

    The handler function of the event to be detached

    +

    해제할 이벤트의 핸들러 함수

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
An instance of a component itself
+

컴포넌트 자신의 인스턴스

+ + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "hi": function(){},
+            "some": function(){
+                this.off("hi",this.hi); //detach event
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + on(eventName, handlerToAttach){eg.Component} +

+ + + + +
+ + +
+
+ + +
+

Attaches an event to a component.

+
+ + +
+

컴포넌트에 이벤트를 등록한다.

+
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +

    The name of the event to be attached

    +

    등록할 이벤트의 이름

    + +
    + + + +
  • + +
  • + +
    + handlerToAttach + + + +
    + + +
    Type: +function + +
    + + + +
    + +

    The handler function of the event to be attached

    +

    등록할 이벤트의 핸들러 함수

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
An instance of a component itself
+

컴포넌트 자신의 인스턴스

+ + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "hi": function(){},
+            "some": function(){
+                this.on("hi",this.hi); //attach event
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + option(key, value){eg.Component|Object} +

+ + + + +
+ + +
+
+ + +
+

Sets options in a component or returns them.

+
+ + +
+

컴포넌트에 옵션을 설정하거나 옵션을 반환한다

+
+ + + + + + + + + +
    + +
  • + +
    + key + + + + + + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    The key of the option

    +

    옵션의 키

    + +
    + + + +
  • + +
  • + +
    + value + + + + + optional + + + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    The option value that corresponds to a given key

    +

    키에 해당하는 옵션값

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + | + + Object + + + + +
An instance, an option value, or an option object of a component itself.
- If both key and value are used to set an option, it returns an instance of a component itself.
- If only a key is specified for the parameter, it returns the option value corresponding to a given key.
- If nothing is specified, it returns an option object.
+

컴포넌트 자신의 인스턴스나 옵션값, 옵션 객체.
- 키와 값으로 옵션을 설정하면 컴포넌트 자신의 인스턴스를 반환한다.
- 파라미터에 키만 설정하면 키에 해당하는 옵션값을 반환한다.
- 파라미터에 아무것도 설정하지 않으면 옵션 객체를 반환한다.

+ + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component);
+        var some = new Some({
+            "foo": 1,
+            "bar": 2,
+        });
+        some.option("foo"); // return 1
+        some.option("foo",3); // return some instance
+        some.option(); // return options object.
+        some.option({
+            "foo" : 10,
+            "bar" : 20,
+            "baz" : 30
+        }); // return some instance.
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + trigger(eventName, customEvent){Boolean} +

+ + + + +
+ + +
+
+ + +
+

Triggers a custom event.

+
+ + +
+

커스텀 이벤트를 발생시킨다

+
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    The name of the custom event to be triggered

    +

    발생할 커스텀 이벤트의 이름

    + +
    + + + +
  • + +
  • + +
    + customEvent + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    Event data to be sent when triggering a custom event

    +

    커스텀 이벤트가 발생할 때 전달할 데이터

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + +
Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring.
+

이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다.

+ + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.trigger("hi");// fire hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + +
+ +
+ + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:18 GMT+0900 (KST) +
+
+
+ + + + + \ No newline at end of file diff --git a/doc/eg.Flicking.html b/doc/eg.Flicking.html new file mode 100644 index 00000000..d116c1e5 --- /dev/null +++ b/doc/eg.Flicking.html @@ -0,0 +1,6271 @@ + + + + + Class: Flicking | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: Flicking

+ + + + +
+ +
+

+ eg. + + Flicking +

+ + +
+ +
+
+ + + + +
+
+

+ + new eg.Flicking(element, options) +

+ + + + +
+ + +
+
+ + +
+

A module used to implement flicking interactions. With this module, you can make flicking gestures, which are ways to navigate left and right to move between panels arranged side by side.

+
+ + +
+

플리킹 UI를 구현하는 모듈. 나란히 배치한 패널을 쓸어 넘겨 다음 패널이나 이전 패널로 이동하는 플리킹 UI를 만들 수 있다.

+
+ + + + + + + + + +
    + +
  • + +
    + element + + + +
    + + +
    Type: +HTMLElement +| + +String +| + +jQuery + +
    + + + +
    + +

    A base element for the eg.Flicking module

    +

    eg.Flicking 모듈을 사용할 기준 엘리먼트

    + +
    + + + +
  • + +
  • + +
    + options + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    The option object of the eg.Flicking module

    +

    eg.Flicking 모듈의 옵션 객체

    + +
    + + + + + +
      + +
    • + +
      + hwAccelerable + + (default: eg.isHWAccelerable()) + + + + + optional + + + + + +
      + + +
      Type: +Boolean + +
      + + + +
      + +

      Force hardware compositing

      +

      하드웨어 가속 사용 여부

      + +
      + + + +
    • + +
    • + +
      + prefix + + (default: eg-flick) + + + + + optional + + + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      A prefix for class names of the panel elements

      +

      패널 엘리먼트의 클래스 이름에 설정할 접두사

      + +
      + + + +
    • + +
    • + +
      + deceleration + + (default: 0.0006) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time

      +

      사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다

      + +
      + + + +
    • + +
    • + +
      + horizontal + + (default: true) + + + + + optional + + + + + +
      + + +
      Type: +Boolean + +
      + + + +
      + +

      Direction of the panel movement (true: horizontal, false: vertical)

      +

      패널 이동 방향 (true 가로방향, false 세로방향)

      + +
      + + + +
    • + +
    • + +
      + circular + + (default: false) + + + + + optional + + + + + +
      + + +
      Type: +Boolean + +
      + + + +
      + +

      Indicates whether a circular panel is available

      +

      패널 순환 여부

      + +
      + + + +
    • + +
    • + +
      + previewPadding + + (default: [0,0]) + + + + + optional + + + + + +
      + + +
      Type: +Number +| + +Array + +
      + + + +
      + +

      The preview size for the previous or next panel. If direction is set to "horizontal", the preview section will be displayed on the left and right of the panel. If direction is set to "vertical", it will be displayed on the top and bottom of the panel

      +

      이전 패널과 다음 패널을 미리 보는 영역의 크기. 패널 이동 방향이 가로 방향이면 패널 왼쪽과 오른쪽에 미리 보는 영역이 나타난다. 패널 이동 방향이 세로 방향이면 패널 위쪽과 아래쪽에 미리 보는 영역이 나타난다

      + +
      + + + +
    • + +
    • + +
      + bounce + + (default: [10,10]) + + + + + optional + + + + + +
      + + +
      Type: +Number +| + +Array + +
      + + + +
      + +

      − The size of bouncing area. If a panel is set to "non-circulable", the start and end panels can exceed the base element area and move further as much as the bouncing area. If a panel is dragged to the bouncing area and then dropped, the panel where bouncing effects are applied is retuned back into the base element area.

      +

      바운스 영역의 크기. 패널이 순환하지 않도록 설정됐다면 시작 패널과 마지막 패널은 기준 엘리먼트 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 패널을 바운스 영역까지 끌었다가 놓으면, 바운스 효과가 적용된 패널이 다시 기준 엘리먼트 영역 안으로 들어온다

      + +
      + + + +
    • + +
    • + +
      + threshold + + (default: 40) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Distance threshold. If the drag exceeds the threshold value, it will be changed to the next panel

      +

      다음 패널로 바뀌는 기준 이동 거리. 패널을 기준 이동 거리 이상 끌었다 놓으면 패널이 다음 패널로 바뀐다

      + +
      + + + +
    • + +
    • + +
      + duration + + (default: 100) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Duration of the panel movement (unit: ms)

      +

      패널 이동 애니메이션 진행 시간(단위: ms)

      + +
      + + + +
    • + +
    • + +
      + panelEffect + + (default: easeOutCubic) + + + + + optional + + + + + +
      + + +
      Type: +function + +
      + + + +
      + +

      The easing function to apply to a panel moving animation

      +

      패널 이동 애니메이션에 적용할 easing 함수

      + +
      + + + +
    • + +
    • + +
      + defaultIndex + + (default: 0) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      The index number of a panel to be selected upon module initialization

      +

      모듈이 초기화될 때 선택할 패널의 인덱스 번호

      + +
      + + + +
    • + +
    • + +
      + inputType + + + + + optional + + + + + +
      + + +
      Type: +Array + +
      + + + +
      + +

      Types of input devices.
      - touch: A touch screen can be used to move a panel.
      - mouse: A mouse can be used to move a panel.

      +

      입력 장치 종류.
      - touch: 터치 입력 장치로 패널을 이동할 수 있다.
      - mouse: 마우스로 패널을 이동할 수 있다.

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + + + +
Example
+ + + +
     <!-- HTML -->
+    <div id="mflick">
+        <div>
+            <p>Layer 0</p>
+        </div>
+        <div>
+            <p>Layer 1</p>
+        </div>
+        <div>
+            <p>Layer 2</p>
+        </div>
+    </div>
+    <script>
+     var some = new eg.Flicking("#mflick", {
+            circular : true,
+            threshold : 50
+        }).on({
+            beforeRestore : function(e) { ... },
+            flickStart : function(e) { ... }
+        });
+     </script>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +

Codepen:

+ + + + + + + + +
플리킹 UI 기본 예제
+
Flicking UI default example
+

See the Pen eg.Flicking by egjs (@egjs) on CodePen.

+ + + +
+ +
+ + + + +

Browser Support

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BrowserVersion
Desktop - Internet Explorer10+
Desktop - Chromelatest
Desktop - Firefoxlatest
Desktop - Safarilatest
Desktop - Edgelatest
iOS7+
Andorid2.3+ (except 3.x)
+ + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + +

Methods

+ +
+ +
+
+

+ + destroy() +

+ + + + +
+ + +
+
+ + +
+

Destroys elements, properties, and events used in a panel.

+
+ + +
+

패널에 사용한 엘리먼트와 속성, 이벤트를 해제한다

+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + disableInput(){eg.Flicking} +

+ + + + +
+ + +
+
+ + +
+

Disables input devices.

+
+ + +
+

입력 장치를 사용할 수 없게 한다.

+
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Flicking + + + + +
An instance of a module itself
+

모듈 자신의 인스턴스

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + enableInput(){eg.Flicking} +

+ + + + +
+ + +
+
+ + +
+

Enables input devices.

+
+ + +
+

입력 장치를 사용할 수 있게 한다

+
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Flicking + + + + +
An instance of a module itself
+

모듈 자신의 인스턴스

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getAllElements(){jQuery} +

+ + + + +
+ + +
+
+ + +
+

Returns the references of whole panel elements.

+
+ + +
+

패널을 구성하는 모든 엘리먼트의 레퍼런스를 반환한다

+
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + jQuery + + + + +
Whole panel elements
+

모든 패널 엘리먼트

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getElement(){jQuery} +

+ + + + +
+ + +
+
+ + +
+

Returns the reference of the current panel element.

+
+ + +
+

현재 패널 엘리먼트의 레퍼런스를 반환한다

+
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + jQuery + + + + +
Current element
+

현재 엘리먼트

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getIndex(physical){Number} +

+ + + + +
+ + +
+
+ + +
+

Returns the index number of the current panel element.

+
+ + +
+

현재 패널 엘리먼트의 인덱스 번호를 반환한다

+
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Types of index numbers
    - true: Indicates physical index numbers relative to DOM.
    - false: Indicates logical index numbers relative to the panel content.

    +

    − 인덱스 번호의 종류
    - true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.
    - false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
Index number of the current panel element
+

현재 패널의 인덱스 번호

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getNextElement(){jQuery|null} +

+ + + + +
+ + +
+
+ + +
+

Returns the reference of the next panel element.

+
+ + +
+

다음 패널 엘리먼트의 레퍼런스를 반환한다.

+
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + jQuery + | + + null + + + + +
Next panel element or null if it does not exist.
+

다음 패널 엘리먼트. 패널이 없으면 'null'을 반환한다.

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getNextIndex(physical){Number|null} +

+ + + + +
+ + +
+
+ + +
+

Returns the index number of the next panel element.

+
+ + +
+

다음 패널 엘리먼트의 인덱스 번호를 반환한다

+
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Types of index numbers
    - true: Indicates physical index numbers relative to DOM.
    - false: Indicates logical index numbers relative to the panel content.

    +

    − 인덱스 번호의 종류
    - true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.
    - false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + | + + null + + + + +
Index number of the next panel element or null if it does not exist.
+

다음 패널 엘리먼트의 인덱스 번호. 패널이 없으면 'null'을 반환한다

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getPrevElement(){jQuery|null} +

+ + + + +
+ + +
+
+ + +
+

Returns the reference of the previous panel element.

+
+ + +
+

이전 패널 엘리먼트의 레퍼런스를 반환한다.

+
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + jQuery + | + + null + + + + +
Previous panel element or null if it does not exist.
+

이전 패널 엘리먼트. 패널이 없으면 'null'을 반환한다

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getPrevIndex(physical){Number|null} +

+ + + + +
+ + +
+
+ + +
+

Returns the index number of the previous panel element.

+
+ + +
+

이전 패널 엘리먼트의 인덱스 번호를 반환한다

+
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Types of index numbers
    - true: Indicates physical index numbers relative to DOM.
    - false: Indicates logical index numbers relative to the panel content.

    +

    − 인덱스 번호의 종류
    - true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.
    - false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + | + + null + + + + +
Previous element index value or null if no more element exist
+

이전 패널 인덱스 번호. 패널이 없는 경우에는 null

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getTotalCount(physical){Number} +

+ + + + +
+ + +
+
+ + +
+

Returns the total number of whole panel elements.

+
+ + +
+

전체 패널 엘리먼트의 개수를 반환한다

+
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Number of elements relative to (true: DOM, false: panel content)

    +

    엘리먼트 개수의 기준(true: DOM 엘리먼트 기준, false: 패널 콘텐츠 기준)

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
Total number of whole panel elements
+

모든 패널 엘리먼트의 개수

+ + + +
+ + + + + + +
+ + + + + + + +
Deprecated
  • since 1.3.0
    + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + inherited + + hasOn(eventName){Boolean} +

    + + + + +
    + + +
    +
    + + +
    +

    Checks whether an event has been attached to a component.

    +
    + + +
    +

    컴포넌트에 이벤트가 등록됐는지 확인한다.

    +
    + + + + + + + + + +
      + +
    • + +
      + eventName + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      The name of the event to be attached

      +

      등록 여부를 확인할 이벤트의 이름

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + Boolean + + + + +
    Indicates whether the event is attached.
    +

    이벤트 등록 여부

    + + + +
    + + + + +
    Example
    + + + +
            var Some = eg.Class.extend(eg.Component,{
    +            "some": function(){
    +                this.hasOn("hi");// check hi event.
    +            }
    +        });
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + isPlaying(){Boolean} +

    + + + + +
    + + +
    +
    + + +
    +

    Checks whether the animated panel is playing.

    +
    + + +
    +

    패널 이동 애니메이션이 진행 중인지 확인한다.

    +
    + + + + + + + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + Boolean + + + + +
    Indicates whether the animated panel is playing
    +

    패널 이동 애니메이션 진행 중 여부

    + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + moveTo(no, duration){eg.Flicking} +

    + + + + +
    + + +
    +
    + + +
    +

    Moves an element to the indicated panel.

    +
    + + +
    +

    지정한 패널로 이동한다.

    +
    + + + + + + + + + +
      + +
    • + +
      + no + + + + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Logical index number of the target panel element, which is relative to the panel content.

      +

      이동할 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다

      + +
      + + + +
    • + +
    • + +
      + duration + + (default: options.duration) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Duration of the panel movement (unit: ms)

      +

      패널 이동 애니메이션 진행 시간(단위: ms)

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Flicking + + + + +
    An instance of a module itself
    +

    모듈 자신의 인스턴스

    + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + next(duration){eg.Flicking} +

    + + + + +
    + + +
    +
    + + +
    +

    Moves an element to the next panel.

    +
    + + +
    +

    다음 패널로 이동한다.

    +
    + + + + + + + + + +
      + +
    • + +
      + duration + + (default: options.duration) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Duration of the panel movement (unit: ms)

      +

      패널 이동 애니메이션 진행 시간(단위: ms)

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Flicking + + + + +
    An instance of a module itself
    +

    모듈 자신의 인스턴스

    + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + inherited + + off(eventName, handlerToDetach){eg.Component} +

    + + + + +
    + + +
    +
    + + +
    +

    Detaches an event from the component.

    +
    + + +
    +

    컴포넌트에 등록된 이벤트를 해제한다

    +
    + + + + + + + + + +
      + +
    • + +
      + eventName + + + +
      + + +
      Type: +eventName + +
      + + + +
      + +

      The name of the event to be detached

      +

      해제할 이벤트의 이름

      + +
      + + + +
    • + +
    • + +
      + handlerToDetach + + + +
      + + +
      Type: +function + +
      + + + +
      + +

      The handler function of the event to be detached

      +

      해제할 이벤트의 핸들러 함수

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Component + + + + +
    An instance of a component itself
    +

    컴포넌트 자신의 인스턴스

    + + + +
    + + + + +
    Example
    + + + +
            var Some = eg.Class.extend(eg.Component,{
    +            "hi": function(){},
    +            "some": function(){
    +                this.off("hi",this.hi); //detach event
    +            }
    +        });
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + inherited + + on(eventName, handlerToAttach){eg.Component} +

    + + + + +
    + + +
    +
    + + +
    +

    Attaches an event to a component.

    +
    + + +
    +

    컴포넌트에 이벤트를 등록한다.

    +
    + + + + + + + + + +
      + +
    • + +
      + eventName + + + +
      + + +
      Type: +eventName + +
      + + + +
      + +

      The name of the event to be attached

      +

      등록할 이벤트의 이름

      + +
      + + + +
    • + +
    • + +
      + handlerToAttach + + + +
      + + +
      Type: +function + +
      + + + +
      + +

      The handler function of the event to be attached

      +

      등록할 이벤트의 핸들러 함수

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Component + + + + +
    An instance of a component itself
    +

    컴포넌트 자신의 인스턴스

    + + + +
    + + + + +
    Example
    + + + +
            var Some = eg.Class.extend(eg.Component,{
    +            "hi": function(){},
    +            "some": function(){
    +                this.on("hi",this.hi); //attach event
    +            }
    +        });
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + inherited + + option(key, value){eg.Component|Object} +

    + + + + +
    + + +
    +
    + + +
    +

    Sets options in a component or returns them.

    +
    + + +
    +

    컴포넌트에 옵션을 설정하거나 옵션을 반환한다

    +
    + + + + + + + + + +
      + +
    • + +
      + key + + + + + + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      The key of the option

      +

      옵션의 키

      + +
      + + + +
    • + +
    • + +
      + value + + + + + optional + + + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      The option value that corresponds to a given key

      +

      키에 해당하는 옵션값

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Component + | + + Object + + + + +
    An instance, an option value, or an option object of a component itself.
    - If both key and value are used to set an option, it returns an instance of a component itself.
    - If only a key is specified for the parameter, it returns the option value corresponding to a given key.
    - If nothing is specified, it returns an option object.
    +

    컴포넌트 자신의 인스턴스나 옵션값, 옵션 객체.
    - 키와 값으로 옵션을 설정하면 컴포넌트 자신의 인스턴스를 반환한다.
    - 파라미터에 키만 설정하면 키에 해당하는 옵션값을 반환한다.
    - 파라미터에 아무것도 설정하지 않으면 옵션 객체를 반환한다.

    + + + +
    + + + + +
    Example
    + + + +
            var Some = eg.Class.extend(eg.Component);
    +        var some = new Some({
    +            "foo": 1,
    +            "bar": 2,
    +        });
    +        some.option("foo"); // return 1
    +        some.option("foo",3); // return some instance
    +        some.option(); // return options object.
    +        some.option({
    +            "foo" : 10,
    +            "bar" : 20,
    +            "baz" : 30
    +        }); // return some instance.
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + prev(duration){eg.Flicking} +

    + + + + +
    + + +
    +
    + + +
    +

    Moves an element to the previous panel.

    +
    + + +
    +

    이전 패널로 이동한다.

    +
    + + + + + + + + + +
      + +
    • + +
      + duration + + (default: options.duration) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Duration of the panel movement (unit: ms)

      +

      패널 이동 애니메이션 진행 시간(단위: ms)

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Flicking + + + + +
    An instance of a module itself
    +

    모듈 자신의 인스턴스

    + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + resize(){eg.Flicking} +

    + + + + +
    + + +
    +
    + + +
    +

    Updates the size of the panel.

    +
    + + +
    +

    패널의 크기를 갱신한다

    +
    + + + + + + + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Flicking + + + + +
    An instance of a module itself
    +

    모듈 자신의 인스턴스

    + + + +
    + + + + +
    Example
    + + + +
            var some = new eg.Flicking("#mflick", {
    +                previewPadding: [10,10]
    +            });
    +
    +        // when device orientaion changes
    +        some.resize();
    +
    +        // or when changes previewPadding option from its original value
    +        some.options.previewPadding = [20, 30];
    +        some.resize();
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + restore(duration){eg.Flicking} +

    + + + + +
    + + +
    +
    + + +
    +

    Restores an element to its original position when it movement stops while the element is not dragged until a certain distance threshold is reached.

    +
    + + +
    +

    다음 패널로 바뀌기 전에 패널 이동이 멈췄을 때 원래 패널로 복원한다

    +
    + + + + + + + + + +
      + +
    • + +
      + duration + + (default: options.duration) + + + + + optional + + + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      Duration of the panel movement (unit: ms)

      +

      패널 이동 애니메이션 진행 시간(단위: ms)

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.Flicking + + + + +
    An instance of a module itself
    +

    모듈 자신의 인스턴스

    + + + +
    + + + + +
    Example
    + + + +
            var some = new eg.Flicking("#mflick").on({
    +                beforeFlickStart : function(e) {
    +                    if(e.no === 2) {
    +                        e.stop();  // stop flicking
    +                        this.restore(100);  // restoring to previous position
    +                    }
    +                }
    +            );
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + inherited + + trigger(eventName, customEvent){Boolean} +

    + + + + +
    + + +
    +
    + + +
    +

    Triggers a custom event.

    +
    + + +
    +

    커스텀 이벤트를 발생시킨다

    +
    + + + + + + + + + +
      + +
    • + +
      + eventName + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      The name of the custom event to be triggered

      +

      발생할 커스텀 이벤트의 이름

      + +
      + + + +
    • + +
    • + +
      + customEvent + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      Event data to be sent when triggering a custom event

      +

      커스텀 이벤트가 발생할 때 전달할 데이터

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + Boolean + + + + +
    Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring.
    +

    이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다.

    + + + +
    + + + + +
    Example
    + + + +
            var Some = eg.Class.extend(eg.Component,{
    +            "some": function(){
    +                this.trigger("hi");// fire hi event.
    +            }
    +        });
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    + + + + + +

    Events

    + +
    + +
    +
    +

    + + beforeFlickStart +

    + + + + +
    + + +
    +
    + + +
    +

    This event is fired before flicking starts

    +
    + + +
    +

    플리킹이 시작하기 전에 발생하는 이벤트

    +
    + + + + + + + + + +
      + +
    • + +
      + param + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      The object of data to be sent to an event

      +

      이벤트에 전달되는 데이터 객체

      + +
      + + + + + +
        + +
      • + +
        + eventType + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event

        +

        이름명

        + +
        + + + +
      • + +
      • + +
        + index + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Physical index number of the current panel element, which is relative to DOM. (@deprecated since 1.3.0)

        +

        현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)

        + +
        + + + +
      • + +
      • + +
        + no + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Logical index number of the current panel element, which is relative to the panel content.

        +

        현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다

        + +
        + + + +
      • + +
      • + +
        + direction + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Direction of the movement (see eg.MovableCoord.DIRECTION* constant)

        +

        − 이동 방향(eg.MovableCoord.DIRECTION* constant 참고)

        + +
        + + + +
      • + +
      • + +
        + depaPos + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        Start coordinate

        +

        출발점 좌표

        + +
        + + + + + +
          + +
        • + +
          + 0 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          x-coordinate

          +

          x 좌표

          + +
          + + + +
        • + +
        • + +
          + 1 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          y-coordinate

          +

          y 좌표

          + +
          + + + +
        • + +
        + +
      • + +
      • + +
        + destPos + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        End coordinate

        +

        도착점 좌표

        + +
        + + + + + +
          + +
        • + +
          + 0 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          x-coordinate

          +

          x 좌표

          + +
          + + + +
        • + +
        • + +
          + 1 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          y-coordinate

          +

          y 좌표

          + +
          + + + +
        • + +
        + +
      • + +
      + +
    • + +
    + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + beforeRestore +

    + + + + +
    + + +
    +
    + + +
    +

    This event is fired before an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached

    +
    + + +
    +

    다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원되기 전에 발생하는 이벤트

    +
    + + + + + + + + + +
      + +
    • + +
      + param + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      The object of data to be sent to an event

      +

      이벤트에 전달되는 데이터 객체

      + +
      + + + + + +
        + +
      • + +
        + eventType + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event

        +

        이름명

        + +
        + + + +
      • + +
      • + +
        + index + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Physical index number of the current panel element, which is relative to DOM. (@deprecated since 1.3.0)

        +

        현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다. (@deprecated since 1.3.0)

        + +
        + + + +
      • + +
      • + +
        + no + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Logical index number of the current panel element, which is relative to the panel content.

        +

        현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다

        + +
        + + + +
      • + +
      • + +
        + direction + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Direction of the movement (see eg.MovableCoord.DIRECTION* constant)

        +

        이동 방향(eg.MovableCoord.DIRECTION* constant 참고)

        + +
        + + + +
      • + +
      • + +
        + depaPos + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        Start coordinate

        +

        출발점 좌표

        + +
        + + + + + +
          + +
        • + +
          + 0 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          x-coordinate

          +

          x 좌표

          + +
          + + + +
        • + +
        • + +
          + 1 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          y-coordinate

          +

          y 좌표

          + +
          + + + +
        • + +
        + +
      • + +
      • + +
        + destPos + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        End coordinate

        +

        도착점 좌표

        + +
        + + + + + +
          + +
        • + +
          + 0 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          x-coordinate

          +

          x 좌표

          + +
          + + + +
        • + +
        • + +
          + 1 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          y-coordinate

          +

          y 좌표

          + +
          + + + +
        • + +
        + +
      • + +
      + +
    • + +
    + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + flick +

    + + + + +
    + + +
    +
    + + +
    +

    This event is fired when panel moves.

    +
    + + +
    +

    패널이 이동할 때 발생하는 이벤트

    +
    + + + + + + + + + +
      + +
    • + +
      + param + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      The object of data to be sent to an event

      +

      이벤트에 전달되는 데이터 객체

      + +
      + + + + + +
        + +
      • + +
        + eventType + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event

        +

        이름명

        + +
        + + + +
      • + +
      • + +
        + index + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Physical index number of the current panel element, which is relative to DOM (@deprecated since 1.3.0)

        +

        현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)

        + +
        + + + +
      • + +
      • + +
        + no + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Logical index number of the current panel element, which is relative to the panel content

        +

        현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다

        + +
        + + + +
      • + +
      • + +
        + direction + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Direction of the movement (see eg.MovableCoord.DIRECTION* constant)

        +

        이동 방향(eg.MovableCoord.DIRECTION* constant 참고)

        + +
        + + + +
      • + +
      • + +
        + pos + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        Start coordinate

        +

        출발점 좌표

        + +
        + + + + + +
          + +
        • + +
          + 0 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          x-coordinate

          +

          x 좌표

          + +
          + + + +
        • + +
        • + +
          + 1 + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          y-coordinate

          +

          y 좌표

          + +
          + + + +
        • + +
        + +
      • + +
      • + +
        + holding + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +

        Indicates whether a user holds an element on the screen of the device.

        +

        사용자가 기기의 화면을 누르고 있는지 여부

        + +
        + + + +
      • + +
      • + +
        + distance + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Distance moved from then starting point. According the move direction, positive on eg.MovableCoord.DIRECTION_LEFT/UP and negative on eg.MovableCoord.DIRECTION_RIGHT/DOWN

        +

        시작점부터 이동된 거리의 값. 이동 방향에 따라 eg.MovableCoord.DIRECTION_LEFT/UP의 경우 양수를 eg.MovableCoord.DIRECTION_RIGHT/DOWN의 경우는 음수를 반환

        + +
        + + + +
      • + +
      + +
    • + +
    + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + flickEnd +

    + + + + +
    + + +
    +
    + + +
    +

    This event is fired after panel moves.

    +
    + + +
    +

    패널이 이동한 다음 발생하는 이벤트

    +
    + + + + + + + + + +
      + +
    • + +
      + param + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      The object of data to be sent to an event

      +

      이벤트에 전달되는 데이터 객체

      + +
      + + + + + +
        + +
      • + +
        + eventType + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event

        +

        이름명

        + +
        + + + +
      • + +
      • + +
        + index + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Physical index number of the current panel element, which is relative to DOM (@deprecated since 1.3.0)

        +

        현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)

        + +
        + + + +
      • + +
      • + +
        + no + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Logical index number of the current panel element, which is relative to the panel content.

        +

        현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.

        + +
        + + + +
      • + +
      • + +
        + direction + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Direction of the movemen (see eg.MovableCoord.DIRECTION* constant)

        +

        − 이동 방향(eg.MovableCoord.DIRECTION* constant 참고

        + +
        + + + +
      • + +
      + +
    • + +
    + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + restore +

    + + + + +
    + + +
    +
    + + +
    +

    This event is fired after an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached.

    +
    + + +
    +

    다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원된 다음 발생하는 이벤트

    +
    + + + + + + + + + +
      + +
    • + +
      + param + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      The object of data to be sent to an event

      +

      이벤트에 전달되는 데이터 객체

      + +
      + + + + + +
        + +
      • + +
        + eventType + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event

        +

        이름명

        + +
        + + + +
      • + +
      • + +
        + index + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Physical index number of the current panel element, which is relative to DOM(@deprecated since 1.3.0)

        +

        현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)

        + +
        + + + +
      • + +
      • + +
        + no + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Logical index number of the current panel element, which is relative to the panel content.

        +

        현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다

        + +
        + + + +
      • + +
      • + +
        + direction + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Direction of the panel move (see eg.MovableCoord.DIRECTION* constant)

        +

        이동 방향(eg.MovableCoord.DIRECTION* constant 참고)

        + +
        + + + +
      • + +
      + +
    • + +
    + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    + + + +
    + +
    + + + + + + + +
    + + comments powered by Disqus + + + +
    + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:19 GMT+0900 (KST) +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/eg.InfiniteGrid.html b/doc/eg.InfiniteGrid.html new file mode 100644 index 00000000..d3ea7ae1 --- /dev/null +++ b/doc/eg.InfiniteGrid.html @@ -0,0 +1,4198 @@ + + + + + Class: InfiniteGrid | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    +

    Class: InfiniteGrid

    + + + + +
    + +
    +

    + eg. + + InfiniteGrid +

    + + +
    + +
    +
    + + + + +
    +
    +

    + + new eg.InfiniteGrid(element, options) +

    + + + + +
    + + +
    +
    + + +
    +

    A module used to arrange card elements including content infinitely on a grid layout. With this module, you can implement a grid-pattern user interface composed of different card elements whose sizes vary. It guarantees performance by maintaining the number of DOMs the module is handling under any circumstance

    +
    + + +
    +

    콘텐츠가 있는 카드 엘리먼트를 그리드 레이아웃에 무한으로 배치하는 모듈. 다양한 크기의 카드 엘리먼트를 격자 모양으로 배치하는 UI를 만들 수 있다. 카드 엘리먼트의 개수가 계속 늘어나도 모듈이 처리하는 DOM의 개수를 일정하게 유지해 최적의 성능을 보장한다

    +
    + + + + + + + + + +
      + +
    • + +
      + element + + + + + + + + +
      + + +
      Type: +HTMLElement +| + +String +| + +jQuery + +
      + + + +
      + +

      A base element for a module

      +

      모듈을 적용할 기준 엘리먼트

      + +
      + + + +
    • + +
    • + +
      + options + + + + + optional + + + + + +
      + + +
      Type: +Object + +
      + + + +
      + +

      The option object of the eg.InfiniteGrid module

      +

      eg.InfiniteGrid 모듈의 옵션 객체

      + +
      + + + + + +
        + +
      • + +
        + itemSelector + + + + + optional + + + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        A selector to select card elements that make up the layout (@deprecated since 1.3.0)

        +

        레이아웃을 구성하는 카드 엘리먼트를 선택할 선택자(selector) (@deprecated since 1.3.0)

        + +
        + + + +
      • + +
      • + +
        + count + + (default: 30) + + + + + optional + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        The number of DOMs handled by module. If the count value is greater than zero, the number of DOMs is maintained. If the count value is zero or less than zero, the number of DOMs will increase as card elements are added.

        +

        모듈이 유지할 실제 DOM의 개수. count 값이 0보다 크면 DOM 개수를 일정하게 유지한다. count 값이 0 이하면 카드 엘리먼트가 추가될수록 DOM 개수가 계속 증가한다.

        + +
        + + + +
      • + +
      • + +
        + defaultGroupKey + + (default: null) + + + + + optional + + + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The default group key configured in a card element contained in the markup upon initialization of a module object

        +

        모듈 객체를 초기화할 때 마크업에 있는 카드 엘리먼트에 설정할 그룹 키

        + +
        + + + +
      • + +
      • + +
        + isEqualSize + + (default: false) + + + + + optional + + + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +

        Indicates whether sizes of all card elements are equal to one another. If sizes of card elements to be arranged are all equal and this option is set to "true", the performance of layout arrangement can be improved.

        +

        카드 엘리먼트의 크기가 동일한지 여부. 배치될 카드 엘리먼트의 크기가 모두 동일할 때 이 옵션을 'true'로 설정하면 레이아웃 배치 성능을 높일 수 있다

        + +
        + + + +
      • + +
      • + +
        + threshold + + (default: 300) + + + + + optional + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        The threshold size of an event area where card elements are added to a layout.
        - append event: If the current vertical position of the scroll bar is greater than "the bottom property value of the card element at the top of the layout" plus "the value of the threshold option", the append event will occur.
        - prepend event: If the current vertical position of the scroll bar is less than "the bottom property value of the card element at the top of the layout" minus "the value of the threshold option", the prepend event will occur.

        +

        − 레이아웃에 카드 엘리먼트를 추가하는 이벤트가 발생하는 기준 영역의 크기.
        - append 이벤트: 현재 스크롤의 y 좌표 값이 '레이아웃의 맨 아래에 있는 카드 엘리먼트의 top 속성의 값 + threshold 옵션의 값'보다 크면 append 이벤트가 발생한다.
        - prepend 이벤트: 현재 스크롤의 y 좌표 값이 '레이아웃의 맨 위에 있는 카드 엘리먼트의 bottom 속성의 값 - threshold 옵션의 값'보다 작으면 prepend 이벤트가 발생한다

        + +
        + + + +
      • + +
      + +
    • + +
    + + + + + + + + + + + + + +
    Example
    + + + +
        <!-- HTML -->
    +    <ul id="grid">
    +        <li class="card">
    +            <div>test1</div>
    +        </li>
    +        <li class="card">
    +            <div>test2</div>
    +        </li>
    +        <li class="card">
    +            <div>test3</div>
    +        </li>
    +        <li class="card">
    +            <div>test4</div>
    +        </li>
    +        <li class="card">
    +            <div>test5</div>
    +        </li>
    +        <li class="card">
    +            <div>test6</div>
    +        </li>
    +    </ul>
    +    <script>
    +    var some = new eg.InfiniteGrid("#grid").on("layoutComplete", function(e) {
    +        // ...
    +    });
    +    </script>
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +

    Codepen:

    + + + + + + + + +
    InfiniteGrid 데모
    +
    InfiniteGrid example
    +

    See the Pen eg.Flicking by egjs (@egjs) on CodePen.

    + + + +
    + +
    + + + + +

    Browser Support

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    BrowserVersion
    Desktop - Internet Explorer8+
    Desktop - Chromelatest
    Desktop - Firefoxlatest
    Desktop - Safarilatest
    Desktop - Edgelatest
    iOS7+
    Andorid2.1+ (except 3.x)
    + + + + +
    + + + +

    Extends

    + + + + + + + + + + + + + + + +

    Methods

    + +
    + +
    +
    +

    + + append(elements, groupKey){Number} +

    + + + + +
    + + +
    +
    + + +
    +

    Adds a card element at the bottom of a grid layout. This method is available only if the isProcessing() method returns false.

    +
    + + +
    +

    카드 엘리먼트를 그리드 레이아웃의 아래에 추가한다. isProcessing() 메서드의 반환값이 'false'일 때만 이 메서드를 사용할 수 있다 +이 메소드는 isProcessing()의 반환값이 false일 경우에만 사용 가능하다.

    +
    + + + + + + + + + +
      + +
    • + +
      + elements + + + + + + + + +
      + + +
      Type: +Array +| + +String +| + +jQuery + +
      + + + +
      + +

      Array of the card elements to be added

      +

      추가할 카드 엘리먼트의 배열

      + +
      + + + +
    • + +
    • + +
      + groupKey + + + + + optional + + + + + +
      + + +
      Type: +Number +| + +String + +
      + + + +
      + +

      The group key to be configured in a card element. It is set to "undefined" by default.

      +

      추가할 카드 엘리먼트에 설정할 그룹 키. 생략하면 값이 'undefined'로 설정된다

      + +
      + + + +
    • + +
    + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + Number + + + + +
    The number of added card elements
    +

    추가된 카드 엘리먼트의 개수

    + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + clear(){eg.InfiniteGrid} +

    + + + + +
    + + +
    +
    + + +
    +

    Clears added card elements and data.

    +
    + + +
    +

    추가된 카드 엘리먼트와 데이터를 모두 지운다.

    +
    + + + + + + + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + eg.InfiniteGrid + + + + +
    An instance of a module itself
    +

    모듈 자신의 인스턴스

    + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + destroy() +

    + + + + +
    + + +
    +
    + + +
    +

    Destroys elements, properties, and events used on a grid layout.

    +
    + + +
    +

    그리드 레이아웃에 사용한 엘리먼트와 속성, 이벤트를 해제한다

    +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    + + fit(){Number} +

    + + + + +
    + + +
    +
    + + +
    +

    Removes extra space caused by adding card elements.

    +
    + + +
    +

    카드 엘리먼트를 추가한 다음 생긴 빈 공간을 제거한다

    +
    + + + + + + + + + + + + + + + + + +
    Returns:
    + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    + + Number + + + + +
    Actual length of space removed (unit: px)
    +

    빈 공간이 제거된 실제 길이(단위: px)

    + + + +
    + + + + + + +
    + + + + + + + +
    Deprecated
    • since version 1.3.0
      + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + getBottomElement(){HTMLElement} +

      + + + + +
      + + +
      +
      + + +
      +

      Returns a card element at the bottom of a layout.

      +
      + + +
      +

      레이아웃의 맨 아래에 있는 카드 엘리먼트를 반환한다.

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + HTMLElement + + + + +
      Card element at the bottom of a layout
      +

      레이아웃의 맨 아래에 있는 카드 엘리먼트

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + getGroupKeys(){Array} +

      + + + + +
      + + +
      +
      + + +
      +

      Returns the list of group keys which belongs to card elements currently being maintained. You can use the append() or prepend() method to configure group keys so that multiple card elements can be managed at once. If you do not use these methods to configure group keys, it returns undefined as a group key.

      +
      + + +
      +

      현재 유지하고 있는 카드 엘리먼트의 그룹 키 목록을 반환한다. 여러 개의 카드 엘리먼트를 묶어서 관리할 수 있도록 append() 메서드나 prepend() 메서드에서 그룹 키를 지정할 수 있다. append() 메서드나 prepend() 메서드에서 그룹 키를 지정하지 않았다면 'undefined'가 그룹 키로 반환된다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Array + + + + +
      List of group keys
      +

      그룹 키의 목록

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + getStatue(){Object} +

      + + + + +
      + + +
      +
      + + +
      +

      Returns the current state of a module such as location information. You can use the setStatus() method to restore the information returned through a call to this method.

      +
      + + +
      +

      카드의 위치 정보 등 모듈의 현재 상태 정보를 반환한다. 이 메서드가 반환한 정보를 저장해 두었다가 setStatus() 메서드로 복원할 수 있다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Object + + + + +
      State object of the eg.InfiniteGrid module
      +

      eg.InfiniteGrid 모듈의 상태 객체

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + getTopElement(){HTMLElement} +

      + + + + +
      + + +
      +
      + + +
      +

      Returns a card element at the top of a layout.

      +
      + + +
      +

      레이아웃의 맨 위에 있는 카드 엘리먼트를 반환한다.

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + HTMLElement + + + + +
      Card element at the top of a layout
      +

      레이아웃의 맨 위에 있는 카드 엘리먼트

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + hasOn(eventName){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether an event has been attached to a component.

      +
      + + +
      +

      컴포넌트에 이벤트가 등록됐는지 확인한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event to be attached

        +

        등록 여부를 확인할 이벤트의 이름

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether the event is attached.
      +

      이벤트 등록 여부

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "some": function(){
      +                this.hasOn("hi");// check hi event.
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + isProcessing(){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether a card element is being added.

      +
      + + +
      +

      카드 엘리먼트 추가가 진행 중인지 확인한다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether a card element is being added
      +

      카드 엘리먼트 추가 진행 중 여부

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + isRecycling(){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether the total number of added card elements is greater than the value of the count option. Note that the value of the count option is always greater than zero. If it returns true, the number of DOMs won't increase even though card elements are added; instead of adding a new DOM, existing DOMs are recycled to maintain the number of DOMs.

      +
      + + +
      +

      추가된 카드 엘리먼트의 전체 개수가 count 옵션의 값보다 큰지 확인한다. 단, count 옵션의 값은 0보다 크다. 'true'가 반환되면 카드 엘리먼트가 더 추가돼도 DOM의 개수를 증가하지 않고 기존 DOM을 재활용(recycle)해 DOM의 개수를 일정하게 유지한다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether the total number of added card elements is greater than the value of the count option.
      +

      추가된 카드 엘리먼트의 전체 개수가 count 옵션의 값보다 큰지 여부

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + layout(){eg.InfiniteGrid} +

      + + + + +
      + + +
      +
      + + +
      +

      Rearranges a layout.

      +
      + + +
      +

      레이아웃을 다시 배치한다.

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.InfiniteGrid + + + + +
      An instance of a module itself
      +

      모듈 자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + off(eventName, handlerToDetach){eg.Component} +

      + + + + +
      + + +
      +
      + + +
      +

      Detaches an event from the component.

      +
      + + +
      +

      컴포넌트에 등록된 이벤트를 해제한다

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +eventName + +
        + + + +
        + +

        The name of the event to be detached

        +

        해제할 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + handlerToDetach + + + +
        + + +
        Type: +function + +
        + + + +
        + +

        The handler function of the event to be detached

        +

        해제할 이벤트의 핸들러 함수

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + + + + +
      An instance of a component itself
      +

      컴포넌트 자신의 인스턴스

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "hi": function(){},
      +            "some": function(){
      +                this.off("hi",this.hi); //detach event
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + on(eventName, handlerToAttach){eg.Component} +

      + + + + +
      + + +
      +
      + + +
      +

      Attaches an event to a component.

      +
      + + +
      +

      컴포넌트에 이벤트를 등록한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +eventName + +
        + + + +
        + +

        The name of the event to be attached

        +

        등록할 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + handlerToAttach + + + +
        + + +
        Type: +function + +
        + + + +
        + +

        The handler function of the event to be attached

        +

        등록할 이벤트의 핸들러 함수

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + + + + +
      An instance of a component itself
      +

      컴포넌트 자신의 인스턴스

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "hi": function(){},
      +            "some": function(){
      +                this.on("hi",this.hi); //attach event
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + option(key, value){eg.Component|Object} +

      + + + + +
      + + +
      +
      + + +
      +

      Sets options in a component or returns them.

      +
      + + +
      +

      컴포넌트에 옵션을 설정하거나 옵션을 반환한다

      +
      + + + + + + + + + +
        + +
      • + +
        + key + + + + + + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The key of the option

        +

        옵션의 키

        + +
        + + + +
      • + +
      • + +
        + value + + + + + optional + + + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The option value that corresponds to a given key

        +

        키에 해당하는 옵션값

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + | + + Object + + + + +
      An instance, an option value, or an option object of a component itself.
      - If both key and value are used to set an option, it returns an instance of a component itself.
      - If only a key is specified for the parameter, it returns the option value corresponding to a given key.
      - If nothing is specified, it returns an option object.
      +

      컴포넌트 자신의 인스턴스나 옵션값, 옵션 객체.
      - 키와 값으로 옵션을 설정하면 컴포넌트 자신의 인스턴스를 반환한다.
      - 파라미터에 키만 설정하면 키에 해당하는 옵션값을 반환한다.
      - 파라미터에 아무것도 설정하지 않으면 옵션 객체를 반환한다.

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component);
      +        var some = new Some({
      +            "foo": 1,
      +            "bar": 2,
      +        });
      +        some.option("foo"); // return 1
      +        some.option("foo",3); // return some instance
      +        some.option(); // return options object.
      +        some.option({
      +            "foo" : 10,
      +            "bar" : 20,
      +            "baz" : 30
      +        }); // return some instance.
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + prepend(elements, groupKey){Number} +

      + + + + +
      + + +
      +
      + + +
      +

      Adds a card element at the top of a grid layout. This method is available only if the isProcessing() method returns false and the isRecycling() method returns true.

      +
      + + +
      +

      카드 엘리먼트를 그리드 레이아웃의 위에 추가한다. isProcessing() 메서드의 반환값이 'false'이고, isRecycling() 메서드의 반환값이 'true'일 때만 이 메서드를 사용할 수 있다

      +
      + + + + + + + + + +
        + +
      • + +
        + elements + + + + + + + + +
        + + +
        Type: +Array +| + +String +| + +jQuery + +
        + + + +
        + +

        Array of the card elements to be added

        +

        추가할 카드 엘리먼트 배열

        + +
        + + + +
      • + +
      • + +
        + groupKey + + + + + optional + + + + + +
        + + +
        Type: +Number +| + +String + +
        + + + +
        + +

        The group key to be configured in a card element. It is set to "undefined" by default.

        +

        추가할 카드 엘리먼트에 설정할 그룹 키. 생략하면 값이 'undefined'로 설정된다

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Number + + + + +
      The number of added card elements
      +

      추가된 카드 엘리먼트의 개수

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + setStatus(status){eg.InfiniteGrid} +

      + + + + +
      + + +
      +
      + + +
      +

      Sets the state of the eg.InfiniteGrid module with the information returned through a call to the getStatue() method.

      +
      + + +
      +

      getStatue() 메서드가 저장한 정보로 eg.InfiniteGrid 모듈의 상태를 설정한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + status + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        State object of the eg.InfiniteGrid module

        +

        eg.InfiniteGrid 모듈의 상태 객체

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.InfiniteGrid + + + + +
      An instance of a module itself
      +

      모듈 자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + trigger(eventName, customEvent){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Triggers a custom event.

      +
      + + +
      +

      커스텀 이벤트를 발생시킨다

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the custom event to be triggered

        +

        발생할 커스텀 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + customEvent + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        Event data to be sent when triggering a custom event

        +

        커스텀 이벤트가 발생할 때 전달할 데이터

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring.
      +

      이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다.

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "some": function(){
      +                this.trigger("hi");// fire hi event.
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + + + +

      Events

      + +
      + +
      +
      +

      + + append +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when a card element must be added at the bottom of a grid layout because there is no card to be displayed on screen when a user scrolls near bottom.

      +
      + + +
      +

      카드 엘리먼트가 그리드 레이아웃의 아래에 추가돼야 할 때 발생하는 이벤트. 사용자가 아래로 스크롤해서 화면에 표시될 카드가 없을 때 발생한다

      +
      + + + + + + + + + +
        + +
      • + +
        + param + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The object of data to be sent to an event

        +

        이벤트에 전달되는 데이터 객체

        + +
        + + + + + +
          + +
        • + +
          + scrollTop + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          Current vertical position of the scroll bar

          +

          현재 스크롤의 y 좌표 값

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + layoutComplete +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when layout is successfully arranged through a call to the append(), prepend(), or layout() method.

      +
      + + +
      +

      레이아웃 배치가 완료됐을 때 발생하는 이벤트. append() 메서드나 prepend() 메서드, layout() 메서드 호출 후 카드의 배치가 완료됐을 때 발생한다

      +
      + + + + + + + + + +
        + +
      • + +
        + param + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The object of data to be sent to an event

        +

        이벤트에 전달되는 데이터 객체

        + +
        + + + + + +
          + +
        • + +
          + target + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          Rearranged card elements

          +

          재배치된 카드 엘리먼트들

          + +
          + + + +
        • + +
        • + +
          + isAppend + + + +
          + + +
          Type: +Boolean + +
          + + + +
          + +

          Checks whether the append() method is used to add a card element. It returns true even though the layoutComplete event is fired after the layout() method is called.

          +

          카드 엘리먼트가 append() 메서드로 추가됐는지 확인한다. layout() 메서드가 호출된 후 layoutComplete 이벤트가 발생해도 'true'를 반환한다.

          + +
          + + + +
        • + +
        • + +
          + distance + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          Distance the card element at the top of a grid layout has moved after the layoutComplete event is fired. In other words, it is the same as an increased height with a new card element added using the prepend() method

          +

          그리드 레이아웃의 맨 위에 있던 카드 엘리먼트가 layoutComplete 이벤트 발생 후 이동한 거리. 즉, prepend() 메서드로 카드 엘리먼트가 추가돼 늘어난 높이다.

          + +
          + + + +
        • + +
        • + +
          + croppedCount + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          The number of deleted card elements to maintain the number of DOMs

          +

          일정한 DOM 개수를 유지하기 위해, 삭제한 카드 엘리먼트들의 개수

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + prepend +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when a card element must be added at the top of a grid layout because there is no card to be displayed on screen when a user scrolls near top. This event is available only if the isRecycling() method returns true.

      +
      + + +
      +

      카드가 그리드 레이아웃의 위에 추가돼야 할 때 발생하는 이벤트. 사용자가 위로 스크롤해서 화면에 표시될 카드가 없을 때 발생한다. 이 이벤트는 isRecycling() 메서드의 반환값이 'true'일 때만 발생한다

      +
      + + + + + + + + + +
        + +
      • + +
        + param + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The object of data to be sent to an event

        +

        이벤트에 전달되는 데이터 객체

        + +
        + + + + + +
          + +
        • + +
          + scrollTop + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          Current vertical position of the scroll bar

          +

          현재 스크롤의 y 좌표 값

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + +
      + +
      + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:20 GMT+0900 (KST) +
      +
      +
      + + + + + \ No newline at end of file diff --git a/doc/eg.MovableCoord.html b/doc/eg.MovableCoord.html new file mode 100644 index 00000000..59ee1304 --- /dev/null +++ b/doc/eg.MovableCoord.html @@ -0,0 +1,5230 @@ + + + + + Class: MovableCoord | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Class: MovableCoord

      + + + + +
      + +
      +

      + eg. + + MovableCoord +

      + + +
      + +
      +
      + + + + +
      +
      +

      + + new eg.MovableCoord(options) +

      + + + + +
      + + +
      +
      + + +
      +

      A module used to change the information of user action entered by various input devices such as touch screen or mouse into logical coordinates within the virtual coordinate system. The coordinate information sorted by time events occurred is provided if animations are made by user actions. You can implement a user interface by applying the logical coordinates provided. For more information on the eg.MovableCoord module, see demos.

      +
      + + +
      +

      터치 입력 장치나 마우스와 같은 다양한 입력 장치로 전달 받은 사용자의 동작을 가상 좌표계의 논리적 좌표로 변경하는 모듈. 사용자의 동작으로 애니메이션이 일어나면 시간순으로 변경되는 좌표 정보도 제공한다. 변경된 논리적 좌표를 반영해 UI를 구현할 수 있다. eg.MovableCoord 모듈의 자세한 작동 방식은 데모를 참고한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + options + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The option object of the eg.MovableCoord module

        +

        eg.MovableCoord 모듈의 옵션 객체

        + +
        + + + + + +
          + +
        • + +
          + min + + + + + + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          The minimum value of X and Y coordinates

          +

          좌표계의 최솟값

          + +
          + + + + + +
            + +
          • + +
            + 0 + + (default: 0) + + + + + optional + + + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The X coordinate of the minimum

            +

            최소 x좌표

            + +
            + + + +
          • + +
          • + +
            + 1 + + (default: 0) + + + + + optional + + + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The Y coordinate of the minimum

            +

            최소 y좌표

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + max + + + + + + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          The maximum value of X and Y coordinates

          +

          좌표계의 최댓값

          + +
          + + + + + +
            + +
          • + +
            + 0 + + (default: 100) + + + + + optional + + + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The X coordinate of the maximum

            +

            최대 x좌표

            + +
            + + + +
          • + +
          • + +
            + 1 + + (default: 100) + + + + + optional + + + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The Y coordinate of the maximum

            +

            최대 y좌표

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + bounce + + + + + + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          The size of bouncing area. The coordinates can exceed the coordinate area as much as the bouncing area based on user action. If the coordinates does not exceed the bouncing area when an element is dragged, the coordinates where bouncing effects are applied are retuned back into the coordinate area

          +

          바운스 영역의 크기. 사용자의 동작에 따라 좌표가 좌표 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 사용자가 끌어다 놓는 동작을 했을 때 좌표가 바운스 영역에 있으면, 바운스 효과가 적용된 좌표가 다시 좌표 영역 안으로 들어온다

          + +
          + + + + + +
            + +
          • + +
            + 0 + + (default: 10) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of top area

            +

            위쪽 바운스 영역의 크기

            + +
            + + + +
          • + +
          • + +
            + 1 + + (default: 10) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of right area

            +

            오른쪽 바운스 영역의 크기

            + +
            + + + +
          • + +
          • + +
            + 2 + + (default: 10) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of bottom area

            +

            아래쪽 바운스 영역의 크기

            + +
            + + + +
          • + +
          • + +
            + 3 + + (default: 10) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of left area

            +

            왼쪽 바운스 영역의 크기

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + margin + + + + + + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          The size of accessible space outside the coordinate area. If an element is dragged outside the coordinate area and then dropped, the coordinates of the element are returned back into the coordinate area. The size of margins that can be exceeded

          +

          − 좌표 영역을 넘어 이동할 수 있는 바깥 영역의 크기. 사용자가 좌표를 바깥 영역까지 끌었다가 놓으면 좌표가 좌표 영역 안으로 들어온다.

          + +
          + + + + + +
            + +
          • + +
            + 0 + + (default: 0) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of top margin

            +

            위쪽 바깥 영역의 크기

            + +
            + + + +
          • + +
          • + +
            + 1 + + (default: 0) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of right margin

            +

            오른쪽 바깥 영역의 크기

            + +
            + + + +
          • + +
          • + +
            + 2 + + (default: 0) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of bottom margin

            +

            아래쪽 바깥 영역의 크기

            + +
            + + + +
          • + +
          • + +
            + 3 + + (default: 0) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The size of left margin

            +

            왼쪽 바깥 영역의 크기

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + circular + + + + + + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          Indicates whether a circular element is available. If it is set to "true" and an element is dragged outside the coordinate area, the element will appear on the other side.

          +

          순환 여부. 'true'로 설정한 방향의 좌표 영역 밖으로 엘리먼트가 이동하면 반대 방향에서 엘리먼트가 나타난다

          + +
          + + + + + +
            + +
          • + +
            + 0 + + (default: false) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            Indicates whether to circulate to top

            +

            위로 순환 여부

            + +
            + + + +
          • + +
          • + +
            + 1 + + (default: false) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            Indicates whether to circulate to right

            +

            오른쪽으로 순환 여부

            + +
            + + + +
          • + +
          • + +
            + 2 + + (default: false) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            Indicates whether to circulate to bottom

            +

            아래로 순환 여부

            + +
            + + + +
          • + +
          • + +
            + 3 + + (default: false) + + + + + optional + + + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            Indicates whether to circulate to left

            +

            왼쪽으로 순환 여부

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + easing + + (default: easing.easeOutCubic) + + + + + optional + + + + + +
          + + +
          Type: +function + +
          + + + +
          + +

          The easing function to apply to an animation

          +

          애니메이션에 적용할 easing 함수

          + +
          + + + +
        • + +
        • + +
          + maximumDuration + + (default: Infinity) + + + + + optional + + + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          Maximum duration of the animation

          +

          가속도에 의해 애니메이션이 동작할 때의 최대 좌표 이동 시간

          + +
          + + + +
        • + +
        • + +
          + deceleration + + (default: 0.0006) + + + + + optional + + + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time.

          +

          사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + +
      See:
      +
      +
        +
      • HammerJS http://hammerjs.github.io
      • + +
      • • Hammer.JS applies specific CSS properties by default when creating an instance (See http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html). The eg.MovableCoord module removes all default CSS properties provided by Hammer.JS Hammer.JS는 인스턴스를 생성할 때 기본으로 특정 CSS 속성을 적용한다(참고: @link{http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}). 특정한 상황에서는 Hammer.JS의 속성 때문에 사용성에 문제가 있을 수 있다. eg.MovableCoord 모듈은 Hammer.JS의 기본 CSS 속성을 모두 제거했다
      • + +
      • Easing Functions Cheat Sheet http://easings.net/
      • + +
      • If you want to try a different easing function, use the jQuery easing plugin (http://gsgd.co.uk/sandbox/jquery/easing) or the jQuery UI easing library (https://jqueryui.com/easing) 다른 easing 함수를 사용하려면 jQuery easing 플러그인(http://gsgd.co.uk/sandbox/jquery/easing)이나, jQuery UI easing 라이브러리({@lin https://jqueryui.com/easing})를 사용한다
      • +
      +
      + + + + + + +

      Codepen:

      + + + + + + + + +
      MovableCoord Cube 예제
      +
      MovableCoord Cube example
      +

      See the Pen eg.Flicking by egjs (@egjs) on CodePen.

      + + + +
      + +
      + + + + +

      Browser Support

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      BrowserVersion
      Desktop - Internet Explorer10+
      Desktop - Chromelatest
      Desktop - Firefoxlatest
      Desktop - Safarilatest
      Desktop - Edgelatest
      iOS7+
      Andorid2.3+ (except 3.x)
      + + + + +
      + + + +

      Extends

      + + + + + + + + + + + + + +

      Members

      + +
      + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_ALLNumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_DOWNNumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_HORIZONTALNumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_LEFTNumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_NONENumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_RIGHTNumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_UPNumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + +
      +
      +

      static,constanteg.MovableCoord.DIRECTION_VERTICALNumber

      +
      + +
      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + +
      + + + +

      Methods

      + +
      + +
      +
      +

      + + bind(element, options){eg.MovableCoord} +

      + + + + +
      + + +
      +
      + + +
      +

      Registers an element to use the eg.MovableCoord module.

      +
      + + +
      +

      eg.MovableCoord 모듈을 사용할 엘리먼트를 등록한다

      +
      + + + + + + + + + +
        + +
      • + +
        + element + + + +
        + + +
        Type: +HTMLElement +| + +String +| + +jQuery + +
        + + + +
        + +

        Element to use the eg.MovableCoord module

        +

        − eg.MovableCoord 모듈을 사용할 엘리먼트

        + +
        + + + +
      • + +
      • + +
        + options + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The option object of the bind() method

        +

        bind() 메서드의 옵션 객체

        + +
        + + + + + +
          + +
        • + +
          + direction + + (default: eg.MovableCoord.DIRECTION_ALL) + + + + + optional + + + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          Coordinate direction that a user can move
          - eg.MovableCoord.DIRECTION_ALL: All directions available.
          - eg.MovableCoord.DIRECTION_HORIZONTAL: Horizontal direction only.
          - eg.MovableCoord.DIRECTION_VERTICAL: Vertical direction only

          +

          사용자의 동작으로 움직일 수 있는 좌표의 방향.
          - eg.MovableCoord.DIRECTION_ALL: 모든 방향으로 움직일 수 있다.
          - eg.MovableCoord.DIRECTION_HORIZONTAL: 가로 방향으로만 움직일 수 있다.
          - eg.MovableCoord.DIRECTION_VERTICAL: 세로 방향으로만 움직일 수 있다.

          + +
          + + + +
        • + +
        • + +
          + scale + + + + + + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          Coordinate scale that a user can move

          +

          사용자의 동작으로 이동하는 좌표의 배율

          + +
          + + + + + +
            + +
          • + +
            + 0 + + (default: 1) + + + + + optional + + + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            X-axis scale

            +

            x축 배율

            + +
            + + + +
          • + +
          • + +
            + 1 + + (default: 1) + + + + + optional + + + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            Y-axis scale

            +

            y축 배율

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + thresholdAngle + + (default: 45) + + + + + optional + + + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          The threshold value that determines whether user action is horizontal or vertical (0~90)

          +

          사용자의 동작이 가로 방향인지 세로 방향인지 판단하는 기준 각도(0~90)

          + +
          + + + +
        • + +
        • + +
          + interruptable + + (default: true) + + + + + optional + + + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          Indicates whether an animation is interruptible.
          - true: It can be paused or stopped by user action or the API.
          - false: It cannot be paused or stopped by user action or the API while it is running.

          +

          진행 중인 애니메이션 중지 가능 여부.
          - true: 사용자의 동작이나 API로 애니메이션을 중지할 수 있다.
          - false: 애니메이션이 진행 중일 때는 사용자의 동작이나 API가 적용되지 않는다

          + +
          + + + +
        • + +
        • + +
          + inputType + + + + + optional + + + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          Types of input devices. (default: ["touch", "mouse"])
          - touch: Touch screen
          - mouse: Mouse

          +

          입력 장치 종류.(기본값: ["touch", "mouse"])
          - touch: 터치 입력 장치
          - mouse: 마우스

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.MovableCoord + + + + +
      An instance of a module itself
      +

      모듈 자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + destroy() +

      + + + + +
      + + +
      +
      + + +
      +

      Destroys elements, properties, and events used in a module.

      +
      + + +
      +

      모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다.

      +
      + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + get(){Array} +

      + + + + +
      + + +
      +
      + + +
      +

      Returns the current position of the logical coordinates.

      +
      + + +
      +

      논리적 좌표의 현재 위치를 반환한다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      NameTypeDescription
      pos + + Array + + + + +
      +

      좌표

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      NameTypeDescription
      0 + + Number + + + + +
      The X coordinate
      +

      x 좌표

      + + + +
      1 + + Number + + + + +
      The Y coordinate
      +

      y 좌표

      + + + +
      + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + hasOn(eventName){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether an event has been attached to a component.

      +
      + + +
      +

      컴포넌트에 이벤트가 등록됐는지 확인한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event to be attached

        +

        등록 여부를 확인할 이벤트의 이름

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether the event is attached.
      +

      이벤트 등록 여부

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "some": function(){
      +                this.hasOn("hi");// check hi event.
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + off(eventName, handlerToDetach){eg.Component} +

      + + + + +
      + + +
      +
      + + +
      +

      Detaches an event from the component.

      +
      + + +
      +

      컴포넌트에 등록된 이벤트를 해제한다

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +eventName + +
        + + + +
        + +

        The name of the event to be detached

        +

        해제할 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + handlerToDetach + + + +
        + + +
        Type: +function + +
        + + + +
        + +

        The handler function of the event to be detached

        +

        해제할 이벤트의 핸들러 함수

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + + + + +
      An instance of a component itself
      +

      컴포넌트 자신의 인스턴스

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "hi": function(){},
      +            "some": function(){
      +                this.off("hi",this.hi); //detach event
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + on(eventName, handlerToAttach){eg.Component} +

      + + + + +
      + + +
      +
      + + +
      +

      Attaches an event to a component.

      +
      + + +
      +

      컴포넌트에 이벤트를 등록한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +eventName + +
        + + + +
        + +

        The name of the event to be attached

        +

        등록할 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + handlerToAttach + + + +
        + + +
        Type: +function + +
        + + + +
        + +

        The handler function of the event to be attached

        +

        등록할 이벤트의 핸들러 함수

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + + + + +
      An instance of a component itself
      +

      컴포넌트 자신의 인스턴스

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "hi": function(){},
      +            "some": function(){
      +                this.on("hi",this.hi); //attach event
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + option(key, value){eg.Component|Object} +

      + + + + +
      + + +
      +
      + + +
      +

      Sets options in a component or returns them.

      +
      + + +
      +

      컴포넌트에 옵션을 설정하거나 옵션을 반환한다

      +
      + + + + + + + + + +
        + +
      • + +
        + key + + + + + + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The key of the option

        +

        옵션의 키

        + +
        + + + +
      • + +
      • + +
        + value + + + + + optional + + + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The option value that corresponds to a given key

        +

        키에 해당하는 옵션값

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + | + + Object + + + + +
      An instance, an option value, or an option object of a component itself.
      - If both key and value are used to set an option, it returns an instance of a component itself.
      - If only a key is specified for the parameter, it returns the option value corresponding to a given key.
      - If nothing is specified, it returns an option object.
      +

      컴포넌트 자신의 인스턴스나 옵션값, 옵션 객체.
      - 키와 값으로 옵션을 설정하면 컴포넌트 자신의 인스턴스를 반환한다.
      - 파라미터에 키만 설정하면 키에 해당하는 옵션값을 반환한다.
      - 파라미터에 아무것도 설정하지 않으면 옵션 객체를 반환한다.

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component);
      +        var some = new Some({
      +            "foo": 1,
      +            "bar": 2,
      +        });
      +        some.option("foo"); // return 1
      +        some.option("foo",3); // return some instance
      +        some.option(); // return options object.
      +        some.option({
      +            "foo" : 10,
      +            "bar" : 20,
      +            "baz" : 30
      +        }); // return some instance.
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + setBy(x, y, duration){eg.MovableCoord} +

      + + + + +
      + + +
      +
      + + +
      +

      Moves an element from the current coordinates to specific coordinates. The change event is fired when the method is executed.

      +
      + + +
      +

      현재 좌표를 기준으로 좌표를 이동한다. 메서드가 실행되면 change 이벤트가 발생한다

      +
      + + + + + + + + + +
        + +
      • + +
        + x + + + + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        The X coordinate to move to

        +

        이동할 x좌표

        + +
        + + + +
      • + +
      • + +
        + y + + + + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        The Y coordinate to move to

        +

        이동할 y좌표

        + +
        + + + +
      • + +
      • + +
        + duration + + (default: 0) + + + + + optional + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Duration of the animation (unit: ms)

        +

        애니메이션 진행 시간(단위: ms)

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.MovableCoord + + + + +
      An instance of a module itself
      +

      자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + setTo(x, y, duration){eg.MovableCoord} +

      + + + + +
      + + +
      +
      + + +
      +

      Moves an element to specific coordinates.

      +
      + + +
      +

      좌표를 이동한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + x + + + + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        The X coordinate to move to

        +

        이동할 x좌표

        + +
        + + + +
      • + +
      • + +
        + y + + + + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        The Y coordinate to move to

        +

        이동할 y좌표

        + +
        + + + +
      • + +
      • + +
        + duration + + (default: 0) + + + + + optional + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Duration of the animation (unit: ms)

        +

        애니메이션 진행 시간(단위: ms)

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.MovableCoord + + + + +
      An instance of a module itself
      +

      자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + trigger(eventName, customEvent){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Triggers a custom event.

      +
      + + +
      +

      커스텀 이벤트를 발생시킨다

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the custom event to be triggered

        +

        발생할 커스텀 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + customEvent + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        Event data to be sent when triggering a custom event

        +

        커스텀 이벤트가 발생할 때 전달할 데이터

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring.
      +

      이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다.

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "some": function(){
      +                this.trigger("hi");// fire hi event.
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + unbind(element){eg.MovableCoord} +

      + + + + +
      + + +
      +
      + + +
      +

      Detaches elements using the eg.MovableCoord module.

      +
      + + +
      +

      eg.MovableCoord 모듈을 사용하는 엘리먼트를 해제한다

      +
      + + + + + + + + + +
        + +
      • + +
        + element + + + +
        + + +
        Type: +HTMLElement +| + +String +| + +jQuery + +
        + + + +
        + +

        Elements from which the eg.MovableCoord module is detached

        +

        eg.MovableCoord 모듈을 해제할 엘리먼트

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.MovableCoord + + + + +
      An instance of a module itself
      +

      모듈 자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + + + +

      Events

      + +
      + +
      +
      +

      + + animationEnd +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when animation ends.

      +
      + + +
      +

      에니메이션이 끝났을 때 발생한다.

      +
      + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + change +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when coordinate changes.

      +
      + + +
      +

      좌표가 변경됐을 때 발생하는 이벤트

      +
      + + + + + + + + + +
        + +
      • + +
        + param + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The object of data to be sent when the event is fired

        +

        이벤트가 발생할 때 전달되는 데이터 객체

        + +
        + + + + + +
          + +
        • + +
          + pos + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          departure coordinate

          +

          좌표

          + +
          + + + + + +
            + +
          • + +
            + 0 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The X coordinate

            +

            x 좌표

            + +
            + + + +
          • + +
          • + +
            + 1 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The Y coordinate

            +

            y 좌표

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + holding + + + +
          + + +
          Type: +Boolean + +
          + + + +
          + +

          Indicates whether a user holds an element on the screen of the device.

          +

          사용자가 기기의 화면을 누르고 있는지 여부

          + +
          + + + +
        • + +
        • + +
          + hammerEvent + + + +
          + + +
          Type: +Object + +
          + + + +
          + +

          The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.

          +

          Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다.

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + hold +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when a user holds an element on the screen of the device.

      +
      + + +
      +

      사용자가 기기의 화면에 손을 대고 있을 때 발생하는 이벤트

      +
      + + + + + + + + + +
        + +
      • + +
        + param + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The object of data to be sent when the event is fired

        +

        이벤트가 발생할 때 전달되는 데이터 객체

        + +
        + + + + + +
          + +
        • + +
          + pos + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          coordinate

          +

          좌표 정보

          + +
          + + + + + +
            + +
          • + +
            + 0 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The X coordinate

            +

            x 좌표

            + +
            + + + +
          • + +
          • + +
            + 1 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The Y coordinate

            +

            y 좌표

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + hammerEvent + + + +
          + + +
          Type: +Object + +
          + + + +
          + +

          The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.

          +

          Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다.

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + release +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when a user release an element on the screen of the device.

      +
      + + +
      +

      사용자가 기기의 화면에서 손을 뗐을 때 발생하는 이벤트

      +
      + + + + + + + + + +
        + +
      • + +
        + param + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The object of data to be sent when the event is fired

        +

        이벤트가 발생할 때 전달되는 데이터 객체

        + +
        + + + + + +
          + +
        • + +
          + depaPos + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          The coordinates when releasing an element

          +

          손을 뗐을 때의 좌표현재

          + +
          + + + + + +
            + +
          • + +
            + 0 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The X coordinate

            +

            x 좌표

            + +
            + + + +
          • + +
          • + +
            + 1 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The Y coordinate

            +

            y 좌표

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + destPos + + + +
          + + +
          Type: +Array + +
          + + + +
          + +

          The coordinates to move to after releasing an element

          +

          손을 뗀 뒤에 이동할 좌표

          + +
          + + + + + +
            + +
          • + +
            + 0 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The X coordinate

            +

            x 좌표

            + +
            + + + +
          • + +
          • + +
            + 1 + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The Y coordinate

            +

            y 좌표

            + +
            + + + +
          • + +
          + +
        • + +
        • + +
          + hammerEvent + + + +
          + + +
          Type: +Object + +
          + + + +
          + +

          The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.

          +

          Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + +
      + +
      + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:21 GMT+0900 (KST) +
      +
      +
      + + + + + \ No newline at end of file diff --git a/doc/eg.Visible.html b/doc/eg.Visible.html new file mode 100644 index 00000000..c1e8c28a --- /dev/null +++ b/doc/eg.Visible.html @@ -0,0 +1,2285 @@ + + + + + Class: Visible | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Class: Visible

      + + + + +
      + +
      +

      + eg. + + Visible +

      + + +
      + +
      +
      + + + + +
      +
      +

      + + new eg.Visible(element, options) +

      + + + + +
      + + +
      +
      + + +
      +

      A module used to check whether an element is visible in the base element or viewport.

      +
      + + +
      +

      엘리먼트가 기준 엘리먼트나 뷰포트 안에 보이는지 확인하는 모듈

      +
      + + + + + + + + + +
        + +
      • + +
        + element + + (default: document) + + + + + optional + + + + + +
        + + +
        Type: +HTMLElement +| + +String +| + +jQuery + +
        + + + +
        + +

        A base element that detects if another element is visible

        +

        엘리먼트가 보이는 기준 엘리먼트

        + +
        + + + +
      • + +
      • + +
        + options + + + + + + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The option object of the eg.Visible module

        +

        eg.Visible 모듈의 옵션 객체

        + +
        + + + + + +
          + +
        • + +
          + targetClass + + (default: "check_visible") + + + + + optional + + + + + +
          + + +
          Type: +String + +
          + + + +
          + +

          The class name of the element to be checked

          +

          보이는지 확인할 엘리먼트의 클래스 이름

          + +
          + + + +
        • + +
        • + +
          + expandSize + + (default: 0) + + + + + optional + + + + + +
          + + +
          Type: +Number + +
          + + + +
          + +

          The size of the expanded area to be checked whether an element is visible. If this value is less than zero, the size of the area is smaller than that of the base element.

          +

          기준 엘리먼트의 경계를 넘어 엘리먼트가 보이는지 확인할 영역의 크기. 값이 0보다 작으면 엘리먼트가 보이는지 확인할 영역의 크기가 기준 엘리먼트보다 작아진다

          + +
          + + + +
        • + +
        + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +

      Codepen:

      + + + + + + + + +
      Visible 기본 예제
      +
      Visible basic example
      +

      See the Pen eg.Flicking by egjs (@egjs) on CodePen.

      + + + +
      + +
      + + + + +

      Browser Support

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      BrowserVersion
      Desktop - Internet Explorer7+
      Desktop - Chromelatest
      Desktop - Firefoxlatest
      Desktop - Safarilatest
      Desktop - Edgelatest
      iOS7+
      Andorid2.1+ (except 3.x)
      + + + + +
      + + + +

      Extends

      + + + + + + + + + + + + + + + +

      Methods

      + +
      + +
      +
      +

      + + check(delay){eg.Visible} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether the visibility property of the target elements has changed. The change event is fired when the property has changed.

      +
      + + +
      +

      보이는지 확인할 대상 엘리먼트 목록의 visibility 속성이 변경됐는지 확인한다. 속성이 변경됐으면 change 이벤트가 발생한다

      +
      + + + + + + + + + +
        + +
      • + +
        + delay + + (default: -1) + + + + + optional + + + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Delay time. It is used to check the property after a method is called and a period of time has passed.

        +

        속성 확인 지연 시간. 메서드를 호출하고 일정 시간이 지난 후에 속성을 확인할 때 사용한다

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Visible + + + + +
      An instance of a module itself
      +

      모듈 자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + hasOn(eventName){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether an event has been attached to a component.

      +
      + + +
      +

      컴포넌트에 이벤트가 등록됐는지 확인한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the event to be attached

        +

        등록 여부를 확인할 이벤트의 이름

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether the event is attached.
      +

      이벤트 등록 여부

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "some": function(){
      +                this.hasOn("hi");// check hi event.
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + off(eventName, handlerToDetach){eg.Component} +

      + + + + +
      + + +
      +
      + + +
      +

      Detaches an event from the component.

      +
      + + +
      +

      컴포넌트에 등록된 이벤트를 해제한다

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +eventName + +
        + + + +
        + +

        The name of the event to be detached

        +

        해제할 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + handlerToDetach + + + +
        + + +
        Type: +function + +
        + + + +
        + +

        The handler function of the event to be detached

        +

        해제할 이벤트의 핸들러 함수

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + + + + +
      An instance of a component itself
      +

      컴포넌트 자신의 인스턴스

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "hi": function(){},
      +            "some": function(){
      +                this.off("hi",this.hi); //detach event
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + on(eventName, handlerToAttach){eg.Component} +

      + + + + +
      + + +
      +
      + + +
      +

      Attaches an event to a component.

      +
      + + +
      +

      컴포넌트에 이벤트를 등록한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +eventName + +
        + + + +
        + +

        The name of the event to be attached

        +

        등록할 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + handlerToAttach + + + +
        + + +
        Type: +function + +
        + + + +
        + +

        The handler function of the event to be attached

        +

        등록할 이벤트의 핸들러 함수

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + + + + +
      An instance of a component itself
      +

      컴포넌트 자신의 인스턴스

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "hi": function(){},
      +            "some": function(){
      +                this.on("hi",this.hi); //attach event
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + option(key, value){eg.Component|Object} +

      + + + + +
      + + +
      +
      + + +
      +

      Sets options in a component or returns them.

      +
      + + +
      +

      컴포넌트에 옵션을 설정하거나 옵션을 반환한다

      +
      + + + + + + + + + +
        + +
      • + +
        + key + + + + + + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The key of the option

        +

        옵션의 키

        + +
        + + + +
      • + +
      • + +
        + value + + + + + optional + + + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The option value that corresponds to a given key

        +

        키에 해당하는 옵션값

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Component + | + + Object + + + + +
      An instance, an option value, or an option object of a component itself.
      - If both key and value are used to set an option, it returns an instance of a component itself.
      - If only a key is specified for the parameter, it returns the option value corresponding to a given key.
      - If nothing is specified, it returns an option object.
      +

      컴포넌트 자신의 인스턴스나 옵션값, 옵션 객체.
      - 키와 값으로 옵션을 설정하면 컴포넌트 자신의 인스턴스를 반환한다.
      - 파라미터에 키만 설정하면 키에 해당하는 옵션값을 반환한다.
      - 파라미터에 아무것도 설정하지 않으면 옵션 객체를 반환한다.

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component);
      +        var some = new Some({
      +            "foo": 1,
      +            "bar": 2,
      +        });
      +        some.option("foo"); // return 1
      +        some.option("foo",3); // return some instance
      +        some.option(); // return options object.
      +        some.option({
      +            "foo" : 10,
      +            "bar" : 20,
      +            "baz" : 30
      +        }); // return some instance.
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + refresh(){eg.Visible} +

      + + + + +
      + + +
      +
      + + +
      +

      Updates the list of elements where the visibility property is to be checked

      +
      + + +
      +

      visibility 속성을 검사할 엘리먼트의 목록을 갱신한다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Visible + + + + +
      An instance of a module itself
      +

      모듈 자신의 인스턴스

      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + inherited + + trigger(eventName, customEvent){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Triggers a custom event.

      +
      + + +
      +

      커스텀 이벤트를 발생시킨다

      +
      + + + + + + + + + +
        + +
      • + +
        + eventName + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        The name of the custom event to be triggered

        +

        발생할 커스텀 이벤트의 이름

        + +
        + + + +
      • + +
      • + +
        + customEvent + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        Event data to be sent when triggering a custom event

        +

        커스텀 이벤트가 발생할 때 전달할 데이터

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring.
      +

      이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다.

      + + + +
      + + + + +
      Example
      + + + +
              var Some = eg.Class.extend(eg.Component,{
      +            "some": function(){
      +                this.trigger("hi");// fire hi event.
      +            }
      +        });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + + + +

      Events

      + +
      + +
      +
      +

      + + change +

      + + + + +
      + + +
      +
      + + +
      +

      This event is fired when the event is compared with the last verified one and there is an element of which the visibility property has changed.

      +
      + + +
      +

      마지막으로 확인한 결과와 비교해 visibility 속성이 변경된 엘리먼트가 있을 때 발생하는 이벤트

      +
      + + + + + + + + + +
        + +
      • + +
        + visible + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        Visible elements (the element type is HTMLElement)

        +

        보이게 된 엘리먼트들

        + +
        + + + +
      • + +
      • + +
        + invisible + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        Invisible elements (the element type is HTMLElement)

        +

        안 보이게 된 엘리먼트들

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + +
      + +
      + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:22 GMT+0900 (KST) +
      +
      +
      + + + + + \ No newline at end of file diff --git a/doc/eg.html b/doc/eg.html new file mode 100644 index 00000000..ac9b1293 --- /dev/null +++ b/doc/eg.html @@ -0,0 +1,1938 @@ + + + + + Namespace: eg | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Namespace: eg

      + + + + +
      + +
      +

      + eg +

      + + +
      + +
      +
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + + + + + + +

      Classes

      + +
      +
      Class
      +
      + +
      Component
      +
      + +
      Flicking
      +
      + +
      InfiniteGrid
      +
      + +
      MovableCoord
      +
      + +
      Visible
      +
      +
      + + + + + +

      Members

      + +
      + + +
      +
      +

      staticeg.VERSION

      +
      + +
      +
      + +
      +

      The version numbers of egjs.

      +
      + + +
      +

      egjs 버전

      +
      + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + +
      + + + +

      Methods

      + +
      + +
      +
      +

      + + agent(){Object} +

      + + +
      + eg.js, line 65 +
      + +
      + + +
      +
      + + +
      +

      Returns the User-Agent information

      +
      + + +
      +

      user-agent 정보를 반환한다.

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      NameTypeDescription
      agent + + Object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      NameTypeDescription
      os + + Object + + + + +
      os Operating system information
      +

      운영체제 정보

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      NameTypeDescription
      name + + String + + + + +
      Operating system name (android, ios, window, mac)
      +

      운영체제 이름 (android, ios, window, mac)

      + + + +
      version + + String + + + + +
      Operating system version
      +

      운영체제 버전

      + + + +
      + + +
      browser + + String + + + + +
      Browser information
      +

      브라우저 정보

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      NameTypeDescription
      name + + String + + + + +
      Browser name (default, safari, chrome, sbrowser, ie, firefox)
      +

      브라우저 이름 (default, safari, chrome, sbrowser, ie, firefox)

      + + + +
      version + + String + + + + +
      Browser version
      +

      브라우저 버전

      + + + +
      webview + + String + + + + +
      Indicates whether a WebView browser is available
      +

      웹뷰 브라우저 여부

      + + + +
      + + +
      + + +
      + + + + +
      Example
      + + + +

      eg.agent(); +// { +// os : { +// name : "ios", +// version : "8.2" +// }, +// browser : { +// name : "safari", +// version : "8.2" +// nativeVersion : "-1" +// } +// } +eg.hook.agent = function(agent) { +if(agent.os.name === "naver") { + agent.browser.name = "inapp"; + return agent; +} +}

      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + cancelAnimationFrame(key) +

      + + + + +
      + + +
      +
      + + +
      +

      A polyfill for the window.cancelAnimationFrame() method. It cancels an animation executed through a call to the requestAnimationFrame() method.

      +
      + + +
      +

      window.cancelAnimationFrame() 메서드의 polyfill 함수다. requestAnimationFrame() 메서드로 실행한 애니메이션을 중단한다

      +
      + + + + + + + + + +
        + +
      • + +
        + key + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        − The ID value returned through a call to the requestAnimationFrame() method.

        +

        requestAnimationFrame() 메서드가 반환한 아이디 값

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + +
      Example
      + + + +
          eg.cancelAnimationFrame(timerId);
      + + + + + +
      + + + + + + + + + + + + + + + + + + + +
      See:
      +
      + +
      + + + + + + +
      + +
      + + + +
      +
      +

      + + isHWAccelerable(){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether hardware acceleration is enabled.

      +
      + + +
      +

      하드웨어 가속을 사용할 수 있는 환경인지 확인한다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether hardware acceleration is enabled.
      +

      하드웨어 가속 사용 가능 여부

      + + + +
      + + + + +
      Example
      + + + +

      eg.isHWAccelerable(); // Returns 'true' when hardware acceleration is supported

      +

      // also, you can control return value +eg.hook.isHWAccelerable = function(defalutVal,agent) { +if(agent.os.name === "ios") { + // if os is 'ios', return value is 'false' + return false; +} else if(agent.browser.name === "chrome" ) { + // if browser is 'chrome', return value is 'true' + return true; +} +return defaultVal; +}

      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + isPortrait(){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether the current orientation of the device is portrait.

      +
      + + +
      +

      기기의 화면이 수직 방향인지 확인한다

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      The orientation of the device (true: portrait, false: landscape)
      +

      기기의 화면 방향(true: 수직 방향, false: 수평 방향)

      + + + +
      + + + + +
      Example
      + + + +

      eg.isPortrait(); // Check if device is in portrait mode

      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + isTransitional(){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Checks whether CSS transition properties can be used.

      +
      + + +
      +

      CSS 트랜지션 속성을 사용할 수 있는 환경인지 확인한다.

      +
      + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      Indicates whether CSS transition properties can be used.
      +

      CSS 트랜지션 속성 사용 가능 여부

      + + + +
      + + + + +
      Example
      + + + +

      eg.isTransitional(); // Returns 'true' when CSS transition is supported.

      +

      // also, you can control return value +eg.hook.isTransitional = function(defaultVal, agent) { +if(agent.os.name === "ios") { + // if os is 'ios', return value is 'false' + return false; +} else if(agent.browser.name === "chrome" ) { + // if browser is 'chrome', return value is 'true' + return true; +} +return defaultVal; +}

      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + requestAnimationFrame(timer){Number} +

      + + + + +
      + + +
      +
      + + +
      +

      A polyfill for the window.requestAnimationFrame() method.

      +
      + + +
      +

      window.requestAnimationFrame() 메서드의 polyfill 함수다

      +
      + + + + + + + + + +
        + +
      • + +
        + timer + + + +
        + + +
        Type: +function + +
        + + + +
        + +

        The function returned through a call to the requestAnimationFrame() method

        +

        requestAnimationFrame() 메서드가 호출할 함수

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Number + + + + +
      ID of the requestAnimationFrame() method.
      +

      requestAnimationFrame() 메서드의 아이디

      + + + +
      + + + + +
      Example
      + + + +
          var timerId = eg.requestAnimationFrame(function() {
      +        console.log("call");
      +    });
      + + + + + +
      + + + + + + + + + + + + + + + + + + + +
      See:
      +
      + +
      + + + + + + +
      + +
      + + + +
      +
      +

      + + translate(x, y, isHA){String} +

      + + + + +
      + + +
      +
      + + +
      +

      Returns the syntax of the translate style which is applied to CSS transition properties.

      +
      + + +
      +

      CSS 트랜지션 속성에 적용할 translate 스타일 구문을 반환한다

      +
      + + + + + + + + + +
        + +
      • + +
        + x + + + + + + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        Distance to move along the X axis

        +

        x축을 따라 이동할 거리

        + +
        + + + +
      • + +
      • + +
        + y + + + + + + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        Distance to move along the Y axis

        +

        y축을 따라 이동할 거리

        + +
        + + + +
      • + +
      • + +
        + isHA + + + + + optional + + + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +

        Force hardware acceleration

        +

        하드웨어 가속 사용 여부

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + String + + + + +
      Syntax of the translate style
      +

      translate 스타일 구문

      + + + +
      + + + + +
      Example
      + + + +

      eg.translate('10px', '200%'); // translate(10px,200%); +eg.translate('10px', '200%', true); // translate3d(10px,200%,0);

      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + + + + + +
      + +
      + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:18 GMT+0900 (KST) +
      +
      +
      + + + + + \ No newline at end of file diff --git a/doc/eg.js.html b/doc/eg.js.html new file mode 100644 index 00000000..3e96029d --- /dev/null +++ b/doc/eg.js.html @@ -0,0 +1,815 @@ + + + + + Source: eg.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Source: eg.js

      + + + + +
      +
      +
      /**
      +* Copyright (c) 2015 NAVER Corp.
      +* egjs projects are licensed under the MIT license
      +*/
      +
      +eg.module("eg", ["jQuery", eg, window, eg.Agent], function($, ns, global, Agent) {
      +	"use strict";
      +
      +	var raf = global.requestAnimationFrame || global.webkitRequestAnimationFrame ||
      +				global.mozRequestAnimationFrame || global.msRequestAnimationFrame;
      +	var caf = global.cancelAnimationFrame || global.webkitCancelAnimationFrame ||
      +				global.mozCancelAnimationFrame || global.msCancelAnimationFrame;
      +
      +	if (raf && !caf) {
      +		var keyInfo = {};
      +		var oldraf = raf;
      +		raf = function(callback) {
      +			function wrapCallback() {
      +				if (keyInfo[key]) {
      +					callback();
      +				}
      +			}
      +			var key = oldraf(wrapCallback);
      +			keyInfo[key] = true;
      +			return key;
      +		};
      +		caf = function(key) {
      +			delete keyInfo[key];
      +		};
      +	} else if (!(raf && caf)) {
      +		raf = function(callback) {
      +			return global.setTimeout(callback, 16);
      +		};
      +		caf = global.clearTimeout;
      +	}
      +
      +	function resultCache(scope, name, param, defaultValue) {
      +		var method = scope.hook[name];
      +		if (method) {
      +			defaultValue = method.apply(scope, param);
      +		}
      +
      +		scope[name] = function() {
      +			var method = scope.hook[name];
      +			if (method) {
      +				return method.apply(scope, param);
      +			}
      +			return defaultValue;
      +		};
      +		return defaultValue;
      +	}
      +
      +	/**
      +	 * @namespace eg
      +	 * @group egjs
      +	 */
      +
      +	/**
      +	 * @name eg.VERSION
      +	 * @description The version numbers of egjs.
      +	 * @ko egjs 버전
      +	 */
      +	ns.VERSION = "#__VERSION__#";
      +	ns.hook =  {};
      +	/**
      +	* Returns the User-Agent information
      +	* @ko user-agent 정보를 반환한다.
      +	* @method eg#agent
      +	* @return {Object} agent
      +	* @return {Object} agent.os os Operating system information <ko>운영체제 정보</ko>
      +	* @return {String} agent.os.name Operating system name (android, ios, window, mac) <ko>운영체제 이름 (android, ios, window, mac)</ko>
      +	* @return {String} agent.os.version Operating system version <ko>운영체제 버전</ko>
      +	* @return {String} agent.browser Browser information <ko>브라우저 정보</ko>
      +	* @return {String} agent.browser.name Browser name (default, safari, chrome, sbrowser, ie, firefox) <ko>브라우저 이름 (default, safari, chrome, sbrowser, ie, firefox)</ko>
      +	* @return {String} agent.browser.version Browser version <ko>브라우저 버전 </ko>
      +	* @return {String} agent.browser.webview Indicates whether a WebView browser is available<ko>웹뷰 브라우저 여부</ko>
      +	* @example
      +eg.agent();
      +// {
      +//     os : {
      +//          name : "ios",
      +//          version : "8.2"
      +//     },
      +//     browser : {
      +//          name : "safari",
      +//          version : "8.2"
      +//          nativeVersion : "-1"
      +//     }
      +// }
      +eg.hook.agent = function(agent) {
      +if(agent.os.name === "naver") {
      +	agent.browser.name = "inapp";
      +	return agent;
      +}
      +}
      +	*/
      +	ns.agent = function() {
      +		var info = Agent.create(global.navigator.userAgent);
      +		return resultCache(this, "agent", [info], info);
      +	};
      +
      +	/**
      +	 * Returns the syntax of the translate style which is applied to CSS transition properties.
      +	 *
      +	 * @ko CSS 트랜지션 속성에 적용할 translate 스타일 구문을 반환한다
      +	 * @method eg#translate
      +	 * @param {String} x Distance to move along the X axis <ko>x축을 따라 이동할 거리</ko>
      +	 * @param {String} y Distance to move along the Y axis <ko>y축을 따라 이동할 거리</ko>
      +	 * @param {Boolean} [isHA] Force hardware acceleration <ko>하드웨어 가속 사용 여부</ko>
      +	 * @return {String} Syntax of the translate style <ko>translate 스타일 구문</ko>
      +	 * @example
      +eg.translate('10px', '200%');  // translate(10px,200%);
      +eg.translate('10px', '200%', true);  // translate3d(10px,200%,0);
      +	 */
      +	ns.translate = function(x, y, isHA) {
      +		isHA = isHA || false;
      +		return "translate" + (isHA ?
      +								"3d(" : "(") + x + "," + y + (isHA ? ",0)" :
      +								")");
      +	};
      +
      +	/**
      +	 * Checks whether hardware acceleration is enabled.
      +	 *
      +	 * @ko 하드웨어 가속을 사용할 수 있는 환경인지 확인한다
      +	 * @method eg#isHWAccelerable
      +	 * @return {Boolean} Indicates whether hardware acceleration is enabled. <ko>하드웨어 가속 사용 가능 여부</ko>
      +	 * @example
      +eg.isHWAccelerable();  // Returns 'true' when hardware acceleration is supported
      +
      +// also, you can control return value
      +eg.hook.isHWAccelerable = function(defalutVal,agent) {
      +if(agent.os.name === "ios") {
      +	// if os is 'ios', return value is 'false'
      +	return false;
      +} else if(agent.browser.name === "chrome" ) {
      +	// if browser is 'chrome', return value is 'true'
      +	return true;
      +}
      +return defaultVal;
      +}
      +	 */
      +	ns.isHWAccelerable = function() {
      +		var result = false;
      +		var agent = ns.agent();
      +		var osVersion = agent.os.version;
      +		var browser = agent.browser.name;
      +		var browserVersion = agent.browser.version;
      +		var useragent;
      +
      +		// chrome 25- has a text blur bug (except Samsung's sbrowser)
      +		if (browser.indexOf("chrome") !== -1) {
      +			result = browserVersion >= "25";
      +		} else if (/ie|edge|firefox|safari|inapp/.test(browser)) {
      +			result = true;
      +		} else if (agent.os.name.indexOf("android") !== -1) {
      +			// for Xiaomi
      +			useragent = (Agent.ua.match(/\(.*\)/) || [null])[0];
      +
      +			// android 4.1+ blacklist
      +			// EK-GN120 : Galaxy Camera, SM-G386F : Galaxy Core LTE
      +			// SHW-M420 : Galaxy Nexus , SHW-M200 : NexusS , GT-S7562 : Galaxy S duos
      +			result = (osVersion >= "4.1.0" && !/EK-GN120|SM-G386F/.test(useragent)) ||
      +				(osVersion >= "4.0.3" &&
      +					/SHW-|SHV-|GT-|SCH-|SGH-|SPH-|LG-F160|LG-F100|LG-F180|LG-F200|EK-|IM-A|LG-F240|LG-F260/.test(useragent) && !/SHW-M420|SHW-M200|GT-S7562/.test(useragent));
      +		}
      +		return resultCache(this, "isHWAccelerable", [result, agent], result);
      +	};
      +
      +	/**
      +	 * Checks whether CSS transition properties can be used.
      +	 *
      +	 * @ko CSS 트랜지션 속성을 사용할 수 있는 환경인지 확인한다.
      +	 * @method eg#isTransitional
      +	 * @return {Boolean} Indicates whether CSS transition properties can be used. <ko>CSS 트랜지션 속성 사용 가능 여부</ko>
      +	 * @example
      +eg.isTransitional();  // Returns 'true' when CSS transition is supported.
      +
      +// also, you can control return value
      +eg.hook.isTransitional = function(defaultVal, agent) {
      +if(agent.os.name === "ios") {
      +	// if os is 'ios', return value is 'false'
      +	return false;
      +} else if(agent.browser.name === "chrome" ) {
      +	// if browser is 'chrome', return value is 'true'
      +	return true;
      +}
      +return defaultVal;
      +}
      +	 */
      +	ns.isTransitional = function() {
      +		var result = false;
      +		var agent = ns.agent();
      +		var browser = agent.browser.name;
      +
      +		if (/chrome|firefox|sbrowser/.test(browser)) {
      +			result = true;
      +		} else {
      +			switch (agent.os.name) {
      +				case "ios" :
      +					result = /safari|inapp/.test(browser) &&
      +							parseInt(agent.os.version, 10) < 6;
      +					break;
      +				case "window" :
      +					result = /safari/.test(browser) ||
      +							(/ie/.test(browser) &&
      +								parseInt(agent.browser.nativeVersion, 10) >= 10);
      +					break;
      +				default :
      +					result = /safari/.test(browser);
      +					break;
      +			}
      +		}
      +		return resultCache(this, "isTransitional", [result, agent], result);
      +	};
      +
      +	// 1. user press one position on screen.
      +	// 2. user moves to the other position on screen.
      +	// 3. when user releases fingers on screen, 'click' event is fired at previous position.
      +	ns._hasClickBug = function() {
      +		var agent = ns.agent();
      +		var result = agent.browser.name === "safari";
      +
      +		return resultCache(this, "_hasClickBug", [result, agent], result);
      +	};
      +
      +	/**
      +	* A polyfill for the window.requestAnimationFrame() method.
      +	* @ko window.requestAnimationFrame() 메서드의 polyfill 함수다
      +	* @method eg#requestAnimationFrame
      +	* @param {Function} timer The function returned through a call to the requestAnimationFrame() method <ko>requestAnimationFrame() 메서드가 호출할 함수</ko>
      +	* @return {Number} ID of the requestAnimationFrame() method. <ko>requestAnimationFrame() 메서드의 아이디</ko>
      +	* @example
      +		var timerId = eg.requestAnimationFrame(function() {
      +			console.log("call");
      +		});
      +	* @see  https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
      +	*/
      +	ns.requestAnimationFrame = function(fp) {
      +		return raf(fp);
      +	};
      +	/**
      +	* A polyfill for the window.cancelAnimationFrame() method. It cancels an animation executed through a call to the requestAnimationFrame() method.
      +	* @ko window.cancelAnimationFrame() 메서드의 polyfill 함수다. requestAnimationFrame() 메서드로 실행한 애니메이션을 중단한다
      +	* @method eg#cancelAnimationFrame
      +	* @param {Number} key −	The ID value returned through a call to the requestAnimationFrame() method. <ko>requestAnimationFrame() 메서드가 반환한 아이디 값</ko>
      +	* @example
      +		eg.cancelAnimationFrame(timerId);
      +	* @see  https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame
      +	*/
      +	ns.cancelAnimationFrame = function(key) {
      +		caf(key);
      +	};
      +
      +	$.extend($.easing, {
      +		easeOutCubic: function(p) {
      +			return 1 - Math.pow(1 - p, 3);
      +		}
      +	});
      +});
      +
      +
      + + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:14 GMT+0900 (KST) +
      +
      +
      + + + + + diff --git a/doc/flicking.js.html b/doc/flicking.js.html new file mode 100644 index 00000000..49108b5d --- /dev/null +++ b/doc/flicking.js.html @@ -0,0 +1,2169 @@ + + + + + Source: flicking.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Source: flicking.js

      + + + + +
      +
      +
      // jscs:disable validateLineBreaks, maximumLineLength
      +/**
      +* Copyright (c) 2015 NAVER Corp.
      +* egjs projects are licensed under the MIT license
      +*/
      +eg.module("flicking", ["jQuery", eg, window, document, eg.MovableCoord], function ($, ns, global, doc, MC) {
      +	"use strict";
      +
      +	// jscs:enable validateLineBreaks, maximumLineLength
      +	/**
      +	 * A module used to implement flicking interactions. With this module, you can make flicking gestures, which are ways to navigate left and right to move between panels arranged side by side.
      +	 * @group egjs
      +	 * @ko 플리킹 UI를 구현하는 모듈. 나란히 배치한 패널을 쓸어 넘겨 다음 패널이나 이전 패널로 이동하는 플리킹 UI를 만들 수 있다.
      +	 * @class
      +	 * @name eg.Flicking
      +	 * @extends eg.Component
      +	 *
      +	 * @param {HTMLElement|String|jQuery} element A base element for the eg.Flicking module <ko>eg.Flicking 모듈을 사용할 기준 엘리먼트</ko>
      +	 * @param {Object} options The option object of the eg.Flicking module<ko>eg.Flicking 모듈의 옵션 객체</ko>
      +	 * @param {Boolean} [options.hwAccelerable=eg.isHWAccelerable()] Force hardware compositing <ko>하드웨어 가속 사용 여부</ko>
      +	 * @param {String} [options.prefix=eg-flick] A prefix for class names of the panel elements <ko>패널 엘리먼트의 클래스 이름에 설정할 접두사</ko>
      +	 * @param {Number} [options.deceleration=0.0006] Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time <ko>사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다</ko>
      +	 * @param {Boolean} [options.horizontal=true] Direction of the panel movement (true: horizontal, false: vertical) <ko>패널 이동 방향 (true 가로방향, false 세로방향)</ko>
      +	 * @param {Boolean} [options.circular=false] Indicates whether a circular panel is available <ko>패널 순환 여부</ko>
      +	 * @param {Number|Array} [options.previewPadding=[0,0]] The preview size for the previous or next panel. If direction is set to "horizontal", the preview section will be displayed on the left and right of the panel. If direction is set to "vertical", it will be displayed on the top and bottom of the panel <ko>이전 패널과 다음 패널을 미리 보는 영역의 크기. 패널 이동 방향이 가로 방향이면 패널 왼쪽과 오른쪽에 미리 보는 영역이 나타난다. 패널 이동 방향이 세로 방향이면 패널 위쪽과 아래쪽에 미리 보는 영역이 나타난다</ko>
      +	 * @param {Number|Array} [options.bounce=[10,10]] −	The size of bouncing area. If a panel is set to "non-circulable", the start and end panels can exceed the base element area and move further as much as the bouncing area. If a panel is dragged to the bouncing area and then dropped, the panel where bouncing effects are applied is retuned back into the base element area. <ko>바운스 영역의 크기. 패널이 순환하지 않도록 설정됐다면 시작 패널과 마지막 패널은 기준 엘리먼트 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 패널을 바운스 영역까지 끌었다가 놓으면, 바운스 효과가 적용된 패널이 다시 기준 엘리먼트 영역 안으로 들어온다</ko>
      +	 * @param {Number} [options.threshold=40] Distance threshold. If the drag exceeds the threshold value, it will be changed to the next panel <ko>다음 패널로 바뀌는 기준 이동 거리. 패널을 기준 이동 거리 이상 끌었다 놓으면 패널이 다음 패널로 바뀐다</ko>
      +	 * @param {Number} [options.duration=100] Duration of the panel movement (unit: ms) <ko>패널 이동 애니메이션 진행 시간(단위: ms)</ko>
      +	 * @param {Function} [options.panelEffect=easeOutCubic] The easing function to apply to a panel moving animation <ko>패널 이동 애니메이션에 적용할 easing 함수</ko>
      +	 * @param {Number} [options.defaultIndex=0] The index number of a panel to be selected upon module initialization <ko>모듈이 초기화될 때 선택할 패널의 인덱스 번호</ko>
      +	 * @param {Array} [options.inputType] Types of input devices.<br>- touch: A touch screen can be used to move a panel.<br>- mouse: A mouse can be used to move a panel. <ko>입력 장치 종류.<br>- touch: 터치 입력 장치로 패널을 이동할 수 있다.<br>- mouse: 마우스로 패널을 이동할 수 있다.</ko>
      +	 *
      +	 * @codepen {"id":"rVOpPK", "ko":"플리킹 UI 기본 예제", "en":"Flicking UI default example", "collectionId":"ArxyLK", "height" : 403}
      +	 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest",  "sf" : "latest" , "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
      +	 *
      +	 * @see Easing Functions Cheat Sheet {@link http://easings.net/}
      +	 * @see If you want to try a different easing function, use the jQuery easing plugin ({@link http://gsgd.co.uk/sandbox/jquery/easing}) or the jQuery UI easing library ({@link https://jqueryui.com/easing}). <ko>다른 easing 함수를 사용하려면 jQuery easing 플러그인({@link http://gsgd.co.uk/sandbox/jquery/easing})이나, jQuery UI easing 라이브러리({@link https://jqueryui.com/easing})를 사용한다</ko>
      +	 * @example
      +	 	<!-- HTML -->
      +		<div id="mflick">
      +			<div>
      +				<p>Layer 0</p>
      +			</div>
      +			<div>
      +				<p>Layer 1</p>
      +			</div>
      +			<div>
      +				<p>Layer 2</p>
      +			</div>
      +		</div>
      +		<script>
      +	 	var some = new eg.Flicking("#mflick", {
      +				circular : true,
      +				threshold : 50
      +			}).on({
      +				beforeRestore : function(e) { ... },
      +				flickStart : function(e) { ... }
      +			});
      +	 	</script>
      +	 */
      +
      +	// define custom events name
      +	var EVENTS = {
      +		"beforeFlickStart": "beforeFlickStart",
      +		"beforeRestore": "beforeRestore",
      +		"flick": "flick",
      +		"flickEnd": "flickEnd",
      +		"restore": "restore"
      +	};
      +
      +	// check for css transform support
      +	var SUPPORT_TRANSFORM = doc.documentElement.style;
      +	SUPPORT_TRANSFORM = "transform" in SUPPORT_TRANSFORM ||
      +		"webkitTransform" in SUPPORT_TRANSFORM;
      +
      +	// check for will-change support
      +	var SUPPORT_WILLCHANGE = global.CSS && global.CSS.supports &&
      +		global.CSS.supports("will-change", "transform");
      +
      +	// check for Android 2.x
      +	var IS_ANDROID2 = ns.agent().os;
      +	IS_ANDROID2 = IS_ANDROID2.name === "android" && /^2\./.test(IS_ANDROID2.version);
      +
      +	ns.Flicking = ns.Class.extend(ns.Component, {
      +		_events: function() {
      +			return EVENTS;
      +		},
      +		/**
      +		 * Constructor
      +		 * @param {HTMLElement|String|jQuery} element - base element
      +		 * @param {Object} options
      +		 */
      +		construct: function (element, options, _prefix) {
      +			this.$wrapper = $(element);
      +
      +			var $children = this.$wrapper.children();
      +			if (!$children.length) {
      +				// jscs:disable validateLineBreaks, maximumLineLength
      +				throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized.");
      +
      +				// jscs:enable validateLineBreaks, maximumLineLength
      +			}
      +
      +			this._setOptions(options);
      +			this._setConfig($children, _prefix);
      +
      +			!ns._hasClickBug() && (this._setPointerEvents = $.noop);
      +
      +			this._build();
      +			this._bindEvents(true);
      +
      +			this._applyPanelsCss();
      +			this._arrangePanels();
      +
      +			this.options.hwAccelerable && SUPPORT_WILLCHANGE && this._setHint();
      +			this._adjustContainerCss("end");
      +		},
      +
      +		/**
      +		 * Set options values
      +		 * @param {Object} options
      +		 */
      +		_setOptions: function(options) {
      +			var arrVal = {
      +				previewPadding: [ 0, 0 ],
      +				bounce: [ 10, 10 ]
      +			};
      +
      +			$.extend(this.options = {
      +				hwAccelerable: ns.isHWAccelerable(),  // check weather hw acceleration is available
      +				prefix: "eg-flick",         // prefix value of class name
      +				deceleration: 0.0006,       // deceleration value
      +				horizontal: true,           // move direction (true == horizontal, false == vertical)
      +				circular: false,			// circular mode. In this mode at least 3 panels are required.
      +				previewPadding: arrVal.previewPadding,	// preview padding value in left(up) to right(down) order. In this mode at least 5 panels are required.
      +				bounce: arrVal.bounce,      // bounce value in left(up) to right(down) order. Works only in non-circular mode.
      +				threshold: 40,				// the distance pixel threshold value for change panel
      +				duration: 100,				// duration ms for animation
      +				panelEffect: $.easing.easeOutCubic,  // $.easing function for panel change animation
      +				defaultIndex: 0,			// initial panel index to be shown
      +				inputType: ["touch", "mouse"]  // input type
      +			}, options);
      +
      +			var self = this;
      +			$.each(arrVal, function(i, v) {
      +				var val = self.options[i];
      +
      +				if ($.isNumeric(val)) {
      +					val = [ val, val ];
      +				} else if (!$.isArray(val)) {
      +					val = v;
      +				}
      +
      +				self.options[i] = val;
      +			});
      +		},
      +
      +		/**
      +		 * Set config values
      +		 * @param {jQuery} $children wrappers' children elements
      +		 * @param {String} _prefix event prefix
      +		 */
      +		_setConfig: function($children, _prefix) {
      +			var options = this.options;
      +			var padding = options.previewPadding;
      +
      +			if ($children.eq(0).hasClass(options.prefix + "-container")) {
      +				this.$container = $children;
      +				$children = $children.children();
      +			}
      +
      +			// config value
      +			this._conf = {
      +				panel: {
      +					$list: $children,	// panel list
      +					index: 0,			// dom index used among process
      +					no: 0,				// panel no used among process
      +					currIndex: 0,       // current physical dom index
      +					currNo: 0,          // current logical panel number
      +					size: 0,			// panel size
      +					count: 0,			// total physical panel count
      +					origCount: 0,		// total count of given original panels
      +					changed: false,		// if panel changed
      +					animating: false,	// current animating status boolean
      +					minCount: padding[0] + padding[1] > 0 ? 5 : 3  // minimum panel count
      +				},
      +				touch: {
      +					holdPos: [0, 0],	// hold x,y coordinate
      +					destPos: [0, 0],	// destination x,y coordinate
      +					distance: 0,		// touch distance pixel of start to end touch
      +					direction: null,	// touch direction
      +					lastPos: 0,			// to determine move on holding
      +					holding: false
      +				},
      +				customEvent: {			// for custom events value
      +					flick: true,
      +					restore: false,
      +					restoreCall: false
      +				},
      +				origPanelStyle: {		// remember original class and inline style in case of restoration on destroy()
      +					wrapper: {
      +						className: this.$wrapper.attr("class") || null,
      +						style: this.$wrapper.attr("style") || null
      +					},
      +					list: $children.map(function(i, v) {
      +						return {
      +							className: $(v).attr("class") || null,
      +							style: $(v).attr("style") || null
      +						};
      +					})
      +				},
      +				inputEvent: false,		// input event biding status
      +				useLayerHack: options.hwAccelerable && !SUPPORT_WILLCHANGE,
      +				dirData: [],			// direction constant value according horizontal or vertical
      +				indexToMove: 0,
      +				eventPrefix: _prefix || "",
      +
      +				// For buggy link highlighting on Android 2.x
      +				$dummyAnchor: null
      +			};
      +
      +			$([["LEFT", "RIGHT"], ["UP", "DOWN"]][+!options.horizontal]).each(
      +				$.proxy(function (i, v) {
      +					this._conf.dirData.push(MC["DIRECTION_" + v]);
      +				}, this));
      +		},
      +
      +		/**
      +		 * Build and set panel nodes to make flicking structure
      +		 */
      +		_build: function () {
      +			var panel = this._conf.panel;
      +			var options = this.options;
      +			var $children = panel.$list;
      +			var padding = options.previewPadding.concat();
      +			var prefix = options.prefix;
      +			var horizontal = options.horizontal;
      +			var panelCount = panel.count = panel.origCount = $children.length;
      +			var cssValue;
      +			var bounce = options.bounce;
      +
      +			this._setPadding(padding, true);
      +			var sizeValue = this._getDataByDirection([ panel.size, "100%" ]);
      +
      +			// create container element
      +			cssValue = "position:relative;z-index:2000;width:100%;height:100%;" +
      +				(horizontal ? "" : "top:0;");
      +
      +			if (this.$container) {
      +				this.$container.attr("style", cssValue);
      +			} else {
      +				this.$container = $children.wrapAll(
      +					"<div class='" + prefix + "-container' style='" + cssValue + "'>"
      +				).parent();
      +			}
      +
      +			// panels' css values
      +			$children.addClass(prefix + "-panel").css({
      +				position: "absolute",
      +				width: sizeValue[0],
      +				height: sizeValue[1],
      +				boxSizing: "border-box",
      +				top: 0,
      +				left: 0
      +			});
      +
      +			if (this._addClonePanels()) {
      +				panelCount = panel.count = (
      +					panel.$list = this.$container.children()
      +				).length;
      +			}
      +
      +			// create MovableCoord instance
      +			this._mcInst = new MC({
      +				min: [0, 0],
      +				max: this._getDataByDirection([panel.size * (panelCount - 1), 0]),
      +				margin: 0,
      +				circular: false,
      +				easing: options.panelEffect,
      +				deceleration: options.deceleration,
      +				bounce: this._getDataByDirection([ 0, bounce[1], 0, bounce[0] ])
      +			});
      +
      +			this._setDefaultPanel(options.defaultIndex);
      +		},
      +
      +		/**
      +		 * Set preview padding value
      +		 * @param {Array} padding
      +		 * @param {Boolean} build
      +		 */
      +		_setPadding: function(padding, build) {
      +			var horizontal = this.options.horizontal;
      +			var panel = this._conf.panel;
      +			var paddingSum = padding[0] + padding[1];
      +			var cssValue = {};
      +
      +			if (paddingSum || !build) {
      +				cssValue.padding = (horizontal ?
      +					"0 " + padding.reverse().join("px 0 ") :
      +					padding.join("px 0 ")) + "px";
      +			}
      +
      +			if (build) {
      +				cssValue.overflow = "hidden";
      +				cssValue.boxSizing = "border-box";
      +			}
      +
      +			!$.isEmptyObject(cssValue) &&
      +				this.$wrapper.css(cssValue);
      +
      +			panel.size = this.$wrapper[ horizontal ? "width" : "height" ]();
      +		},
      +
      +		/**
      +		 * To fulfill minimum panel count cloning original node when circular or previewPadding option are set
      +		 * @return {Boolean} true : added clone node, false : not added
      +		 */
      +		_addClonePanels: function () {
      +			var panel = this._conf.panel;
      +			var panelCount = panel.origCount;
      +			var cloneCount = panel.minCount - panelCount;
      +			var list = panel.$list;
      +			var cloneNodes;
      +
      +			// if panels are given less than required when circular option is set, then clone node to apply circular mode
      +			if (this.options.circular && panelCount < panel.minCount) {
      +				cloneNodes = list.clone();
      +
      +				while (cloneNodes.length < cloneCount) {
      +					cloneNodes = cloneNodes.add(list.clone());
      +				}
      +
      +				return this.$container.append(cloneNodes);
      +			}
      +		},
      +
      +		/**
      +		 * Move panel's position within array
      +		 * @param {Number} count element counts to move
      +		 * @param {Boolean} append where the list to be appended(moved) (true: to the end, false: to the beginning)
      +		 */
      +		_movePanelPosition: function (count, append) {
      +			var panel = this._conf.panel;
      +			var list = panel.$list.toArray();
      +			var listToMove;
      +
      +			listToMove = list.splice(append ? 0 : panel.count - count, count);
      +			panel.$list = $(append ? list.concat(listToMove) : listToMove.concat(list));
      +		},
      +
      +		/**
      +		 * Set default panel to show
      +		 * @param {Number} index
      +		 */
      +		_setDefaultPanel: function (index) {
      +			var panel = this._conf.panel;
      +			var lastIndex = panel.count - 1;
      +			var coords;
      +			var baseIndex;
      +
      +			if (this.options.circular) {
      +				// if default index is given, then move correspond panel to the first position
      +				if (index > 0 && index <= lastIndex) {
      +					this._movePanelPosition(index, true);
      +				}
      +
      +				// set first panel's position according physical node length
      +				baseIndex = this._getBasePositionIndex();
      +				this._movePanelPosition(baseIndex, false);
      +
      +				this._setPanelNo({
      +					no: index,
      +					currNo: index
      +				});
      +			} else {
      +				// if defaultIndex option is given, then move to that index panel
      +				if (index > 0 && index <= lastIndex) {
      +					this._setPanelNo({
      +						index: index,
      +						no: index,
      +						currIndex: index,
      +						currNo: index
      +					});
      +
      +					coords = [ -(panel.size * index), 0];
      +
      +					this._setTranslate(coords);
      +					this._setMovableCoord("setTo", [
      +						Math.abs(coords[0]), Math.abs(coords[1])
      +					], true, 0);
      +				}
      +			}
      +		},
      +
      +		/**
      +		 * Arrange panels' position
      +		 * @param {Boolean} sort Need to sort panel's position
      +		 * @param {Number} indexToMove Number to move from current position (negative: left, positive: right)
      +		 */
      +		_arrangePanels: function (sort, indexToMove) {
      +			var conf = this._conf;
      +			var panel = conf.panel;
      +			var touch = conf.touch;
      +			var dirData = conf.dirData;
      +			var baseIndex;
      +
      +			if (this.options.circular) {
      +				// when arranging panels, set flag to not trigger flick custom event
      +				conf.customEvent.flick = false;
      +
      +				// move elements according direction
      +				if (sort) {
      +					indexToMove && (touch.direction = dirData[+!Boolean(indexToMove > 0)]);
      +					this._arrangePanelPosition(touch.direction, indexToMove);
      +				}
      +
      +				// set index for base element's position
      +				baseIndex = this._getBasePositionIndex();
      +
      +				this._setPanelNo({
      +					index: baseIndex,
      +					currIndex: baseIndex
      +				});
      +
      +				// arrange MovableCoord's coord position
      +				conf.customEvent.flick = !!this._setMovableCoord("setTo", [
      +					panel.size * panel.index, 0
      +				], true, 0);
      +			}
      +
      +			this._applyPanelsPos();
      +		},
      +
      +		/**
      +		 * Set each panel's position in DOM
      + 		 */
      +		_applyPanelsPos: function() {
      +			this._conf.panel.$list.each(
      +				$.proxy(this._applyPanelsCss, this)
      +			);
      +		},
      +
      +		/**
      +		 * Set CSS style values to move elements
      +		 *
      +		 * Initialize setting up checking if browser support transform css property.
      +		 * If browser doesn't support transform, then use left/top properties instead.
      +		 */
      +		_setMoveStyle: (function () {
      +			return SUPPORT_TRANSFORM ?
      +				function ($element, coords) {
      +					$element.css("transform",
      +						ns.translate(coords[0], coords[1], this._conf.useLayerHack)
      +					);
      +				} :	function ($element, coords) {
      +					$element.css({ left: coords[0], top: coords[1] });
      +				};
      +		})(),
      +
      +		/**
      +		 * Callback function for applying CSS values to each panels
      +		 *
      +		 * Need to be initialized before use, to set up for Android 2.x browsers or others.
      +		 */
      +		_applyPanelsCss: function () {
      +			var conf = this._conf;
      +			var dummyAnchorClassName = "__dummy_anchor";
      +
      +			if (IS_ANDROID2) {
      +				conf.$dummyAnchor = $("." + dummyAnchorClassName);
      +
      +				!conf.$dummyAnchor.length && this.$wrapper.append(
      +					conf.$dummyAnchor = $("<a href='javascript:void(0);' class='" +
      +						dummyAnchorClassName +
      +						"' style='position:absolute;height:0px;width:0px;'>")
      +				);
      +
      +				this._applyPanelsCss = function (i, v) {
      +					var coords = this._getDataByDirection([
      +						(this._conf.panel.size * i) + "px", 0
      +					]);
      +
      +					$(v).css({
      +						left: coords[0],
      +						top: coords[1]
      +					});
      +				};
      +			} else {
      +				this._applyPanelsCss = function (i, v) {
      +					var coords = this._getDataByDirection([
      +						SUPPORT_TRANSFORM ?
      +							(100 * i) + "%" :
      +							(this._conf.panel.size * i) + "px", 0]);
      +
      +					this._setMoveStyle($(v), coords);
      +				};
      +			}
      +		},
      +
      +		/**
      +		 * Adjust container's css value to handle Android 2.x link highlighting bug
      +		 *
      +		 * @param {String} phase
      +		 *    start - set left/top value to 0
      +		 *    end - set translate value to 0
      +		 * @param {Array} coords coordinate value
      +		 */
      +		_adjustContainerCss: function (phase, coords) {
      +			var conf = this._conf;
      +			var panel = conf.panel;
      +			var options = this.options;
      +			var horizontal = options.horizontal;
      +			var paddingTop = options.previewPadding[0];
      +			var container = this.$container;
      +			var value;
      +
      +			if (IS_ANDROID2) {
      +				if (!coords) {
      +					coords = [-panel.size * panel.index, 0];
      +				}
      +
      +				if (phase === "start") {
      +					container = container[0].style;
      +					value = parseInt(container[horizontal ? "left" : "top"], 10);
      +
      +					if (horizontal) {
      +						value && (container.left = 0);
      +					} else {
      +						value !== paddingTop && (container.top = paddingTop + "px");
      +					}
      +
      +					this._setTranslate([-coords[+!options.horizontal], 0]);
      +
      +				} else if (phase === "end") {
      +					!horizontal && (coords[0] += paddingTop);
      +					coords = this._getCoordsValue(coords);
      +
      +					container.css({
      +						left: coords.x,
      +						top: coords.y,
      +						transform: ns.translate(0, 0, conf.useLayerHack)
      +					});
      +
      +					conf.$dummyAnchor[0].focus();
      +				}
      +			}
      +		},
      +
      +		/**
      +		 * Set MovableCoord coord value
      +		 * @param {String} method
      +		 * @param {Array} coord
      +		 * @param {Boolean} isDirVal
      +		 * @param {Number} duration
      +		 * @return {eg.MovableCoord} MovableCoord instance
      +		 */
      +		_setMovableCoord: function (method, coord, isDirVal, duration) {
      +			if (isDirVal) {
      +				coord = this._getDataByDirection(coord);
      +			}
      +
      +			return this._mcInst[method](coord[0], coord[1], duration);
      +		},
      +
      +		/**
      +		 * Set hint for browser to decide efficient way of doing transform changes(or animation)
      +		 * https://dev.opera.com/articles/css-will-change-property/
      +		 */
      +		_setHint: function () {
      +			var value = "transform";
      +			this.$container.css("willChange", value);
      +			this._conf.panel.$list.css("willChange", value);
      +		},
      +
      +		/**
      +		 * Get data according options.horizontal value
      +		 *
      +		 * @param {Array} value primary data to handle
      +		 * @return {Array}
      +		 */
      +		_getDataByDirection: function (value) {
      +			value = value.concat();
      +			!this.options.horizontal && value.reverse();
      +			return value;
      +		},
      +
      +		/**
      +		 * Move nodes
      +		 * @param {Boolean} direction
      +		 * @param {Number} indexToMove
      +		 */
      +		_arrangePanelPosition: function (direction, indexToMove) {
      +			var next = direction === this._conf.dirData[0];
      +			this._movePanelPosition(Math.abs(indexToMove || 1), next);
      +		},
      +
      +		/**
      +		 * Get the base position index of the panel
      +		 */
      +		_getBasePositionIndex: function () {
      +			return Math.floor(this._conf.panel.count / 2 - 0.1);
      +		},
      +
      +		/**
      +		 * Bind events
      +		 * @param {Boolean} bind
      +		 */
      +		_bindEvents: function (bind) {
      +			var options = this.options;
      +			var $wrapper = this.$wrapper;
      +			var mcInst = this._mcInst;
      +
      +			if (bind) {
      +				mcInst.bind($wrapper, {
      +					scale: this._getDataByDirection([-1, 0]),
      +					direction: MC["DIRECTION_" +
      +					(options.horizontal ? "HORIZONTAL" : "VERTICAL")],
      +					interruptable: false,
      +					inputType: options.inputType
      +				}).on({
      +					hold: $.proxy(this._holdHandler, this),
      +					change: $.proxy(this._changeHandler, this),
      +					release: $.proxy(this._releaseHandler, this),
      +					animationStart: $.proxy(this._animationStartHandler, this),
      +					animationEnd: $.proxy(this._animationEndHandler, this)
      +				});
      +			} else {
      +				mcInst.unbind($wrapper).off();
      +			}
      +
      +			this._conf.inputEvent = !!bind;
      +		},
      +
      +		/**
      +		 * 'hold' event handler
      +		 */
      +		_holdHandler: function (e) {
      +			var conf = this._conf;
      +
      +			conf.touch.holdPos = e.pos;
      +			conf.touch.holding = true;
      +			conf.panel.changed = false;
      +
      +			this._adjustContainerCss("start", e.pos);
      +		},
      +
      +		/**
      +		 * 'change' event handler
      +		 */
      +		_changeHandler: function (e) {
      +			var conf = this._conf;
      +			var touch = conf.touch;
      +			var posIndex = +!this.options.horizontal;
      +			var pos = e.pos[posIndex];
      +			var holdPos = touch.holdPos[posIndex];
      +			var direction;
      +			var eventRes = null;
      +			var movedPx;
      +
      +			this._setPointerEvents(e);  // for "click" bug
      +
      +			/**
      +			 * This event is fired when panel moves.
      +			 * @ko 패널이 이동할 때 발생하는 이벤트
      +			 * @name eg.Flicking#flick
      +			 * @event
      +			 * @param {Object} param The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
      +			 * @param {String} param.eventType The name of the event<ko>이름명</ko>
      +			 * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM (@deprecated since 1.3.0)<ko>현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)</ko>
      +			 * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content <ko>현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다</ko>
      +			 * @param {Number} param.direction Direction of the movement (see eg.MovableCoord.DIRECTION_* constant) <ko>이동 방향(eg.MovableCoord.DIRECTION_* constant 참고)</ko>
      +			 * @param {Array} param.pos Start coordinate <ko>출발점 좌표</ko>
      +			 * @param {Number} param.pos.0 x-coordinate <ko>x 좌표</ko>
      +			 * @param {Number} param.pos.1 y-coordinate <ko>y 좌표</ko>
      +			 * @param {Boolean} param.holding Indicates whether a user holds an element on the screen of the device. <ko>사용자가 기기의 화면을 누르고 있는지 여부</ko>
      +			 * @param {Number} param.distance Distance moved from then starting point. According the move direction, positive on eg.MovableCoord.DIRECTION_LEFT/UP and negative on eg.MovableCoord.DIRECTION_RIGHT/DOWN <ko>시작점부터 이동된 거리의 값. 이동 방향에 따라 eg.MovableCoord.DIRECTION_LEFT/UP의 경우 양수를 eg.MovableCoord.DIRECTION_RIGHT/DOWN의 경우는 음수를 반환</ko>
      +			 */
      +			if (e.hammerEvent) {
      +				direction = e.hammerEvent.direction;
      +
      +				// Adjust direction in case of diagonal touch move
      +				movedPx = e.hammerEvent[ this.options.horizontal ? "deltaX" : "deltaY" ];
      +
      +				if (!~$.inArray(direction, conf.dirData)) {
      +					direction = conf.dirData[ +(Math.abs(touch.lastPos) <= movedPx) ];
      +				}
      +
      +				touch.lastPos = movedPx;
      +			} else {
      +				touch.lastPos = null;
      +			}
      +
      +			conf.customEvent.flick && (eventRes = this._triggerEvent(EVENTS.flick, {
      +				pos: e.pos,
      +				holding: e.holding,
      +				direction: direction || touch.direction,
      +				distance: pos - (holdPos || (touch.holdPos[posIndex] = pos))
      +			}));
      +
      +			(eventRes || eventRes === null) && this._setTranslate([ -pos, 0 ]);
      +		},
      +
      +		/**
      +		 * 'release' event handler
      +		 */
      +		_releaseHandler: function (e) {
      +			var touch = this._conf.touch;
      +			var pos = e.destPos;
      +			var posIndex = +!this.options.horizontal;
      +			var holdPos = touch.holdPos[posIndex];
      +			var panelSize = this._conf.panel.size;
      +
      +			touch.distance = e.depaPos[posIndex] - touch.holdPos[posIndex];
      +
      +			touch.direction = this._conf.dirData[
      +				+!Boolean(touch.holdPos[posIndex] < e.depaPos[posIndex])
      +			];
      +
      +			pos[posIndex] = Math.max(
      +				holdPos - panelSize, Math.min(holdPos, pos[posIndex])
      +			);
      +
      +			touch.destPos[posIndex] =
      +				pos[posIndex] = Math.round(pos[posIndex] / panelSize) * panelSize;
      +
      +			touch.distance === 0 && this._adjustContainerCss("end");
      +			touch.holding = false;
      +
      +			this._setPointerEvents();  // for "click" bug
      +		},
      +
      +		/**
      +		 * 'animationStart' event handler
      +		 */
      +		_animationStartHandler: function (e) {
      +			var conf = this._conf;
      +			var panel = conf.panel;
      +			var customEvent = conf.customEvent;
      +
      +			panel.animating = true;
      +
      +			if (!customEvent.restoreCall && e.hammerEvent &&
      +				this._setPhaseValue("start", {
      +					depaPos: e.depaPos,
      +					destPos: e.destPos
      +				}) === false) {
      +				e.stop();
      +			}
      +
      +			if (e.hammerEvent) {
      +				e.duration = this.options.duration;
      +
      +				e.destPos[+!this.options.horizontal] =
      +					panel.size * (
      +						panel.index + conf.indexToMove
      +					);
      +			}
      +
      +			if (this._isMovable()) {
      +				!customEvent.restoreCall && (customEvent.restore = false);
      +			} else {
      +				this._triggerBeforeRestore(e);
      +			}
      +		},
      +
      +		/**
      +		 * 'animationEnd' event handler
      +		 */
      +		_animationEndHandler: function () {
      +			this._setPhaseValue("end");
      +
      +			this._conf.panel.animating = false;
      +			this._triggerRestore();
      +		},
      +
      +		/**
      +		 * Trigger beforeRestore event
      +		 * @param {Object} e event object
      +		 */
      +		_triggerBeforeRestore: function(e) {
      +			var conf = this._conf;
      +			var touch = conf.touch;
      +
      +			// reverse direction value when restore
      +			touch.direction = ~~conf.dirData.join("").replace(touch.direction, "");
      +
      +			/**
      +			 * This event is fired before an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached
      +			 * @ko 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원되기 전에 발생하는 이벤트
      +			 * @name eg.Flicking#beforeRestore
      +			 * @event
      +			 * @param {Object} param The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
      +			 * @param {String} param.eventType The name of the event <ko>이름명</ko>
      +			 * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM. (@deprecated since 1.3.0)<ko>현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다. (@deprecated since 1.3.0)</ko>
      +			 * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content.<ko>현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다</ko>
      +			 * @param {Number} param.direction Direction of the movement (see eg.MovableCoord.DIRECTION_* constant) <ko>이동 방향(eg.MovableCoord.DIRECTION_* constant 참고)</ko>
      +			 * @param {Array} param.depaPos Start coordinate <ko>출발점 좌표</ko>
      +			 * @param {Number} param.depaPos.0 x-coordinate <ko>x 좌표</ko>
      +			 * @param {Number} param.depaPos.1 y-coordinate <ko>y 좌표</ko>
      +			 * @param {Array} param.destPos End coordinate <ko>도착점 좌표</ko>
      +			 * @param {Number} param.destPos.0 x-coordinate <ko>x 좌표</ko>
      +			 * @param {Number} param.destPos.1 y-coordinate <ko>y 좌표</ko>
      +			 */
      +			conf.customEvent.restore = this._triggerEvent(EVENTS.beforeRestore, {
      +				depaPos: e.depaPos,
      +				destPos: e.destPos
      +			});
      +
      +			if (!conf.customEvent.restore) {
      +				"stop" in e && e.stop();
      +				conf.panel.animating = false;
      +			}
      +		},
      +
      +		/**
      +		 * Trigger restore event
      +		 */
      +		_triggerRestore: function() {
      +			var customEvent = this._conf.customEvent;
      +
      +			/**
      +			 * This event is fired after an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached.
      +			 * @ko 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원된 다음 발생하는 이벤트
      +			 * @name eg.Flicking#restore
      +			 * @event
      +			 * @param {Object} param The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
      +			 * @param {String} param.eventType The name of the event <ko>이름명</ko>
      +			 * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM(@deprecated since 1.3.0)<ko>현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)</ko>
      +			 * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content. <ko>현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다</ko>
      +			 * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) <ko>이동 방향(eg.MovableCoord.DIRECTION_* constant 참고)</ko>
      +			 */
      +			customEvent.restore && this._triggerEvent(EVENTS.restore);
      +			customEvent.restoreCall = false;
      +		},
      +
      +		/**
      +		 * Set value when panel changes
      +		 * @param {String} phase - [start|end]
      +		 * @param {Object} pos
      +		 */
      +		_setPhaseValue: function (phase, pos) {
      +			var conf = this._conf;
      +			var options = this.options;
      +			var panel = conf.panel;
      +
      +			if (phase === "start" && (panel.changed = this._isMovable())) {
      +				/**
      +				 * This event is fired before flicking starts
      +				 * @ko 플리킹이 시작하기 전에 발생하는 이벤트
      +				 * @name eg.Flicking#beforeFlickStart
      +				 * @event
      +				 * @param {Object} param The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
      +				 * @param {String} param.eventType The name of the event <ko>이름명</ko>
      +				 * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM. (@deprecated since 1.3.0)<ko>현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)</ko>
      +				 * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content.<ko>현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다</ko>
      +				 * @param {Number} param.direction Direction of the movement (see eg.MovableCoord.DIRECTION_* constant) <ko>−	이동 방향(eg.MovableCoord.DIRECTION_* constant 참고)</ko>
      +				 * @param {Array} param.depaPos Start coordinate <ko>출발점 좌표</ko>
      +				 * @param {Number} param.depaPos.0 x-coordinate <ko>x 좌표</ko>
      +				 * @param {Number} param.depaPos.1 y-coordinate <ko>y 좌표</ko>
      +				 * @param {Array} param.destPos End coordinate <ko>도착점 좌표</ko>
      +				 * @param {Number} param.destPos.0 x-coordinate <ko>x 좌표</ko>
      +				 * @param {Number} param.destPos.1 y-coordinate <ko>y 좌표</ko>
      +				 */
      +				if (!this._triggerEvent(EVENTS.beforeFlickStart, pos)) {
      +					return panel.changed = panel.animating = false;
      +				}
      +
      +				conf.indexToMove === 0 && this._setPanelNo();
      +			} else if (phase === "end") {
      +				if (options.circular && panel.changed) {
      +					this._arrangePanels(true, conf.indexToMove);
      +				}
      +
      +				!IS_ANDROID2 && this._setTranslate([-panel.size * panel.index, 0]);
      +				conf.touch.distance = conf.indexToMove = 0;
      +
      +				/**
      +				 * This event is fired after panel moves.
      +				 * @ko 패널이 이동한 다음 발생하는 이벤트
      +				 * @name eg.Flicking#flickEnd
      +				 * @event
      +				 * @param {Object} param The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
      +				 * @param {String} param.eventType The name of the event <ko>이름명</ko>
      +				 * @param {Number} param.index Physical index number of the current panel element, which is relative to DOM (@deprecated since 1.3.0)<ko>현재 패널 엘리먼트의 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다 (@deprecated since 1.3.0)</ko>
      +				 * @param {Number} param.no Logical index number of the current panel element, which is relative to the panel content. <ko>현재 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.</ko>
      +				 * @param {Number} param.direction Direction of the movemen (see eg.MovableCoord.DIRECTION_* constant) <ko>−	이동 방향(eg.MovableCoord.DIRECTION_* constant 참고</ko>
      +				 */
      +				panel.changed && this._triggerEvent(EVENTS.flickEnd);
      +			}
      +
      +			!(phase === "start" && pos === undefined) && this._adjustContainerCss(phase);
      +		},
      +
      +		/**
      +		 * Get positive or negative according direction
      +		 */
      +		_getNumByDirection: function() {
      +			var conf = this._conf;
      +			return conf.touch.direction === conf.dirData[0] ? 1 : -1;
      +		},
      +
      +		/**
      +		 * Revert panel number
      +		 */
      +		_revertPanelNo: function() {
      +			var panel = this._conf.panel;
      +			var num = this._getNumByDirection();
      +
      +			var index = panel.currIndex >= 0 ? panel.currIndex : panel.index - num;
      +			var no = panel.currNo >= 0 ? panel.currNo : panel.no - num;
      +
      +			this._setPanelNo({
      +				index: index,
      +				no: no
      +			});
      +		},
      +
      +		/**
      +		 * Set the panel number
      +		 * @param {Object} obj number object
      +		 */
      +		_setPanelNo: function (obj) {
      +			var panel = this._conf.panel;
      +			var count = panel.origCount - 1;
      +			var num = this._getNumByDirection();
      +
      +			if ($.isPlainObject(obj)) {
      +				$.each(obj, function(i, v) {
      +					panel[i] = v;
      +				});
      +
      +			} else {
      +				// remember current value
      +				panel.currIndex = panel.index;
      +				panel.currNo = panel.no;
      +
      +				panel.index += num;
      +				panel.no += num;
      +			}
      +
      +			if (panel.no > count) {
      +				panel.no = 0;
      +			} else if (panel.no < 0) {
      +				panel.no = count;
      +			}
      +		},
      +
      +		/**
      +		 * Set pointerEvents css property on container element due to the iOS click bug
      +		 * @param {Event} e
      +		 */
      +		_setPointerEvents: function (e) {
      +			var pointer = this.$container.css("pointerEvents");
      +			var val;
      +
      +			if (e && e.holding &&
      +				e.hammerEvent && e.hammerEvent.preventSystemEvent &&
      +				pointer !== "none"
      +			) {
      +				val = "none";
      +			} else if (!e && pointer !== "auto") {
      +				val = "auto";
      +			}
      +
      +			val && this.$container.css("pointerEvents", val);
      +		},
      +
      +		/**
      +		 * Get coordinate value with unit
      +		 * @param coords {Array} x,y numeric value
      +		 * @return {Object} x,y coordinate value with unit
      +		 */
      +		_getCoordsValue: function (coords) {
      +			// the param comes as [ val, 0 ], whatever the direction. So reorder the value depend the direction.
      +			coords = this._getDataByDirection(coords);
      +
      +			return {
      +				x: this._getUnitValue(coords[0]),
      +				y: this._getUnitValue(coords[1])
      +			};
      +		},
      +
      +		/**
      +		 * Set translate property value
      +		 * @param {Array} coords coordinate x,y value
      +		 */
      +		_setTranslate: function (coords) {
      +			coords = this._getCoordsValue(coords);
      +			this._setMoveStyle(this.$container, [ coords.x, coords.y ]);
      +		},
      +
      +		/**
      +		 * Return unit formatted value
      +		 * @param {Number|String} val
      +		 * @return {String} val Value formatted with unit
      +		 */
      +		_getUnitValue: function (val) {
      +			var rx = /(?:[a-z]{2,}|%)$/;
      +			return (parseInt(val, 10) || 0) + (String(val).match(rx) || "px");
      +		},
      +
      +		/**
      +		 * Check if panel passed through threshold pixel
      +		 */
      +		_isMovable: function () {
      +			var options = this.options;
      +			var mcInst = this._mcInst;
      +			var isMovable = Math.abs(this._conf.touch.distance) >= options.threshold;
      +			var max;
      +			var currPos;
      +
      +			if (!options.circular && isMovable) {
      +				max = this._getDataByDirection(mcInst.options.max)[0];
      +				currPos = this._getDataByDirection(mcInst.get())[0];
      +
      +				// if current position out of range
      +				if (currPos < 0 || currPos > max) {
      +					return false;
      +				}
      +			}
      +
      +			return isMovable;
      +		},
      +
      +		/**
      +		 * Trigger custom events
      +		 * @param {String} name - event name
      +		 * @param {Object} param - additional event value
      +		 * @return {Boolean}
      +		 */
      +		_triggerEvent: function (name, param) {
      +			var conf = this._conf;
      +			var panel = conf.panel;
      +
      +			// pass changed panel no only on 'flickEnd' event
      +			if (name === EVENTS.flickEnd) {
      +				panel.currNo = panel.no;
      +				panel.currIndex = panel.index;
      +			}
      +
      +			return this.trigger(conf.eventPrefix + name, $.extend({
      +				eventType: name,
      +				index: panel.currIndex,
      +				no: panel.currNo,
      +				direction: conf.touch.direction
      +			}, param));
      +		},
      +
      +		/**
      +		 * Get next/prev panel element/index.
      +		 * @param {Boolean} direction
      +		 * @param {Boolean} element - true:to get element, false:to get index
      +		 * @param {Number} physical - true : physical, false : logical
      +		 * @return {jQuery|Number}
      +		 */
      +		_getElement: function (direction, element, physical) {
      +			var panel = this._conf.panel;
      +			var circular = this.options.circular;
      +			var pos = panel.currIndex;
      +			var next = direction === this._conf.dirData[0];
      +			var result = null;
      +			var total;
      +			var index;
      +			var currentIndex;
      +
      +			if (physical) {
      +				total = panel.count;
      +				index = pos;
      +			} else {
      +				total = panel.origCount;
      +				index = panel.currNo;
      +			}
      +
      +			currentIndex = index;
      +
      +			if (next) {
      +				if (index < total - 1) {
      +					index++;
      +				} else if (circular) {
      +					index = 0;
      +				}
      +			} else {
      +				if (index > 0) {
      +					index--;
      +				} else if (circular) {
      +					index = total - 1;
      +				}
      +			}
      +
      +			if (currentIndex !== index) {
      +				result = element ? $(panel.$list[next ? pos + 1 : pos - 1]) : index;
      +			}
      +
      +			return result;
      +		},
      +
      +		/**
      +		 * Set value to force move panels when duration is 0
      +		 * @param {Boolean} next
      +		 */
      +		_setValueToMove: function (next) {
      +			var conf = this._conf;
      +
      +			conf.touch.distance = this.options.threshold + 1;
      +			conf.touch.direction = conf.dirData[ +!next ];
      +		},
      +
      +		/**
      +		 * Check and parse value to number
      +		 * @param {Number|String} val
      +		 * @param {Number} defVal
      +		 * @return {Number}
      +		 */
      +		_getNumValue: function (val, defVal) {
      +			return isNaN(val = parseInt(val, 10)) ? defVal : val;
      +		},
      +
      +		/**
      +		 * Returns the index number of the current panel element.
      +		 * @ko 현재 패널 엘리먼트의 인덱스 번호를 반환한다
      +		 * @method eg.Flicking#getIndex
      +		 * @param {Boolean} [physical=false] Types of index numbers<br>- true: Indicates physical index numbers relative to DOM.<br>- false: Indicates logical index numbers relative to the panel content. <ko>−	인덱스 번호의 종류<br>- true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.<br>- false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.</ko>
      +		 * @return {Number} Index number of the current panel element <ko>현재 패널의 인덱스 번호</ko>
      +		 */
      +		getIndex: function (physical) {
      +			return this._conf.panel[ physical ? "currIndex" : "currNo" ];
      +		},
      +
      +		/**
      +		 * Returns the reference of the current panel element.
      +		 * @ko 현재 패널 엘리먼트의 레퍼런스를 반환한다
      +		 * @method eg.Flicking#getElement
      +		 * @return {jQuery} Current element <ko>현재 엘리먼트</ko>
      +		 */
      +		getElement: function () {
      +			var panel = this._conf.panel;
      +			return $(panel.$list[ panel.currIndex ]);
      +		},
      +
      +		/**
      +		 * Returns the reference of the next panel element.
      +		 * @ko 다음 패널 엘리먼트의 레퍼런스를 반환한다.
      +		 * @method eg.Flicking#getNextElement
      +		 * @return {jQuery|null} Next panel element or null if it does not exist.<ko>다음 패널 엘리먼트. 패널이 없으면 'null'을 반환한다.</ko>
      +		 */
      +		getNextElement: function () {
      +			return this._getElement(this._conf.dirData[0], true);
      +		},
      +
      +		/**
      +		 * Returns the index number of the next panel element.
      +		 * @ko 다음 패널 엘리먼트의 인덱스 번호를 반환한다
      +		 * @method eg.Flicking#getNextIndex
      +		 * @param {Boolean} [physical=false] Types of index numbers<br>- true: Indicates physical index numbers relative to DOM.<br>- false: Indicates logical index numbers relative to the panel content. <ko>−	인덱스 번호의 종류<br>- true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.<br>- false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.</ko>
      +		 * @return {Number|null} Index number of the next panel element or null if it does not exist. <ko>다음 패널 엘리먼트의 인덱스 번호. 패널이 없으면 'null'을 반환한다</ko>
      +		 */
      +		getNextIndex: function (physical) {
      +			return this._getElement(this._conf.dirData[0], false, physical);
      +		},
      +
      +		/**
      +		 * Returns the references of whole panel elements.
      +		 * @ko 패널을 구성하는 모든 엘리먼트의 레퍼런스를 반환한다
      +		 * @method eg.Flicking#getAllElements
      +		 * @return {jQuery} Whole panel elements <ko>모든 패널 엘리먼트</ko>
      +		 */
      +		getAllElements: function () {
      +			return this._conf.panel.$list;
      +		},
      +
      +		/**
      +		 * Returns the reference of the previous panel element.
      +		 * @ko 이전 패널 엘리먼트의 레퍼런스를 반환한다.
      +		 * @method eg.Flicking#getPrevElement
      +		 * @return {jQuery|null} Previous panel element or null if it does not exist. <ko>이전 패널 엘리먼트. 패널이 없으면 'null'을 반환한다</ko>
      +		 */
      +		getPrevElement: function () {
      +			return this._getElement(this._conf.dirData[1], true);
      +		},
      +
      +		/**
      +		 * Returns the index number of the previous panel element.
      +		 * @ko 이전 패널 엘리먼트의 인덱스 번호를 반환한다
      +		 * @method eg.Flicking#getPrevIndex
      +		 * @param {Boolean} [physical=false] Types of index numbers<br>- true: Indicates physical index numbers relative to DOM.<br>- false: Indicates logical index numbers relative to the panel content. <ko>−	인덱스 번호의 종류<br>- true: 물리적 인덱스 번호. DOM 엘리먼트를 기준으로 하는 인덱스 번호다.<br>- false: 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다.</ko>
      +		 * @return {Number|null} Previous element index value or null if no more element exist<ko>이전 패널 인덱스 번호. 패널이 없는 경우에는 null</ko>
      +		 */
      +		getPrevIndex: function (physical) {
      +			return this._getElement(this._conf.dirData[1], false, physical);
      +		},
      +
      +		/**
      +		 * Returns the total number of whole panel elements.
      +		 * @ko 전체 패널 엘리먼트의 개수를 반환한다
      +		 * @method eg.Flicking#getTotalCount
      +		 * @deprecated since 1.3.0
      +		 * @param {Boolean} [physical=false] Number of elements relative to (true: DOM, false: panel content)<ko>엘리먼트 개수의 기준(true: DOM 엘리먼트 기준, false: 패널 콘텐츠 기준)</ko>
      +		 * @return {Number} Total number of whole panel elements <ko>모든 패널 엘리먼트의 개수</ko>
      +		 */
      +		getTotalCount: function (physical) {
      +			return this._conf.panel[ physical ? "count" : "origCount" ];
      +		},
      +
      +		/**
      +		 * Checks whether the animated panel is playing.
      +		 * @ko 패널 이동 애니메이션이 진행 중인지 확인한다.
      +		 * @method eg.Flicking#isPlaying
      +		 * @return {Boolean} Indicates whether the animated panel is playing <ko>패널 이동 애니메이션 진행 중 여부</ko>
      +		 */
      +		isPlaying: function () {
      +			return this._conf.panel.animating;
      +		},
      +
      +		/**
      +		 * Move panel to the given direction
      +		 * @param {Boolean} next
      +		 * @param {Number} duration
      +		 */
      +		_movePanel: function (next, duration) {
      +			var conf = this._conf;
      +			var panel = conf.panel;
      +			var options = this.options;
      +
      +			if (panel.animating || conf.touch.holding) {
      +				return;
      +			}
      +
      +			this._setValueToMove(next);
      +
      +			if (options.circular ||
      +				this[next ? "getNextIndex" : "getPrevIndex"]() != null
      +			) {
      +				this._movePanelByPhase("setBy", [
      +					panel.size * (next ? 1 : -1), 0
      +				], duration);
      +			}
      +
      +			return this;
      +		},
      +
      +		/**
      +		 * Move panel applying start/end phase value
      +		 * @param {String} method movableCoord method name
      +		 * @param {Object} coords coordinate array value
      +		 * @param {Number} duration duration value
      +		 */
      +		_movePanelByPhase: function(method, coords, duration) {
      +			duration = this._getNumValue(duration, this.options.duration);
      +
      +			if (this._setPhaseValue("start") !== false) {
      +				this._setMovableCoord(method, coords, true, duration);
      +				!duration && this._setPhaseValue("end");
      +			}
      +		},
      +
      +		/**
      +		 * Moves an element to the next panel.
      +		 * @ko 다음 패널로 이동한다.
      +		 * @method eg.Flicking#next
      +		 * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) <ko>패널 이동 애니메이션 진행 시간(단위: ms)</ko>
      +		 * @return {eg.Flicking} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		next: function (duration) {
      +			return this._movePanel(true, duration);
      +		},
      +
      +		/**
      +		 * Moves an element to the previous panel.
      +		 * @ko 이전 패널로 이동한다.
      +		 * @method eg.Flicking#prev
      +		 * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) <ko>패널 이동 애니메이션 진행 시간(단위: ms)</ko>
      +		 * @return {eg.Flicking} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		prev: function (duration) {
      +			return this._movePanel(false, duration);
      +		},
      +
      +		/**
      +		 * Moves an element to the indicated panel.
      +		 * @ko 지정한 패널로 이동한다.
      +		 * @method eg.Flicking#moveTo
      +		 * @param {Number} no Logical index number of the target panel element, which is relative to the panel content. <ko>이동할 패널 엘리먼트의 논리적 인덱스 번호. 패널 콘텐츠를 기준으로 하는 인덱스 번호다</ko>
      +		 * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) <ko>패널 이동 애니메이션 진행 시간(단위: ms)</ko>
      +		 * @return {eg.Flicking} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		moveTo: function (no, duration) {
      +			var conf = this._conf;
      +			var panel = conf.panel;
      +			var circular = this.options.circular;
      +			var currentIndex = panel.index;
      +			var indexToMove;
      +			var isPositive;
      +
      +			no = this._getNumValue(no, -1);
      +
      +			if (no < 0 || no >= panel.origCount || no === panel.no ||
      +				panel.animating || conf.touch.holding) {
      +				return this;
      +			}
      +
      +			if (circular) {
      +				indexToMove = no - panel.no;
      +				isPositive = indexToMove > 0;
      +
      +				// check for real panel count which can be moved on each sides
      +				if (Math.abs(indexToMove) > (isPositive ?
      +					panel.count - (currentIndex + 1) : currentIndex)) {
      +					indexToMove = indexToMove + (isPositive ? -1 : 1) * panel.count;
      +				}
      +
      +				this._setPanelNo({ no: no });
      +			} else {
      +				indexToMove = no - currentIndex;
      +				this._setPanelNo({ index: no, no: no });
      +			}
      +
      +			this._conf.indexToMove = indexToMove;
      +			this._setValueToMove(isPositive);
      +
      +			this._movePanelByPhase(
      +				circular ? "setBy" : "setTo",
      +				[ panel.size * (circular ? indexToMove : no), 0 ],
      +				duration
      +			);
      +
      +			return this;
      +		},
      +
      +		/**
      +		 * Update panel's previewPadding size according options.previewPadding
      +		 */
      +		_checkPadding: function () {
      +			var options = this.options;
      +			var previewPadding = options.previewPadding.concat();
      +			var padding = this.$wrapper.css("padding").split(" ");
      +
      +			options.horizontal && padding.reverse();
      +
      +			// get current padding value
      +			padding = padding.length === 2 ?
      +				[ padding[0], padding[0] ] : [ padding[0], padding[2] ];
      +
      +			padding = $.map(padding, function(num) {
      +				return parseInt(num, 10);
      +			});
      +
      +			// update padding when current and given are different
      +			if (previewPadding.length === 2 &&
      +				previewPadding[0] !== padding[0] || previewPadding[1] !== padding[1]) {
      +
      +				this._setPadding(previewPadding);
      +			}
      +		},
      +
      +		/**
      +		 * Updates the size of the panel.
      +		 * @ko 패널의 크기를 갱신한다
      +		 * @method eg.Flicking#resize
      +		 * @return {eg.Flicking} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
      +		 * @example
      +			var some = new eg.Flicking("#mflick", {
      +					previewPadding: [10,10]
      +				});
      +
      +			// when device orientaion changes
      +			some.resize();
      +
      +			// or when changes previewPadding option from its original value
      +			some.options.previewPadding = [20, 30];
      +			some.resize();
      +		 */
      +		resize: function () {
      +			var conf = this._conf;
      +			var options = this.options;
      +			var panel = conf.panel;
      +			var horizontal = options.horizontal;
      +			var panelSize;
      +			var maxCoords;
      +
      +			if (~~options.previewPadding.join("")) {
      +				this._checkPadding();
      +				panelSize = panel.size;
      +			} else if (horizontal) {
      +				panelSize = panel.size = this.$wrapper.width();
      +			}
      +
      +			maxCoords = this._getDataByDirection([panelSize * (panel.count - 1), 0]);
      +
      +			// resize elements
      +			horizontal && this.$container.width(maxCoords[0] + panelSize);
      +			panel.$list.css(horizontal ? "width" : "height", panelSize);
      +
      +			this._mcInst.options.max = maxCoords;
      +			this._setMovableCoord("setTo", [panelSize * panel.index, 0], true, 0);
      +
      +			if (IS_ANDROID2) {
      +				this._applyPanelsPos();
      +				this._adjustContainerCss("end");
      +			}
      +
      +			return this;
      +		},
      +
      +		/**
      +		 * Restores an element to its original position when it movement stops while the element is not dragged until a certain distance threshold is reached.
      +		 * @ko 다음 패널로 바뀌기 전에 패널 이동이 멈췄을 때 원래 패널로 복원한다
      +		 * @method eg.Flicking#restore
      +		 * @param {Number} [duration=options.duration] Duration of the panel movement (unit: ms) <ko>패널 이동 애니메이션 진행 시간(단위: ms)</ko>
      +		 * @return {eg.Flicking} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
      +		 * @example
      +			var some = new eg.Flicking("#mflick").on({
      +					beforeFlickStart : function(e) {
      +						if(e.no === 2) {
      +							e.stop();  // stop flicking
      +							this.restore(100);  // restoring to previous position
      +						}
      +					}
      +				);
      +		 */
      +		restore: function (duration) {
      +			var conf = this._conf;
      +			var panel = conf.panel;
      +			var currPos = this._getDataByDirection(this._mcInst.get());
      +			var destPos;
      +
      +			// check if the panel isn't in right position
      +			if (currPos[0] !== panel.currIndex * panel.size) {
      +				conf.customEvent.restoreCall = true;
      +				duration = this._getNumValue(duration, this.options.duration);
      +
      +				this._revertPanelNo();
      +				destPos = this._getDataByDirection([panel.size * panel.index, 0]);
      +
      +				this._triggerBeforeRestore({ depaPos: currPos, destPos: destPos });
      +				this._setMovableCoord("setTo", destPos, true, duration);
      +
      +				if (!duration) {
      +					this._adjustContainerCss("end");
      +					this._triggerRestore();
      +				}
      +
      +				// to handle on api call
      +			} else if (panel.changed) {
      +				this._revertPanelNo();
      +				conf.touch.distance = conf.indexToMove = 0;
      +			}
      +
      +			return this;
      +		},
      +
      +		/**
      +		 * Set input event biding
      +		 * @param {Boolean} bind - true: bind, false: unbind
      +		 * @return {eg.Flicking} instance of itself
      +		 */
      +		_setInputEvent: function(bind) {
      +			var inputEvent = this._conf.inputEvent;
      +
      +			if (bind ^ inputEvent) {
      +				this._bindEvents(bind);
      +			}
      +
      +			return this;
      +		},
      +
      +		/**
      +		 * Enables input devices.
      +		 * @ko 입력 장치를 사용할 수 있게 한다
      +		 * @method eg.Flicking#enableInput
      +		 * @return {eg.Flicking} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		enableInput: function() {
      +			return this._setInputEvent(true);
      +		},
      +
      +		/**
      +		 * Disables input devices.
      +		 * @ko 입력 장치를 사용할 수 없게 한다.
      +		 * @method eg.Flicking#disableInput
      +		 * @return {eg.Flicking} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		disableInput: function() {
      +			return this._setInputEvent();
      +		},
      +
      +		/**
      +		 * Destroys elements, properties, and events used in a panel.
      +		 * @ko 패널에 사용한 엘리먼트와 속성, 이벤트를 해제한다
      +		 * @method eg.Flicking#destroy
      +		 */
      +		destroy: function() {
      +			var conf = this._conf;
      +			var origPanelStyle = conf.origPanelStyle;
      +			var wrapper = origPanelStyle.wrapper;
      +			var list = origPanelStyle.list;
      +
      +			// unwrap container element and restore original inline style
      +			this.$wrapper.attr("class", wrapper.className)
      +				.attr("style", wrapper.style);
      +
      +			this.$container.children().unwrap().each(function(i, v) {
      +				var $el = $(v);
      +
      +				if (i > list.length - 1) {
      +					return !!$el.remove();
      +				}
      +
      +				$el.attr("class", list[i].className)
      +					.attr("style", list[i].style);
      +			});
      +
      +			// unbind events
      +			this.disableInput();
      +			this.off();
      +
      +			// release resources
      +			for (var x in this) {
      +				this[x] = null;
      +			}
      +		}
      +	});
      +});
      +/**
      + * A jQuery plugin available in the eg.Flicking module.
      + *
      + * @ko eg.Flicking 모듈의 jQuery 플러그인
      + * @method jQuery.flicking
      + * @example
      +	<div id="content">
      +	    <div>
      +	        <p>Layer 0</p>
      +	    </div>
      +	    <div>
      +	        <p>Layer 1</p>
      +	    </div>
      +	    <div>
      +	        <p>Layer 2</p>
      +	    </div>
      +	</div>
      +    <script>
      +	// create
      +	$("#content").flicking({
      +        circular : true,
      +     	threshold : 50
      +    });
      + 	// method
      +	$("#content").flicking("option","circular",true); //Set option
      +	$("#content").flicking("instance"); // Return flicking instance
      +	$("#content").flicking("getNextIndex",1); // Get next panel index
      + 	</script>
      + * @see eg.Flicking
      + */
      +/**
      + * A jQuery custom event of the eg.Flicking module. This event is fired before an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached.
      + *
      + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원되기 전에 발생한다
      + * @name jQuery#flicking:beforeRestore
      + * @event
      + * @example
      + $("#mflick").on("flicking:beforeRestore",callback);
      + $("#mflick").off("flicking:beforeRestore",callback);
      + $("#mflick").trigger("flicking:beforeRestore",callback);
      + * @see eg.Flicking#event:beforeRestore
      + */
      +/**
      + * A jQuery custom event of the eg.Flicking module, which occurs before the flicking starts.
      + *
      + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 플리킹을 시작하기 전에 발생한다
      + * @name jQuery#flicking:beforeFlickStart
      + * @event
      + * @example
      + $("#mflick").on("flicking:beforeFlickStart",callback);
      + $("#mflick").off("flicking:beforeFlickStart",callback);
      + $("#mflick").trigger("flicking:beforeFlickStart",callback);
      + * @see eg.Flicking#event:beforeFlickStart
      + */
      +/**
      + * A jQuery custom event of the eg.Flicking module. This event is fired when panel moves.
      + *
      + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 패널이 이동될 때 발생한다
      + * @name jQuery#flicking:flick
      + * @event
      + * @example
      + $("#mflick").on("flicking:flick",callback);
      + $("#mflick").off("flicking:flick",callback);
      + $("#mflick").trigger("flicking:flick",callback);
      + * @see eg.Flicking#event:flick
      + */
      +/**
      + * A jQuery custom event of the eg.Flicking module. This event is fired after the panel moves.
      + *
      + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 패널이 이동된 뒤 발생한다
      + * @name jQuery#flicking:flickEnd
      + * @event
      + * @example
      + $("#mflick").on("flicking:flickEnd",callback);
      + $("#mflick").off("flicking:flickEnd",callback);
      + $("#mflick").trigger("flicking:flickEnd",callback);
      + * @see eg.Flicking#event:flickEnd
      + */
      +/**
      + * A jQuery custom event of the eg.Flicking module. This event is fired after an element is restored to its original position when user action is done while the element has not bene dragged until a certain distance threshold is reached.
      + *
      + * @ko eg.Flicking 모듈의 jQuery 커스텀 이벤트. 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원된 다음 발생한다
      + * @name jQuery#flicking:restore
      + * @event
      + * @example
      + $("#mflick").on("flicking:restore",callback);
      + $("#mflick").off("flicking:restore",callback);
      + $("#mflick").trigger("flicking:restore",callback);
      + * @see eg.Flicking#event:restore
      + */
      +
      +
      +
      + + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:13 GMT+0900 (KST) +
      +
      +
      + + + + + diff --git a/doc/fonts/glyphicons-halflings-regular.eot b/doc/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..423bd5d3a20b804f596e04e5cd02fb4f16cfcbc1 GIT binary patch literal 20290 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/fonts/glyphicons-halflings-regular.ttf b/doc/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a498ef4e7c8b556fc36f580c5ff524025bb11c84 GIT binary patch literal 41236 zcmc${34B}Cl|TOOdr!M8>1nlW%aSZh@-ADltvHKgvhN959SD$s!WNdWGz16%Qr5Hq zLm`wxhZF|Lu$1?dP}&a6w6rkl;x0@`ftk{z3q#8?Eo6ReL;Ujlp8MoA3AF$DeLjCD zlHMl0d(S=h+;hHXc>)szLBX3Wc;?Jmx%k3A|K_)Xz-n-`X6~%nbC?xp1U3o#v85|A z*$bXrcnkLXvA_PjOE+x(^}IzP?0-`b#EZ|{a&=5-kZ#A1)#JSN{LL3!x?+FkN$j`a z{KgA5T(ud;J%V7qkIr9k$+hP<{q(UrvH!3j+*x_y#tj7~Z^HK7`*FVeLL9JXWjFTU z$A0~VmtMW~yZ@@(EeHen4e`h&m!G#Gd;iMo1mR26#&2G_Ve4j5W_twTz87(Q?6M7) zZanZW4}OgO{}cpi+vdx!y86eb4XhS~FQfg|TQ*<0akKhSvtJPQ;Jnaw&Bk-j-=Htg z3&Pi&*f--v)DeC>?a`mo=TFXRd%*bg-oVeeuvbY(1QGj8cndGI1beuhd@~ymOoA*q z#h+pS4C9miqmUIrEdi%a{ep`JtY53N14 z{?J8-u03?;p$87z4u=mn9_~3j=kWZ)YY$&^_}asF9=`wZgTEGzAIGm5zt@D{6DItg zaL9DXb0~JG{ZQYbW%#{w4{bhl)1iUG?6Bu>>~Q!asH*G5-F7f0ttPmA`|67~Nd|1t2u@Q*SYReFv6!$}$f<4-=-kPct) z|MMp?^teB8{@?g_x6mN|MHO09!M9Ldw5(rUuw|_(B&JuY=H~usYx%Jo*2WH~%-2@g zsMRu8VN#&!Ke z)gP>_PQ+DHbH6%g%UXV7?OObvsik7w8Lg_hMXO_X;O?xckEv2}ej=vIsRgRAtbgamof~4bF{wHpUt7JC?=3g>=!SNq zb)ITZ95->a#9rgwakj)Vs-<~de=IgPF=xZYvHn=$T;nI`x(d28ZXMeho4a$)hQ!X; z&IG?*LKT+xt9`f<{iEBeeH&>9-*NFfO*>c_k5|VI?gSa|rTJ*vs&d=VK3wK*NyHA8 zZ=Q(tFI-U_SJ~SBo#@c~#Lh%)=lq?C4b&3q4!u)*JTwem41+=)pbhVY4xpilIf)Gy zuOHhJ`l_!5o!EIhk!?XCvD2c)mi14q{tnLgTlNWktZ&8)w(y%C;XHxA)5WXM^4QMh z{fTqY`oxTCe6Yj}P`+<@e^H1DGtZk*WHE*hHFlmF-dMw1ieC)0s5lC`;H{My60#JM z#*Nw5fSn7a7$%uTXw#UGnOd~S;s;sHZ2HfsMM=b_phUL-FPLPEWu3K_K`r?NrSk!5OSM)e(3Ohp!Upus`hn3ceKQ;2eKyHol)oqyLDikr zdRVhomsh;1rAKX5ijG*er>BRgn9p_Q6Zu?szB`u<1w)C>HZf7>5-o8{+#JALt(?pD zid{Lg#hj>1x3P4gaE0lu!tKe0pWFY@=BeiAbBh+#R`$%A?qk;%^aEzL8}GLEo|(Bo zWWl1`*P|OYJvn$y{R}5NQpj`_o;+jMOBY<6?{5$LTh8b$v~?F2Ts@=NUDdv(>zRu` z_YZAPZ{>VeVgvFb@kQ{Lm-B)&$W%F_nT(MKSxeF_$F>nUY53Ujk64TRvV58l6rzGE zWmNZ|YR6YX8Lbju(d?4q)tug*p7svOAI!zG-CdojM4hFLCF;xpf5^pLS1c7j-1^j0 zTiaS%p1hbYJ@cvJ@8+p&HNT`ZJmNyTPT z*gy%b{$v?z(GQ6IVn0T^r9cPu%_Y8fWax46Ox?*^hW4V(((#Xve=NTwzl7OjCf&=D z1Uoal^4*;oma4N-i8Z1gy;vC5Y#{3@Sg5?$nX;H%EP!KXx&Dr& zr-2xK3zn|&Dt9iOv%+N`^4MM2|H5UBRe|+Q;@J-k{n-<$y0Sap7!IADm#(lor0+^T z`_NLQGE6Ib==l5c_vHr#pHMBV6^c-tnpJN`4GpT*8T5v!H5rv1R0D%*z(cY@HDL~b z-NOOJyH655-uh6FYEr=Yg64H$3fOwokfM5e)N1cOCRj{3-`?T%phE$_g$4a?X0A&! zu)F99#=1SJScuht)oPZo7K`OltKX_0xaO|X=U-;t?|xVRkbOYs^xu~5x<)^Mlb2d7 ztYwLKiT=lzzl$qqSV*?@%g@QPgs>10m|B%lg@dYV5dXDmgQYur#ab4^n;7uBBukrI zm~_T9*Ie7ue*M@#__LjZ9y-(h9?M%tjw`E1EJb%{gd2;KDEqy)L-gIMe)vDr+ zH(d)_9si~{s`S_p&$i9rx%r={xSdPn2R@DE&d7 z&V2d@>|gPTwo2oEBM3cOt$_IDVn_xPm8TRY(%4`3g)I3{I-f{ePQ1^|@6Z3v_ZEEj zy~RsTa!2v%yMFz}UBCO{zyCX@6W%btpv{1nyI5CUY8vb8&ITjQZ%zbQfDI(4tAA0a zC)vQ=j1}(BmA0wswo>l?f_@z42h9ii{vy6EIj~asu$ojuCM1M3H0=y#genwqQL`!! zYLzhvN=rtq%c<5uwLYslGHNQPItSH;tm@9FO*z#wsJ3KPUq)@qss2H=Jxl$s&E|+4 zOzq_3C=c$lIz9gSP*#;aB%=1&DwF{2Rt~B)csIB*l2v1a`|2B7+UZoxqs4J$vaz*; zcBMhBiv*R^0YOz&-P5DG6|E*h0;_|smtBdj-1wIdQV_E=&L$kE>tywl{e_V~h@YXo z{Pp6N@q7Da4?`?OyhN_Fh+RnKKqRG5pY2u5((&= z>3wut>>s-~b~`(IQAE6S%+AnDV|K=!5gQ6z;}a&8eVGy#$N^ zM(Qkpks=vw(KhV+2enyOW4|?{t@|SO>j$-!w`4(`0iurPA*Qo|`5NfcqqRd)^)178 z&!9H1pFTa>dK}w)6SglJ)VAJ{&1&~>%F$ey!i?F_%<57~*Qf8Z&p1Ev`+x8CkwA%t z;1q9c;FPEMiO)Kp9r<1M_{lbp{m;pcj=AMR;nbsdeVx)LM0e%y$LPBEg|hLew;KZwEX#-OG!nC8I5(WTL#dBJ5L<_V3~r|o|> zwZ#`{xQ1rY`^mS*(tLDiN9g?76s5H;BGkzr$xQ^LVChM-bc8)7We*H}?I-M2eVx>a zExFCBU(ly=4lFAMo|nxWcR2^MfLWmVQ3v8Pt_Q$BjknF;px#L&_4DFra&c~ zt5%BsFvHhAUH6b6&vSuXAQ4D(eX1TZr%);sN}r*P=xgbsLSdA4U*URHR5)uK?aGvi zjiF3gv%;#yHLK@Iv#N=V>E%S->Uq+wYHB}IyOOYso!GOjyGAsuIi#ns56f!Su50zz zEkWpER@S_jt648I&&%i-*A<13{2=s)YOMCN1u`7T3~1r&l4Y<6r5&Safib6AJem_@ z?HepQeRR+XJBmyu&1u0Pg(_2o!)!^+N>X{AdH4|SI`R$O{{AZnK6N}o*5H3 z^xBgbY&*)%J-Y3JCto}Bq1WGk{h>42FC&2h%_O{u{V%YF-Y4>gQV4?6QBZ&LDgY&$33Vi zT-xMeVKW%V!~Y5}PFhMB`Vu1pg&onIWO+kTSVnZK5~}6h@@`?SaJq1=Kk?J)6#Ud$s1%h~a(ys2GegOE8oV1+kgSP8YkUvruYV9zk8tSSuDRW!Kblar%Wm2V^ zec5FCGV_F_Wi3;0GqtvxjVnyq7SpX$+LlS-3h@CmyI^~9JN}DnGaIx+f11@bE-YuzkPfE z+U?t+K3Igp@#C^;@)?Cn=eC2St6RCAO;o}h)=XB2SH>r+jiH(R z9}@?}TT1!?`X{axZyDM)w3psFqQzKfa_sLng@$!Mg%ik zArXAWY~niU2t}B}3N8ox4>sU(9Q(S%CHAwHu)N*j(w#$Rp?i{-`c5)d7G(Ju`5CNn zKJdT}foyPK6MiyZiy=SVCKSN9z`~F*&M*wof(ne9NAqKxMlTBEqL7CsH|9MVjhep# za>_2be3)6962gv6c9X3uXnr^LEJB5cPWkARnJG@}&{E^AkI7z-D97r(W%JfYQX(Ml zVO}Eu{^ZG&rB#CEB>ZD>DIxiCQlh|~`+49||IgTS zL+>8zfbQ0{O~OG1y#;a7wfYSY=m&{Xu`50ki_90E{FptSH|76|y(P zb%Pp3t?f|*-u+IKFGy>wpoM&j_jzWu303746^KE$R^&?&8y-oCi+hQkv*+z2Z|^zB z_*nN5TlvvP`ZLRRmv$dzV@}|_DC*CAMCWxrUBR^DdA3T}FwC=M7KLUo!lI-Sz{Z7v zTjt9e>IwLAKk+3j;vTh9Q3E|Hju3MOc~5-c&gYrgB5*zE>aGLN9dMg=@XFsCDChI52^RiK{Y1aV}WT?!H-7*m-OD;UE5cw+g=I!O$(+jJ^Yeat4a#)%V{ z?Z>D;^E9USPIgZT(l%7qn`(p=0zu6XK}tpqqn$ADG2W0_ZjWX+__Y@8w9_D(WS>72 zreU@zS|CX4zCxqV1e+fK2vlK3<&E~&iUcAj{N`B7LqM}7u2`_D12ZfuO1qEh{{XG% zj?3<41NVIORcJ-xPe_5n=`B!~pjDktXRbT*AAjXvRJdY3;t`mw1&3nwT;9xNr zrFkB#!aN6VWg0A2nCL(SCO%W^xGDos$74*xszEJ*&Ui?bQ2-C4!7o@$4m?EAc#fV-844+yZ5$yDNuz3Amhkx8>EZ-lK2+ z(&pQ>qx0DS|J-dH7W+y0yN=E-JF3z0M4$YafRztomGdq6SSDgw%LLV$Q7dzVw7?+% z#{`@M7&L%PP!3}`6{052*}FbR$Y>Ix5N3|`U=c_aDID-0xV%AZkt(fKFUu<~)+U)P==Rjxw{E-g;zDD?^|uV% ze)SoC!rj=w)b@&awQ1?;?8xb}?F|j~*{2&a1Me8~2f)=G!fC<CLIBLA9HY za|C3XQMPAjC94B%ng`WpkCw&OltFchNAqASG^ou4YiFB5Bc~%$0~!fhDudZ+@%a1_ zakmre9hY^=h$Yj@Vzof-NA}x9_<{mHPFjPY1Uw}t?7JLL>URB>nSZ;BZ=Uzq+wZ>p z*m)(Vb&u7_-^BjWZRUfZbg-5ie}3haKfh5wVC-FuFW`Gu553NQOkdJF>3z&L9|u7w z$^Fv1z!os&mAFYU#Tje{m=UlH(g5BK$uFwAcFi6B45L3(;zW&j3EV%Ad54o|kFESB_FidiRrMSVp9Gk5!h=JoBWVd|tzg z#n(*>Y%b_~7LuSa?MUf@?geEAQyiK%oPj`kih|j}F*uTOxwwr9{!lOr7i=0HSOzQi zE%8NIb#Fv!SJX!64MXrBb~n^Lr}UeZk=oh_z2UwRt!$=Wg1&U$Fyyy!=MZKP-CXr! zIvDmH?oVDne*gWre~?rtC=(}XK{7`Ost9puwBr}X{cuy!0UpquS@tru$l;pMB9-=W z61v^69$|<7#_)Z?=S5mC%xSnG?QoTkGpFqkLq*X7y$3S}Lc&{QvWe3Ou@=zVpyR}q z!gJDB3q#(5_@T_6J5~wyD;(n?cT4~fhqY3J1|y*LK*!+aF$YTQW%hC;aO_YZ!d}#8 z%iI06wG`*X!?gH#Ik2*($-|qZ5rc&U%MmuCoqMP$v;wgoMTy5;j98G+Y0w35CW0~m zfe{!6Yy=iEL9mEdiv$-o0qao~S^XLSi%Z(Ye6)GA$s~CtZ??rU580Gk6G=siIJz5&QX&%&a z=t>mBpoV+2<}|t#uTRFPOIm9q_M&wOvIy09pS1Byo{t2m7^UvM%gA~ z@pg%B9`qm(ga!mn^ar!uovAuf{H8QY?-EM0TXyI2E1F7;%O|%voV%eV6$VNJ10{2B ze{XL;19j*sQkbmOv%8wH6Yx)Igei<`23U+P>OC7`M-;mFTzn2TaUEU;_aUyQcCaWq zNwPCFkwKuCp@DYQwXx|e9>Opn03n576RdLySc)#@X3Q7zb+Jnud+UAc*zLZu!I8t!oeo)#Ph)RY>m~^R`zztKgUaH}-=s z>fZy;VNOWjgS{Sugy;}93dI=lTzt^@MA#9=r)f~_;FeH@2OP#n38-s)kQS;qmMn}8 zEQw_7paN#)qm*pJC`o0RSXw-Jc!X0$;#zq4Asb~wO)?M*kF{m2&87s9(&Vm2a?GBxmllEpt}hv$(Wj1&Z{d=2OWtw}(>F<&%0WI6yr5?xU& z_7v;kR8$${Ph-u=hZ0K80=z4Z9gIXXQ$k?1yaH2H3M^c>@P-@kI=WkYad*}eXp7gC z3i{?ksV<)JD^MbzeDc_#C#Cafd5xq4Hu2ckvxP!dS}xiG=?Lb!D8!F{L%tibkNOLg z*Gl~r2f1lFw!3z;+ii3g0cC%8CnL~l_K8*-!yMN`_ zg%5c+`4aH=?neUhBC^0f*-!6MjNWPe!1lX*yOQ3;etI9;3zdbI6z**)ed^ZV(pH#2 zSQEH+mbV>P%eeiC=f}5owB4msx>`q?$c~I`>YGP4#~eLLdsAhE5qbqY(r^p_ra^ql zvfYC z{q%krJu-UtS^fGf-}uDyWBc{DY-dNB&-y-N6JkKXwCC&I=v)|%9a&x;H^dWQ=nzkU zULu|VL${L07F@z(3kq2p$!$6E-&_qbaTDnWMNh1qY#|#2VZ$V{c5deD=ES&xiBTP& zwLc1(7(6kNR-d&$>frqJEy7twdFF4~{yV6CY~VA7Wz4uCgXB0+L@uk$&{C^}CSfv= zs2I1_5demzu?~g$re=0CSM!uVxM3MgpuZxYRTojiv|cfefUYgTCz@6GPBowX{UV52GzD(IIcN zMY;uMx=-B6_qX7k!7`;F-eKE?=6MJaa`X#2>6#w{c71pir1sT=P$Tl|TtPV|=9;G~dNqfMVf{@AZfZp53zSVgy`d@bV0 z5jNi@<`Ku6Zxhog1T?tV=Vo1c)m62D`AgR{-fZqa62 zmuI`r{^r-d`pWvbcW=4os?Xgvd+mdTDYE(O7j9gBN!7XL;DUzvyE=21?Z!Md`0W+> zLgbRgg_N*HC{~e%2_y#I02;6~A27qKMAQflY7ImUc$M~d^E@s$!kF(37-`0OX#vnTa^!&ZY z^#hN;$M%1XJ$$9UiT(A8D+22XV1N8Qv-R6B5S?`84W+}6zxUq7S@!T1xaKccT(PQ# zWR&5jyB{*D2HxX&<(^^Mz-N;lRBaqXkv(wFGm44;TLPwPC;43G0Sg8q^Rcvt#w6al>Yj<6d9wC`3(l#HunYAE zEtT_TuAbRr^k`YEf4D~vcA-Noo!70S)LbhKYjqF)jCJFxz98wma4 zJ>u9J@5`vmpW|lSyKkwD5_Un+>T!&h4ISMVguPG4WJQa`$x&GrUZ)r>n}`5B^sQy; z%%c9-#Llf|)nfM@`tmOseF|yAU7B6`C+gEK{kLNNPW|*RQA`G2STi+9y4ga}OMHj9 z2kQ~`jSb5sVy*lKk!L`n&dQT?G>;#X(9C68km7+VLXc>pq6wIf0N7aoYXl-T@L^*> zTY(ng09HYYRbuJyaTK)lJ^fAKnkDf}*6^xvC*{lKe;?ZB0<5{(V}_7>3C2Pzxh zKnLPQAR-LfqCJH8VQm}nTp)%6&Rz0mU=fD$KrSr4ku{79eIffVfUfWA3$PmVd*F@h z3?%7`a0?;T$4${#=s4~I31sw|BTYtNZUFZ%{uy^F--vE?;?4AM`G%DvH)X;dBYKLz zoXbIRFqRAoEk8Kw*OTVZyAx;$xyuEIGHm;eA`zFtNJ0fL$o zl#yVziNS3k(r_5)*uY)xAv;m4E8iQ=LjL>o>tsFAuXAe(zc%`%-L%{ryZn22lN&IW zW~@jCVq_ZIXYh@J1)3cZJBNNOFQN`pb_#pf;L$N-gdYL`4Wwb1Ipr(~4MZ(~bo4V6 zYEA*w5Dc6Xy6D&uc4SnMB~^>=fYqlW@}i-) zjvAUVTF=~KC+5nx1dH@n`JZ@vE<@OD`di|%KkARL4Sy8Z45@!)8?Z%v^BjLoUM^ov z)=bjI@+@Qt;2_(eKk_GWYJd%?FY`->UI{Wbq@nX@FHms#S@~Iku-q9u;sIGMNLQm) zW1e889vAU|q2Lh@`zYc8QcchT6e3H(A$%bk8?EF+6f9RN;g*s1FdyWs53x!gAXe#v zJ4^hJhdB%%e1Fd#wwxax*Dg17h|!oNY8M>lBkiKNAfU$-7gRxO=19Ao6d7U>u*Aq% zH8lp0M*Fy6Dsq&c&@4*2I7y>Uq*a!;sjROWgdz}(GplA{xTDiUOSVkSsDNfT;pT9F z!VQXONlR#ABUZe=YuD>{-G%o9yH03Ju23XPQ zZX-pzQ_;-8FDK9yQ3Oz5drgy}*HXZ##U+Pwy>b_@LnstJELRgdSQ?Ps7PDv)ZL&-D zNxq;pWOAn?m8@j)w${}oI%aiLUvwK7b{qx3tYVdDcG@i_34z6)pwq+TP;^>KvNvY? zv$;hLmFCSue}npK zOC4|P z=168Z{tw?r@Ljn&NDh1>s5}KGs5VNu+DO%92tHTE5&2I{N(W$w2{C# z9uF{{6GtNa#zZ@uD&%Ya?YCb#{GW5#NKEJ0(9QoCz696uIXAWs;S>5WHZ--|2Z}-+ z?Sm1oHrfZnsX106jP?QIik+(Un|7`F@m=~8r);>M*tKTxE*;fNFcZeMxw_nDFh8aM zF~5-*YOFXEs|eY^6GMk%?A#Qhh?q5S7LT!WRiC)(_(P0ByL>#Xt22Ex&!Ht5-zV)J$o&+(kF^?Y_%U>>1@H%% zNtZ>U4p1OCg%Nv&kZP!wnoR9r<&bJ>$dB2}aN8ayKr;#w3#TV$#$qq)mEUWnnJ4=*Jix|yZ!(%-uIy}MZI zW_>fNz?2V2Hadb`$gesfA>Sq61-hUmFm&SzY+Z%_N*znnMf#g;@69ZIm;UC>Dvs!z zcj#}5UG!t=UHY3lz>`KS<%7`KDDQMB*VsQt}vqh(IkUS|SV! z?|GB6LXMM-2bq_EthUi|6+x_)u{@2%Ets#Ck=joFI+!wiK^l&zGy*Hx>dA7#-|bJx zljX|5PyLnckl?>AM^+ji;vD@oe1pggRWxTI{pX5Z&Th-7URdQ4yNXyZBXc|*2%dk&;?irzR_M&-Y>dj)Jd>(2lL%Y z@M|waxQOAWmMw4CtWsc7TjrvTU%B($3tJXkc*W=jI3hFAipJWKvBU?mAeug&LL?Ce2xwudV~3osm0XM=qvcSA|TV&X@7 zekf=(ww3{*gDz8x#JYU1obMLX!B8*_pRbsQhEprKWQ&=$+2tnNoH@}MlP5K}V=n*F z)ru(^wAQTAce%szMO@qY{k(sSM3r7KLiilz$|w7Es6Y-P;hsq&^Khb*qn z>FirGYA4;;8n7pOr`68*AiZpFAwIvw=a0EVRtJ;K{+eksFPr%cTXAX2sz*#HKXKce z_gkaqU;5+<=alNs>V{C*Biq{+ua31{29b08d%_L!2XYQ5*mT6K%@ioI21&-y4=Idv z9+Hv|s`)`}K8TQ?s(AbCws4iTv7xJ%$9DlrfgbpRpwzc@_0E{fg+2z+oUJt>DamE7 zYcr+uwWcg60}zw+zPeObXWoqZ7Wah44xduBE_wDPa zojs|!A-8VIg)TNfIeT(=!CFdpUp0TtRoiA>RJp#so~9{iA%GStutimvLbFsg=)QayQu6v)u?esP8^YHgDf3M>2 z_53|a??s%YGBOD>3^c?^BQ_e@UPyWDQ5`+P3l3+6CtOvZY%Bk-OY)b3Dr(^yI4ai*qW(p_hs0I=Jd>)+bXK6EXgxAerc54%3Yr$a z8}xU&cX^+@%%EsyP0jM^s-Y+Eai_AW>6LxrjqUe#-`(eLXmECJI+qL+>G(fDIC|x$ zVc&WoCxjG-HPUFZg)C{P&;g|yP}b$uNs}vC9T?i~pX49f{y*#`_LBZ2Iecc#nj4d2 zadYgGg9Y*5hguQjh71~L(D-@G>4FfzI;dhC=Lr-vO5EI(QIlNGLa}jVi$NY88LUJU zL^4QG5R{*)HG|WG2n*06wPcgoYOxtil08E{-aMfXgmbW3M)}0)q{8!xGb~{-Q;mhZ zVlt-+K?KnBZ|i59+`&pkf3Q&HJNxakeN_ehL8X$J8~q(FHk+;J?eFi^pVj}_)!}dS zS2+Kw|Mkoum7!U(#O4X~1W;XUK(~CEL^*dkPxHw&DhF%IiS?n(zy&|?Q z>~Q#N5)CbFm5TLfscHH4i?3Lg%PqU&;_b`XYN9N?h{f6QUkl%qFO=RUtw}-(d!E() zhOK8Cem(Rr?4jQfT=pArCeeD1@Rs~znQK>Y6hN<>BhC_M{91oR-y=naUJ_^ihCn#_ zP4W0-pI+2QQY`DNA63>1NL50GLfOX|n*34Rd z#BTlts`%XZ3w8tTH{Hk?9CeQwf;b))C2@#)J~xM4L4Rv169Uklt~*$iY)KT zNH!uu{}n{y8KEZ5 z9F#T^PR89eagsm?Y9ILt{1pFD{THvig7$&A@kZ;H8&Z$*3gEAG5*Jl*00_npQjQfO1iM@}OM!^E&mI#$^@ zCHjo1-Y@R)B~8!hcXP2_Foq0LimeiV6HK>;hU$6vJen*a9>j>#b-!E|_IgPzWrU@C6ajSx1hgv`EYDa3WG& zYGXDWmR)sK!4i|5wvzbR&{;@sw>#Y?X@x%`Pm+Eg2@uCqseo){wxZ&wXbA-4tB#6N zg~M$=dhF{Z{e7o{)dbk-`md$s+#&IGe1pg?BBDc(&j;<($mZx0ip@m#4B{s zX$a}!JeE3%%nGKqXDCZt(2~dr(i&R1szC0LJaU-w@Ltn|MSv=q&%@ZKSjTNRQ!SaC z=DG#der3ya_jN10X0QKjKi*ed=bpYr@mE)QgUg4G{%P`LZxwseIcd%$NBbr0>_FsM zHh1xMf6P}E@FjgWF4n*GEPC8vvDLISBFm=nKRc#P>i~+tke3pWAC?~`9gCNiq6{D4 z+xQ2F8~>2*6Zrj-L#+=z)Ou*iANKG6!|?X+_pz67==b~f@zW2t9A5JK{ri8v2J&f%&H}@`}N_2KT{pHBzhvB?yod zHJ#-GC_N}8(&Vr#OuOE5v@Q8zWLjGPX3ey8wz}Q5{vLl}H;MzXmyaI211s^+#|sNR ztUuaZXgPh0Wp~Tz4K=TRzbdKU$*wu@`g4bG(C_4WAhpw2myLEJKLb8;9t{hWSIANF zKUPYh@hnTlEvUwY;SRhzMr zw2|0u!b%c`?0~Cu3L`EEAqAQ0Z^iisF*YhP3Elvuq2=!eOBM0bq0UQK^9qPnTE)lcG~rr-B53M)u{T(Fh{y(t!m`BjfOxQTsl zMUN3R+{#0RTc<*zP(oZQI=|nkRQoAANYJY5(d9&s+Nh|NJ(?f*MKLt>G>$6g0bP*4 zcsfgB5+gf+(yt(Kj8%+LEJQvO$7}(OD0({)ZxSiyr3=<>+GH&iYLE|nvCE-2FLgOq zv9?v4E?v24ho#!BKW%vedVlis=4$tkJYKIy&ohT?lPt0Z*8Q#rs4%$gz#UF;*jzXA-i{ zKs)%7KsyLttkIJwpF*9SEl%QMU{Vi>foU8!pxgsq^dQ;-tqhAfi98V6@1a5w>eNB4 z7qm-38t=C_Yve{wy9m)PMUlpUEH!BoXvfmTRqY*OXLl%WkOH&|nNZfQoJyUB;{@UE zklXRRlC)4#o5f{n0y!yeY~v+FD2MCP3Xj9ZF17gLPh0h;+|}mKU%b-(Hhr?>#rjig z?y;Mg2?Vpr4yM;j@0P@w1B=+T9#5d+3a9xUxgxC$eN^$ah5%bpX!PsPu4Vt{gB9O& zxE(eS44NOD<)AQ4GYJ{)&{It=SSjRdnky9ZG}k6!PQkYn0FFTQ%ZiNwvb7o~gFHDL z@Q^M__4~-#)JV=1FK`yk1!0O$q^%{%nB5Yt{N`z=u2RQdpwtO@t( zriwXG=qQ3X&r3y8N6~X$EwZtj7=!nmDv-dBK8box;pTRfdC@9hd=eA@Mcf?4vN4^Z z(k2B^CwbNbW(VPYk}n=oP#ls3N~%kl3d=d2ax>E1nLD_-BIUl8Ego3HR`?qqtr+?k z{BM8g1NP^&`ZIo1*ODye%HTKeMaSnygO^n>2le)n%T``YGl{LXJW=Cv>pL*y`dd59 zHSQkKlRN=i>yn=cylAew=;AzzU2w=Po{R9zIkgVl+GDLF#^rNI+%?($9 zW>X+25uGO(ncte#XDpVK`&}-jAtvJ}T@{F%&e`+J>mD6(OuxSe*;_3lyH~$VKPaxc z?w5Pc*`vQt9&30!eW$(5QmhGzli@de8g24m#hX;N#1P|#02^u(CNV;5P_KeQ7c?Ib z7^*WBR8XxJP2<_1p24gb)hYscOgxGHM{j?Y`en`^Y@as92A zfAGo}`cPYXN7^zR=Ym#I)*o2FXpiP2!_`G3@*~oYB7E#{Q5zbPksm+OB9#5bKgNl4 zEvE%}?}A(4KY;KATT14w$^fYqnl@vM&0}L5n|VL7XP6`L&>5wTov;999EaPq1xoGILnfj7&1k4YFn(eM8f7s^r zNj66)9f(;Pr3%R;*C&EbNpgD4cH~!?&1ttIWU0II3TM({cPg^CBP}y4Y$sTkh^cu_ zz7^3>!c?FOpnP}86v_uNCMZ;!K~ztFe98KMyh|Ut=aY(myne^fGwx>h<##uG#5Eg# z(7kTs&Ud#zw{A{m=oya(*g4c|VLjyEGu%H#6;TO~Lp=%9kbolxf*PuD@Mqlf1q@EVrIE^e`Pk;O)}Ey)jrMPQ=2_E}j3z)s^7LPNm^ zV-2}eZNu_J#2febAXoGIqsHC0PPPdw6W||mrb*V~jpI@h&(bn-w90N&WSk<=*|4Pr zO~B&D1OI7xLZJbqz9P@{*aGPm{n3)V2q+>|02- zI3!q($Tjde7^7seMMy;rP#$_f0WD>9N+TJ>1Yb;PMBXN$7$6+~K*27$pg<{{ z&`XbS8$>4Mh}%l!3-v=o7>>sC!mm)1Ax}ESxkG_AV+jF{gl$HsWL`mLEdWX-ZMnI0 zSBX5W#)tT3d9OrnRIEb$xD?|b#~w6JitiZTF!)rE_sV+(2iEB*FvOX{V&S!N{T{5> zK*ty6P@+bigJNhIwTIUr=*$)yIL#VP1I-Y5La^BquHqVD09e(_N$PQ=tD~w$%A+;m zSnr_P>(ORmYyRNA{QOx~csjYYfvBVTBNcjZ?yyZQ{jt!-wVzRfb5UF-LSs#9)H{m?Hv=jYF`ncVI5sY*Xv*Ewxd zcQ|y;7OUmVV?&nNqG{$N#dH4B*()}k(J)sR*uj5U($iPt>1b+hph!BE zGuh{Yo=|<7esRY1L~mbxeSm&1-z6&#oxAbOzaAGXQ`zyE`_Ec)TYWrVi65gs5j5+T zzbE$tjq4`QCgR*sd>V$E1^76`Gn5@8g#=J8>0qRWM@V@H_o&UNwPw^7*ziE}1*$Uq2rT zO}=@~X_LFonYJudz52A?;2D>%yWH73r@vs%OmD<+NOMK)?Ra z=Xl#9`56ah?DAc7fZa;F(MTe1T&MqT2HS8pwrAiQ-^N!=^p(Gy<87UkpTXp_X6#b< zm)3jRx*~~-n{i;q4E=X~)K-b-PgA`>s+ba?_;>DMh46u8jgULo4wRPwk%ZB~zSpSo z!YgKQag*WYUaAq4STviU88@7y5TOsZ(XXBTqp8xPuUnxvBTq-C?Ftqpk z(^gNLwz?pFE0Argt!>K&j?IPC{*(CPu{Y_&G_;d+1w&?6jz+_TGa3quk*Ef&7sm*9 z=DV{Yl)1N%^1vXcS>~s&LA!M%+-_Hsi&gWFdj0nYe#W-_>;MbZOGAFh{vn?!1s*8{}eDfuvx~V1LaTx0znB;*1efx1S!eg=dYE(Td3INBNPYe z5??T_Sy0_JV@W37zhh}3HGBEgX6X@Y_kzBrtBgH5Pf={69R^ zznp1{&vUb-78k0Y_UG5#KGU*fsqAZ+e$kA13oGi&RfJ>;C*P3t47Atv`!%C`HY~i?h)iJO1;;H+i!$(8;_leq$qO9+V{yT16f4oNd)xytFdM|PPj9Ev@E_gqX15&s1F>zKo&&miiJ{1Ox^ zMtq1keGo`9K$foK$}R$pvZkEC3bK5lY9TD$eH0uIkru@g}i$BeO^=4jAt(d zfxy)XPn2uGm{A3jiVp);Lh(`zB5K47G8i54{D_a|=v*{&F=Gh0?=N_PAAz!)inSJqhsbC z)v91cKv)?mws`(Ug#xS!gKL=O2-6CnQW11rqwo=m+3_Msd8m=%t0nRs4WQN#O!D&z z=MmstVEB*h$Ya}hp;tN!ofwh?nmK$frExTIL4PEg>@o6KG>e@o4RKr&eFa(IFN5Sn zNL)3F*>RDIc!!Auu%I*U06Gg^R;Zek%ftO%5h4JH;sbH^RoNXN0F@#_^{Md$uowiW z1CY57Rc$ECK&wH}9l&28JXk_UsZs7dRdyOjl`+&H8la=BGPJ=vhHing$=WJ&H}NvY%otPZ5sfRf zbPOeG`=G=h9u7gE;i>z8Hlg+KQKP1|m)F$xQdtjl%7wKNeQ*$lwa>>#hk~K`Q#bU2uW-_XUKtxwGX5> zvR8%)PT=OqD;F3RCrC7+mKo)`xFuUAI(d^uU;p3Q>p*+myuA=G5I%OkX4t*dUVHE} z+KUQjBkhfkwwKxjs#1%O@GXN!Mw?2_Ci)t9<|6pSDF(J_G-nsM0vTj51)wK^zTjRm z$PoRCczCEN<0DPrUm1=ID(8(+BIBbUe()HjnUY5yNvB4}B0+GEzh|6y?=(7UoFm;0 ze>?|{+EPb|CPI6;d@Q#H0(N3+NM?p07I=!Kpw%FASc@TN_On~)Yh@okN^PNB*vCE? z*T@oEtnZ_iKK6l;DLb~My7TB!YU=;8y*#nkXm9*)X>X{S(s)N&G_Jh`)LrGR{qRvD z_}JDK(2>Re+qR;Ce;;k*618=BoX5A79pQ~N2oD~aKFS2(*Tn`;qCPd{6;{DFHnJRZ z=!Y@}yx>f%7*Gcg#e!fKBuG<;jj3n20)(n4s>FGK2SNZ98cu2C1)a#jg~bok1CWrx zm~4RBLqsg;j{-EpDT6c1snQs4CcGgq>7e{oa3}erF*i`^9SQ_UlulXV-QIjR!uRT+W(gMa8}=Y;d&p$6*=!XRVwKxwt;9_IiYQvGHjhnyN&lZk zifHla3;Y3xm3hQ1;AlLO^*N_vx4KQQ>;K;GLtFT~*CG z*B`RG~6whaY`|$;2D!Sajn9&Cm z3kOE^0^;lum8+bXNjaQ{11Bvn0e3=9OS$rU=*m4;Ub$ytPRmH~cil^;uN)(@C@#qZ zJrC92dCh+0L<52Yo=gvMgpG_uJu7qr?oad*U`$1~2}3N0S}8UWHn2hgJuZh_>F^w@ zMC9zt6uwB6FsX2?+pd2g#i-&iu?ebB;r1hPX!!ok6Yl@F-5eP+_{Ve5NA3=v4@>Ja z8LHV0-yKyK!HMk1C-02A_l@W~J#TEd?}qk3-aC*0+8b(SqVEdtyFz_864J-^9j52F zu6KwlzoO6CE#5lj=HJzSDz1D;pYy=bx$q$N~#B-mvP?Kd3QuvvWZ==}%oXFnNjg7lx~zP{nuVey~;8z=M% zB7%Vxk8Q^=6(+U=(XXJwXEX&7KLC{#s460~-#o_t3uk zJ`i7|;h<*);&~hLbI|at@Luv~rZB3sfXpWIAk{AiyCG?wa(Yn1LVi$B>OWj6?ipIo z9+5ns{D67%YuKJa>8YVf#8)H_k;4x9Ql{l%fmR7T9zrpbYOc`pG+f!DS)o0%j6EyZ z9Ek{q?18`p3`BM}BqXKExe+>6v<2ZIB@5FKC*ZhTh-aUZR$iAP@<#$k!R@75|L&n# zh*yT;Ti7kV>#yYk@YvT;ssNlHkuE54zVGGFT%d}h5ur~Yy%jBV^A@^cJQU4bQ5|WX z0a1ZDK@No637Q$=ujmLF1zg57DuC==-lQaQ^+JpWquen4{jJ;e+o)x;uiwfxT(2h& zk8R;w`UhKYL<2RPTz@@+GoIo)A?Y<{lMA$@XYwUL(c#(`Mq{X=_jsyU(wLEDn)u*d z;Eo3HXt@~|JcV?$7s>=GJoVI#!~aK#rGLyX;>7yob$&$YnuZl{L_#lj( za5rm2V2vNLV`&^iXL{Hs^%5!egf)=4IZWrxx|4Sg(guokX$%*@-UfxA=7I<+In^OW zmrm%@nJ4Mf$$EosQ+a=*{bL)Cv@^8=U7)0oqQe;m>(T-_u?yvaGTi%E*+;ri!Vq1? z`@kLih_@UwIG54ckzOF-YorfU^I#EV8ga_R+yGubf*f*2-L_Ab$*NHy5SI2)9vhsZ z;C)mC^zt7he5%v{s6gtgyED?M08A|y*#Hr2o)AC;tjh4q;PC;l!R$BzK!w6VAs+ESWr}<& zzgb3VV{GV3{;e`MlcD`L-rN19eBHDZaHaOPIk@w9% z(odryV*gr*bj2&pCjBbfm6u0-%I7?@ktbkap@d~Gf`=LrF*t&{(>YWOFNzKq+2IYD zVr5N|vdQ6Gs>0mt%oxwmY{+50nPX)A;L%2;eDWt51+d*F(af7p);M>P(h5l1wGx5w zZq)S}SQutU!VB^EVG7hmz^=Y|VOV#D7wVgbk4$o=*iL;*$~kEgGuZ+zX=^ad#7Q`; zZ(%z}4j;RN4uk9PSGGSZ;nRu19&UrjqljwBynrlpR+L!x@>CwLpD^7_#wcv$rFuWI z6sFq!!|L>C4Hd-C<&sp3dBj$ahXQz5O&lP9R}!^+$}* zV?2;ynZAf0BW23C+Av&D)A(HdAg(N%_5-DJ&n*>(<~(-mW3X2|f=B)b`4M=z1uvlU zS}BLX56b8S0pW^E1MsCxPdD?hXz#t}U-0t>u8&3^^O$|#@pXExxqI98jawA6>kF<{ z@1xRhoA12)!1)*4J1x#0RWhzST(Yv|f^FOH+M;y$U-p@mM@Mvhs-M&c&Nk{NK`g`P zOEG$3`y;ZIY$xM+=YDwfv9h5QEuqFhva~>Y9K%bPyK%YaiXeyZKIZ?a~q%BAJb9qtii(@i|&P+BB zf=)&-8LBn_gb3lhnnL-}{y;3z(8Ogc@KEem#ZnCvk&1}?5tSCUIK}5ep+|Oc0tv`a zv;qkeD##F~?Sp_TsN2LBDW7s^);5(_M&b-lwWdHfA|&?N5xPQm;+?WF_8LNrq;d$RK@I6ql2;|7#+%;q|Z~13P~sm52th_R^n$p6e(UCgIxQtSs_vQtEpsEI?{HVC1(VrLml~vWK#+dr_9^n}o zxd5d$eOiAC8%b21qBE%4gII48SG+UeyYc;@9IYf!gNH`@gJ-zZHA1UG!T{Khn+pVC zpe`X{sR)jI)N`kRE97!C zQc@v>!XcWzOfm?0V+WB%U(*5h&-3joMAqlbjabZ{5KL34Bo8? zEWG(0RXh*F(Sg}isD+HjJ`HA-E1 zvK;X5RKQ)NEPfz@PW|LYz92welFUS$o$-vy7<7U?!@WhFEq{)J6ahzK?8}S}aCKaV zQQD+BTa58^oLDWaX5-QJYB)=oCwR6!o>@wxTLxicAP2(dI8aGNxbS?0dOY>W?Ugw} z>QLQ@6NEq00?$YeRU*lkg2G0LGB#pv7|Vn&FvOK2tnx6Xa)DDs!i8xCC#9%xYSMg# z3>M=LcGdBZjz28FET0B+J}z9rquIEYq`D{~1r9^X;)V+wvdl2EXaX1+vG7(C_=9*( zO-6)PF<42DiPoY>v(kL^8K{%>p78eG*?h0nUV2}uYc2_b|8k_#lfbGhrjZxSGZ5NSvO z(L#bW6vQ$B*8dowfGsJ8Pf&o!35luWkDK3!JwP1!jDi{q|uroCv&}nP=91!E>Q) zNDA(l?V(}=%y0%tz=~u!EC(9e?=%BPoOz5eb{y_&$?IC(ey<_sn>dQ|oTQ^MwV1 z55kQu=DbS)9kLQI4`$MU$FjbgC(IwLH}b7RB_)T<7R;Nq_77c|x67J3?|FMTqp{?TJ??u-OilWBtqmEIF|osSGH z|EE=mr*V8PKAiPLT=tjtcO|}$88^mDy#2lf8tNtH_V2d;m-fA#_`Z!~s>DA>q{o_Q z&;|s|WOU-L4pS3Ur4&3ZOEs$gk>MEP<~X10NRx-UrapRFFbdDc>HoV~xRRKrpKb&K z%Jla*;Z|O}jFF=e*0ZcB&pK8fbb~LHZeVmlH+4)J;zp7b_6V{zzn=k?~-;&)el!J0!%I-UU|7jD*CF zr`(tto!U|Iqms+s2Jb%a&1rsLhVPV))g9XFcll2SmIn3(vx8m1zR>bePdFpIID9JN zjx3G55V;<$h#rq6$L7ZN#Lkx{m)4fHm7XulD_dFCTkb7iTz+A?fBM1ceKW!{PR#i8 z%z~MFXMR{Qzv5_RM&-83%doZ&^96xDCIue6DA=Z{O}++uXi+UDK*f8(Y1r zHnm`c_9kmHxVi=YF4w{zUYq5yUPAC&KKQ^4KwF7i4`%1Dur@-@L-}pcP5BMz3G`s> zY%{)|0SK*jY>m~5m8rI%^coxuUd&9b#R>xpaTb37TU}tyhwmH@Vk=O)5upkAYf)zr z%CCio`eu78ikd##mNM%hY<&spmE9NXUZj${u>M~QJa^SwY`3Eo7H+cl!9bf9+O2Rb zylv?^lx)K~+NS(Aw9={J#atyHtZzZfHUQI+gDnmO1<6K|AijUR;Ci zo7AxVKZJJxA$aa9wP$$U<|FSpuriljb!coP^=C za7QC0=p3GgGqz%V_J9N>Bw&7OZ&sXKhN}rK_ zBv9J<@cz)vf ziRUMtpLl-a`HANzo}YLD;suBoAYOoY0pbOS7a(4Mcmd)Ch!-SYka$7j1&J3VUXXY} z;suEpBwmnsA>xII7b0GWcp>72h!-MWhUYIyx;)ID4CQg_*Vd8{|6DCfC zI1$+xG2+FD7b9Mb zcroI|h!-PX%)wLgUdekU@73qjQ}SQQetO8zVPujD`GfID`O|4RNV`LA)_$DHFxW6p7et51*gKh-TyTl2b;7uKB? r*3W+&`;C+07ClD7NGtg|F8f5H!(3~86Y5F{~s0SKbSx7ABc;Hiv4KWKOFA| z1i(;0U~)?IOg~!J4;TJ{zFC=cu#t^{JrEGc4+X~fv6g!he=v+(oe6+|Krw$rsQ(28 zXqc(Jnaz*(qXYl_@iS3sqAxQuaQcY_Tl{~1KtPCQ)*hxm+9nW?%smiL1SZu?QG~gP zfiVz};_Qzf%MaLq!K|{)e?%Z4C9og<-_7H@-~JSD z;ml7TXj+FZ?f)#YkNdijzOlak4yYkC1fss7KG=Ykz!b<4BM=Z=IWQa$(0|uWEsV4K z`X>4YrUsn@0s;tOgqZ0J7!22e4?s)mgXFL6`5_=7{)zvZg8YI7T9RZ~1PZ}QNTy(5 z00DwEfL{K&2Oxo08dMN5)GSH+K*R_N1}~gh9kVdRVj(AnECji}gG!JDvmQ#dR62_; z28`R!zr>GB&HX-eU_#2qdYKgxT}?y%Wx$)3d8UsB>5#ISmT5Yv-9ANQ5q!bJ$X05Q&V-WBXr%h%L(^Hf}DXuSYAAwZ2iR0ABilT&V9spwLQj0E-lgH zE?t}Na6d-F;z*hxOECeB66Th?_a3|V4mQZ{C9|$=ROiZm$jp0S)O&2#HT&N#y-DN) zC@bf&<67tgtRfoE+X|H_{<0tQBe)B(iNt?X5C=p7^5VX(qtGd?t(&}=IEn)`qWegD9}=f-SeS$J6Ff<7e#JIZp94!XtybW9?=1upFx zGB6aUm+sN=mnwd>vK(7Z);A~2bpASIcHyPQf+CCj6d%^a|B?!LUFv2?Y;?W`u^v*^w7-fR>!zBqgzzQdq|dv&V>Ki4AsyevyiH`{;f4nXhfZ z9N7B))|JjA19)9~ZNKZ{#~!b9#CnT`+k=ohoFeZs1(`@5Y)_^}hx*~t!17o-k^&=O z-`Hy~!H7dng2f#llxL5P-?A}@`@PTjp%aO3TkrdgAk~hc4V&yS$sTHQ#!Q+&Ws6m2 zvP!e~iQVJO|Iz^HEEQW*3UIY!@#cE7sK_5?Ys;6EBde4oOr|C=Tx(hOR`llBfE*enVzK#>^b2(n7z#AJ06+pGUq4 z60d<@A7OpoJ4%_4H*7Z2Vzcuqba%Ma#^BJI-VKw>ZoTe-W1ub1K)H9y;?kAAM@rXb zZk+y_R!{SLE1dCV{ajRqA1xLV8#4I--l1nd1TTM)`Q2 z3SJ6dh(?{nriUFAK~^*Rs%BTR2*=Zn$tS-r7ll7w!tqMmn+Hus_i1?*dWc)3R$IVNH1tuEwg{F~y^|g@!v&)F-Yg3cf z;*c`^Df3oFX9asY$r8}Cd3c;#i4x_D=)KCaFnS-@d=V6Ki2a?=k|RsC_Bt*kImi$((qu~+)~BLFnTU~Zj4Z-!ZH%p zB*@gC6X*g@-uRg>z^z?t$rnHXdhA5n3R>#luBT)ISgK=fe@2pJ>U+iFwZ$MPb|>At z=ZauVCF;BCn#4GDA|fKav473?56MNV2N#_xKoodD1yJ-hW*^~(Jlbb7m{cGIcB z4^B#xKt9#%*Q@@1Ex8^*OXfGot;5JeId%e;-3>>dGT$TwD1>~Mkd4fD4|=DU-;7Y} zh7ptu?@cMy^}J=)Vy)PGUcB{qtZX*8xxYkc)n<^l9a(EE(9-4h?uh*L0;F<&u57vs zza}e9uy4A<&7Q5Yw~Ow5GCZMAL(rf<9`GpaF`~rDb0mChbboXou=GS zZ)@Fcxuw>nAH{yCxP3msa(~~1_+x2wN2g9%v{WvqE@flY5SO)AYO1N;8#g)2-m5laX$wvlo8b`qSpRta(mvX zm8U&akYB4NC=ZnR{LECMV-1tnf1G_}!k>}zEI_5Q}k+kVbC z8_p5E#VVH1t-BdVd~TA1-gwTi&d65Z7MvApiIBz39?pEhqSh1FE{?NTf=&hK4G9@WG>JSqY|95*{)U*AC@ zK{=d<$`~Qm_mcbo?bEpcqs2FJMQ2Edgbo!WFni=2#zlp40U9CMhKv&KJL zgm*j1MErI_#&pU& zpjrbWmTR`Y-x0)KRWN5tu}1!tcxD$1x}(hOgn>G1+6_d530KiI1NZwkzVv;tjQ*nA zDVVC??GX4zY`jyfb>~imUUtj-lAGR^&+k_k3Cg_-ian4=5DRSIF8MW0F2~}gW<_^z zb-&9HT6;9@Ki2zJ=+&K~vHsdrF{g~oZ4KenvE!+eNPv_%ks-(gAS!>xat$o5X-mn{ z`BETsHsJlXFEz0J;wlhfJwo&R_`wc1T041ERl==6?W8v8&0*R-*}duAcxY9X<`S$L zg!0x*#p|I;*TSkMoGW11_22mm5jf>k%Y^#xhj)BsiRa>~<}PUJw%-dPJNmz;!rNzp~ zZ2OGlcFu{(3W}t}*1zQ`mAgjNnasWY-Cjaewt`xJcX<68Z&6nwv-o57s}+#_SL%j) zJndH~JyIG~_1W((z%1|JSS^Eb=dV`yVl`-B?r;AD?fUL6+^>7=!b?dbxwPGufCot- zL|Lp~2scmp_KGXBHlek6AC69L^Xcadn{3ohiHP>~d2V3ANlcBl%*OL02hn|Rmm4c~ zt39~J1w&|YxG1ba7!O|#a7}$%{V7EpE1Lc5d2?AIB}6HdZpQD9`E)EQg2N&u19RY` z%vkCgiH=T346- zQJ%c^3U#oLe-I;25c6eGwM9l$6GIP&KrP8PgjDbPV3%a%Y&uVx5N8CqPc88Y@S+wB zK2K8SGXI1pTdn3HHzapNUkyV-zr}&>rL!dz636WQ244unj_y+fu z6ygu@`-1vSp0vz$Q;5Gjj$Km#Z9{PG?ikaJr1Yzwk&HbOTt+W7BoOpRlf^^fv1OIZ za)}`kB^3@zeT77GREy^|bGayf6DVEO0nh;1s2L}pX)(elALt%CB@2MJ?u zYAkh87*AGW*cDMR(Ba`YT4I8Lxni=ajl)94>Y@5aDPzdmrazmrq;|Q+E1~!A24tut zs;n|b$u_yPC$2zyA)C4FQX=FsA+M>T3|%dUpSa!{7BA_b^x-8VMz)2ujeGC?YZUj> zl97x2 z&85tzDY_CkICVX^;_U1?L#n+N`E2Y4iV|!*Dr%yUe6vh6D$SNzkRKxi&bjdFkkv^UV_8%LnP(co$` z6XLYMX$=T;LkLo}){;p}LNLSHH3fAQWSB8fx{{{zc|){S$|cBD1NPY}(yJG+a~pD! zUWupf6fr&pZbfZ*&5#Fo?@USbn1EVdk1?j<^^fCYB)4&O^b|iniT_2w&vU7EqL#RL z7tH&n>+1p1UAJrjE!~x92BJO2CAa3Uxe{m;5t;t}+vrOJ79()aW}Nq_=%0^<(g!Ph zu#5$9##;^~l%gR8UUSb>)J%P%(Zl`Qg9&1BSKK`6M<-0WWXTuCyug@y$4gd(x^7LT zF#+y;?A=z-%;4ywAL|5+WSSeEJj)s(& zqByXz-u#n!6o&h8t@>%a5iPcPh24+Mfzb9i=U?(%Aa&~_b@{ zLw6NQ;fEEcBuMF7q5BDE!c0+3a%5<02t{8HO7>r}j&k5_t+ni|PF5Vwtb;ETShPU) zp%mFbtqUp*48Cxn+33NO1fE@%Kw)b%X{h+M?@Y0LyHmR02$04xAeV6WCnB+4F$u-6 zxBx}vRDBgU#O6|pORhpcw5Gxt9Z!0!_G9Wgf7PMy1D(>}Hoz{>O_fPEQ_W?UN9nnv z3hp}E$(^axlN_ZCquxsmb>PSC^icPku}*c?>^s2RVYYXePV&mE7)Jl}n^7T+waX{Q zu6)5>z{mBQ{e6)|UxKa@*MiMoHT5GR6p;)@&VQXqnAvjol@f@H$c^~5W-1}tN(c^0T5j#1ib4}Nao7ir4cU?+ArjvV-jB}{JL$mVc&Y`zL zE6ZTYk|DD2j&PQte$w8&ck zMTAvh)4f77uqndPBhb7FlT?!2T?~JS4bX~jS93?o!^if{-Uruul!DZM7kNb)b;2=W zyAZ{%QN`*6pK{hP7>4O9PlOV{X9AbF%!W+n90B=f-QC@>;VV20*%}%Yh^l{D> z7AS3J^@31qz?>~@taRy+(pddnZV6hO7*z>h;?cLhCYzrC_-$D_Pm&R^M%m7z3*5c| zagLkfa+glZ{D;V(F#5XeH9bg;hsjBXKyZ#VA-(CkK2Wjs{(0!-J;(WeQ+(U~Jw|+{ zX7!KPAGWuVI{a-iJj7(xd6&VNy0*Pz_7ljpe=0ZNFaK1E>JstyLpJXF+E*S^M%{kl{OW#RIh#P316`{h9+sJGS+m4R5v6V2f z!W7#Fngn2eyb3_v!cqb0xbK&suymc~|1_VfK3_NT-rs6`(*Aka`F!-y<`RFfe*zHM zC5+TgDB)Lpu|I|J$lNvcoq0?#ans~XqFG``lGw&2f<+ z;M&s$97~n+7@chqDve528fiA|iV1E+GEj{$P>1~>1T2Xyp)ihX4iPr`w zCj?}H0+}VRlQy<{=zr55sv-|?bg>xmVUk=~ws)HWPekjNW}j(~L?=5IdU4`KnMidZ z#SRHl&VXc+jz-jD)TDZ16wNrH{iY)o#{4W=O7u?{N4$?;o9h}^Y3BL)uduKxTNd1+ zb80wbd2B8=I+|ws%XLc!tyTfFo#97hji4+&PWp06MGGo54X~uHI{YdKp_r5nj4}<@ zH@Tzw61cWj_Jf69)3LS6i`bo3tcIqzxScL;vDBuEYJ`}zLvfv9#P$y88Q7W4_DFu= zRp87OPm`v@7Y*Y=i3QUIff5B)8Q>`oTci%c_*+B(RM<9Ii!Pvzj9PF*6gKxnMm$_- zTa=0Zd!K@*GhJo+9@r2y{OZ@&@;i(htZlLRY!EPgTJkJEJjh z&z)H}7(}xTJowuCXp%iH=6&(en7Pq^qOcW993z>SG#M~&r0iu=5+HnJBCuvSS!fx> zMVL;hn#^jR^&d6T`>Bb*SQ7qF+715oIRA?wlT1-Y69l4}k68Tx`P3aI|fuQW_$ z5wBt-N13b|4wp`)hEqw9Qz4o>e=f@R0%!?k5Sb(?exWR4X@Ie3Je-*+zU^5Hw14VXDe6)KZh0IN?SSFsP7cdy zfG|ep3g&)ykF}m1Q)uM2K<5n`l~|{US#5o3(R`1m>bm6yxTc~*F%y#_BYYh`p01of zmpdBOpVCtBSJ_pCF3?MTm_b%zl0Xc&JV}>s9^8%NKC;;UD2F`WvXCm1f1!yv=C^+; zno9$Y`V(_x3aNetAp^*jEI`h+aiZ}d9gz1Fcs(2?-|ef8ogLpT)y#6eX_t@Sv18ug z%udqYvuto>$=8%+^;lO{RvydPJ5~TW(p)?iVLI;T}1E-ZOZJ|MyFSvZMki|;U}ANC}IMPEp6m19kdod+EI6_o_|4*@;P z=y#Jf+p0y3Rd7&S8|{a;DJgX}ZMSdC_+K9lQO{TZ2oBeS158Kebl2SPD%jELw0b;=vyui(l#gQ<#R6s#X~Tga#kv$&mK2c?rvl3m#u5B0 z;rk`QisV$NChJ&ujV!c`S+K`eUQepk`}Eu9n2Z#9S?GzgSsIsw!REK^BFm83Hs<`! za9N(5KK>qC@ewlLe7n|e4qY@c+1>048G**OD#W@0k81g2Cn^gt0nlq?(kbho!pids zF3JRP{1AgUe18vF1lGN-Wgb-Tc~fc#l&1b#G_|rYyoJiDju7}lo%#s;o#vD%J}qhh zDOQ*?MpdsV2%)4bpGv3W`T2Om)eyyBPkpX9Kc`+&ZbzqTI2Wx3;c^{89^3O8Y)?m5 zSCDLY6vvlEi{3b3`LDWI$oVn??>*F=eT;AD86JL-wlA$taiIxG2e$9h_(T)l$CE@j zf8kQ)ZkgC-TML;n{;0k(FkoOI2uy#!T*>prf zj=Fa9F`8*WZd4wBE3o|DZCRo25Qb$$u|4yqABtQDgzwT<0x7Kk{AteD8-wU2_8ii> zSEluo#j`zEjQ%-rB2XG8rbU_0_1rE%CAaDNHTWLI0C&3V)Nn z%nDCzmb!x(6BEjW0osV7=uwpsp(xdgQG{$HocC3(bvs=0Z^A{&$Zh!_Ofd8-ke%14 zQMSj{GVZrqcgAQ;*Sz4gj|!v1g}CM0meB+vCq4rd1tys+HUDj@Jw8s4*-P~cUc<~ht#x4u+k6MOYNHoU-nEi?I;O2lVXKKu@ zCBTe?q?9t!&(m#^k$B>`hK%EnHHDkT$v)B^QaD zBd1E~Rf+X`K<8R`Ie3(glD6t0lyT4Ubn38JCi=tJ^v0vy4N)}-YgLv})Q+hw*|d_~ zb7Gm1ZU~_&tp@w;E3KwBS>9P9-3C78jNnJUwGDDzJeKGl66#S4V#2;?%1-nA$Up}u zNZ)aSSD6D>g#FZK6Quw`9RJKDO5?GuYy&bjNfQ@b5lO1{crPOZ0LVg7Z^sneWTFr{ zh97eU`tIj+-RfVqi;bWqySx_tZX*HIs@7M?@SQ<|&kERGz0WaO_(X$mSqJrBC_Jqo zCr`sh_>q9UsB8?Dhl1Y_gb-e^AvuSB`6$anfhsaE@zZof)r7$+dmmGwSK!iA*krnu zf6IoIkv$?ZF-GWh@9(YZ-q%>8Fur~KdP!Zcu+&_qeNO|T*m!UH3Uog3TR-ngFYCTm zKGi-}HrtO@ODCUbK0oL@kAO{QR*bA*THSdXj!Y6*^@NQ9gW;8hW-_$_;RVp3Vvka~ z2ozG7f>~_7sYymCgQk=G^G)M(OpRYl!~>fCr;XVZA6fn5uL3jsKsE)4Y=vUN77mZb*9VX_mm~Jx zr?NPKVW$s;|b!uazlLgBtD8 zlpqN>GqfUL4t+{4eVWSP#TylA8woh<5r1I=7Hrl$ZOaHk!9SQ}szNl2gcI*Xf87g@ zJi%;HR4f7umEP*wZAsh&Sk-lxu3Erdx412qN8llcPrJ%p6I0@4%|R2M1G!IAmJa$5ty#AKEENSz zdS-%-8OSF->^en~b%L%~W=&H*QAK~Pm7T7JuM^{g zoVV-O0o*sq=f9iQsY%6-ux$<4e{U4dkuI>AspoI;=7VYWObbQ1NYgOL3KAw*@Q*;( zRMO+RwD+u8&IC}^iKj^5@l6xM5SWjcs87Jb1G3)m9s^Z-%D!R#QGZwzU!uAGY*w>= z?ogwhiTIdI9g}Q=usi{!Xt2y?7G3d)Y59v|NgwDZz=HVw0j^|tJgB!V!qzA~Jd+;p z^=r!Os-dqqW?eSnm3nIk{Br0-Y5e=~K<9{SRf`u{xoz?x+l)Oo6+p?p0NRZGHfk%? zHWPD7`A?G;@~B?|>%rNe2loAO=C=DK%R5mn_FF25-WJP|P(BSEu%nVpPpz%c7E+r= zi=&pFJjKS@Uc=pA!wKW*cZT~RkM8_s+a z^9z=RbLu(vOIxe<=L zSTlc8OnpdOd+eu>Hmz>R@}Ge}Fd`|a91?722;U+2%46kE$lcBlCisL!q-5t{u^4$s zc?CV2?JWEK3d4@9!R!32`-Jk7?yF%~2#bCN`jIq8+3j;wtqX7&cU@jf8hY*W7yIMfYA z$dAG?-^qh80ODo-A)*)yK&&aM8Zb&SdXI6O{g@#nflF3&s6|A925P07+O*{%%7mmP zBrZ&dR=Qj5_e-5ufzLtQWqtFy{Givr$O<5mc#z24K>y@2rsM20aF+FfWs{bW2{%T# zk6#`CnZ4qUy(8RzJ-cG(Ot>q(jTf9$c2O=8=Pj2~R(-685 z+swB8Dns7{j;m$b_7tw~H+kmVNK3*<1=&9=dGJ-wV^FYcvLWxX455)|9NXzuXa}Bc zu9q(l;f=4eT0?SIymP-o`$DjJ9r3ckK+1iZ>=Lb&Hz3zR31B)H$$W^-y^^dVZv zOdsn1P^>O2ej$hTJf`}_j2%jdlQ(l8c*C>Yc*{cHQxWVCBqGn0Nm4;pa^PH258ZRF zh6LGDm319lsMlLKl-Ny@J;(W?x*G@|!sfx|UG`dA9De=7R|Ywzuchf;{C09|V`?*y z>DR4rSKI2!cl`QyGD*+QYyY_?{lWh_9$lxJYOUz^LHu2cLY?H)%~O9zlby_rVKJ6b zCCSI~!Jrm-lvG~AZ?K9!jKyXTjC^`-4C z{`zFpLtD-ZN*(HvTTtnI0QP}DHD&m~JUT^AFB4l#`n3p4GPg8M@H#~(c?rPXm=p$#QkDyEC8`tR5ZS3W`kEsCb-AZ&LKi507377`=?c(iv(c(@{ z*={h>GJOK7LzscCYkwPmplW*l%U1j_RV}Z*PbB*nY>&&A8TMfeQV-?IeFIKLVq@uk z1=ttQO=8iR42ehD*PG1srf4GjX_g%kaWiNjR$L$5hi-IKlv{+`-1dIoY|MoId4pa= z0;+EDcjQHPMDf+UpGy*i_yd6ZLGRY%k;I zbq&MKjpLZ8Mv>k-r8++diJR@%yf6gcf-hJ*iUU#$cYGhLgEoWcTFKg=tp3LVs-*o1 z%H$(n&R@}m2Y6HFyiL@?^p_J1U^mZC{zEOEca7>pI@6R2nJA$8aEZpD`rX|qroXNC ziXD+5Z>gFRmrw@Z5HgLGpo~CXpy(*mZoQ|tk|Tq^29KX8uEm8b2&J=+>8TCT-4(*y zx5B=_*{;6|`jH&&g@V_@L=A5M^LUBx&}}`| zmV0XR)=oyhNchChLmT#AeK=>?7#^D!rQ0RPG3L`Z*sUqtJ;KtD_7(H$X45c7zyg(- zM)np9A2QcSD3}*AU}xU%aP9m`t;WshdOglv%IX|)&t(DB@fon}wp=w^5_Qq$HC9I))GD^pup**?oL*`__Bjx7+O~0h8e^>5hwml`VauX!)c!zqNrbn5*JSH`}_Yszdo8tkZ$2 z^CyF$_lVKoUXtY=OA;$s^nl>VX*fj2!#56?f;@HyQrjC%TR4f~uP2%t3Wm)XxxxDn zpqk#^kL@zqM>D)HuDzu!6BfE1V+hTz+w>*Z$2UY!2vyZ)bFxdMV*jljXgLis+nuP= zMC=yaY(6ViJ)svxb@KcRS7OzOFn?e}0CYP4TQCNY>Xh+V@06U_^mc47I)0JLRsV%! zd1Py@08TTPq}Rii)Qe<2+upCm*hX>EPR;_*?j1R_@iZ%aA}&bCO_>LU3Fy(#LJ*-s zm^|Y|aU!xbw;qOB_+qFr1>wDbkhhlJ4?1Be6d*V=nhu7d6GSnlvK7M^2%}RZp(|C- zQfzB6RPr_ZOF|0^8r=`1sM)sL9rVzu)oQO=|B~ga*UDV+Ss!2d=l*yGr$eqONyt*g zzghGdm&*6OoC{0;hvwe>_0cA^#f3btn<7cW`Dy%oodMQ)ujlZhfZ5Eo!uOLnJcBqhg1+SwMOQJ}eJr#0+r zpWhcinS&0^2gk zpZ{nT;7hw&*ZgD^;R{%w>DF&v(+SYGBGP#mKT_X`ALQKC=c)lfBgfADUMO`Ui3Ou; zOQ>cAnIU7j1g)hYF+g<3L3D`TA%}+}>nZQO8y-3vt!ra2S^JE_K+d`<6#87-f_e&~5X{OUId-F~QzotWr^E%MVlxyRm_06>-uPs@DrLoq- zMaljl!Yg~++OfqC-fuA4>-{Qs-^Qx((U$AjdmVeXiU4P8PbuH7jS-Spa_cuGkcN=- zZ)I~)TcXz&6B+0r;<@5z+vn+rSle&8J0cGSKM+v9`(ygZ@Pu;4ySW0Q@0p@4QB;#v z%Hn_ILIsYkxTdURF+}Wc#!X-;jeHlON>6ha5_#L38nQ2Ej};}dJI;C_rCt=#Y#E%t zvU_R#D0;J(rAx}o>jn|n0K#zL){t}}tNZ6Wej z1*f*}ncM222pI}eO=i?yy7}97OZ|a2j?|O}0fO1TZ+3Ld%ZTl*Y}2$SKJF=MQfPwi zPx@v_a3ubF+(_=r^EpOna*^~|#d-bShm6*g96e@BUV-HGsLTS$;3ENN~8BSo;0T~Ok`mp1uB1D_E02&5KoEBY(*3Y>NvXQ^O z@{t%|P!wl_Bg*vXwC=bNh=-4=fAq_KA1W!n4heWgS%WiUKYdml9{U_}>v7t7OxO)A z|0#~r)8lmXIC$`1IG&wTtQyx$?TbS5UG+L?-DDr0 zfwIeACMiFmfc=immSOvHeZU{P+Aiq4aQomXeiXWLxg8}^tBYb!3i~bx6ZLxVI_+hQMr5)fJ9na*a!znXVCPf0FDNud!nAE zN0?K5E`Cs|hv$>zeVcaRxp`fE11XX81-YIIWwp+B?nfX~J`Eaei`htSFx3EL!x_4d zHfEtC;FXqYtkI9@jZ`&8Mv)~TYB@Y5`bW*$bPiTNRmzgte^Ex9R0HTAa1N+X-pMN} zjyHJ$H5D%58`kI{8hzAAB4um;DHIet8Jx^r1_#!=Z(r8HRjRzW1V5CWMy6QNG-fyN zybWURT_P;@>;^Y6I`@+>%cY#PS7?bXu`574o=WGMQLaK zOH%U9gqmDe;l*SDF~F>wEH3(b3P>%3tI_q1BR6o@?Cl&wzBrBV$L0+A&Y@qbiEUAg zL)TexTe)+tA*gZGe_Zr>$E?asU=5L2fafhKM*7Uo{fJb~+4B|N} zyeC|4G`Fnyk|u=UCMZPiCY7Rm7)Sl@;$L^?I{?jZz4u%0@sj_Fn0`La=ixzEr&r^4 z^z;3@ZI4|C;jc@(dR0KUgN6FNIZgW|;>h@4is2QAi=!Gf3dC!mehN(W6`C~@n$h9$ zAYGyvGEUJ*Dj}W_;K{vNms;Y}q4$D<COQ*RYN#L#iH^g| zux~?8N#m-^Ji3M2ilhyo&YM4d_L@Kq-}|wBTf1&s!MYk$OEt)eS4<82poS?e9Mmw+>;jV(>`Y7z_7 z4ctYq2HC+!;Wq z9*(RzQT0b?aFOmX!=GSRzu~vaYMMwTxdCHOMC*rmni$){lU&ELQC{rQ<(H)zO4=HFbu; zEn@OTcpXi1#h2!gah&uX^{z?~N+qio_VH0Ts%x$hgPt&wc@3wDN$i*Lnb~hj^ZWVF zVoPGz6ojRTY>Y|MV5kz+No2{yTp{^I26B~!Y!yl=0Eo-|j+_f5P4MKh+X`aOv zpc+L@A!v5th`J0=Y)OM(1DS4Cju$+)oDQ@YN2ZQJ65M{g+^EYZ8R~KcfQeKyMMj23 zd<%AwG=ys2d>I7I4)sf5CV0g4^8qoWb^T_R=;(#O!=M(^zd7@Ci&9B6P3Ri?Z_)#Q zs!=6f6xMIMeJqm`Kqh_Q40>|glacrSD#IVTHW84M&{!tngu(|#n#l598G1&izOs(mP`di_aa|MmI`3xPZsMvj1qP)NX(bF<)7}X8tn3F?g&E02cQ^!@ zZqA@-DaM(HS?#UftR?VRHv{%?wC@Y)pm@3#)|2LjP}}tR{3I0*J#q{HvLG_(!Mm3w zy-Nov8LKFslZ;+{C}yz69J2K1%U0%FB9K<7#@LV$JidGqUq}7SKqH>4bs)pZ@+qtF z=*Q5HH){-EgxIp)Te;_7x@Py(#7i5~6f2Zw&nf)gGsga_ch*?jy<%g=f@~eEJR9&N ztd`^u_QkbIm7=*BXpg?j8=2b>09Ltyo73%?=$C*sR?!#nTYHughVx6RLiXROa2yMM6Z^tQJ;mgK5KPkYjG zJy2%I8q~c1F6_^^^~WAp+%U6p_#fK0_!R$2(Ix4-ZBOdy7VrlCQf}cJ=G0HgP+5@6 zR&H3n8|OHC7%cpkxDX1j-kxWA>`;BzX?*t(x8%Dr0On0Zl_4m|l-+#1vcflyh(}C0 zn>yD0R`N#pm2BnLeO%4^*4Z3hb{w20k?7o|y&{(flCE992dLIC%%uV`Dqn8IprLUo zIOyk-ww>Ci(&A{(Qzn;C6c`xTeEa)om;;Uovkea;TzHdm zBNJS7)|_?mMAIzLan5F1`-WwFAh3&~SZ73kXV$=^@p;9se_;%}QAS0cl{}-n4DN-u z%eyA$wcVFbGyMLsKvD1DUe&bR&Tk=F6(_tE(yqNblhZhS4&xng?)@@%IE^9qxt>dx zS=Sq)S&r?KYIfbOT&TQac?XY@8qSba20c5>1D$6sh{;mkz@{W0qv(BNvmlJo>uF?d zIw#b9E(Y@;nH<@azhFa*f%o@An&Qu-cay`Yl}3_5k0_slQg+1Pv%kUh(EoMW53=xw zH2ATyVi^q`-Dh>3`wV^(DrweJI>aSlPH(IuTcF`!Wf>J%<3$$hXrxI*UlQ5DfT_fd zS~_BGWJb5Jg$)u%LeJ?ZeDD=bF7BxUQlDO|vzF!+>osCdmt^BM*06BcIKy!Ntp)B7 z3Lzi`=j$ib*p8E;>~B6%?n|)^wXkGiKvd(+Av2l`6na&tSy&>+;6=ss@@#T#8j>X* zG$8-8jH&VtZOsDHo5zI-&K#s8CM5eQ?%1HC(3%(aPHrHkY~%D>Dk({cnqgi030g*c z*aYj_W6+5(V@8q}Dy9BX)3uV4M9H9U@lqzFTTh7(4rcmNA0M^}DiR31@-5|~doz#? zVNN2F_wse@UG#QJ<98nuzi;cb8a-H;mEAXVa_f9_-22YDy?MCxbbq!lV3>;Kxwg|C zn$HY228id?9tJY|ZBoH|!9J)e++drZcVVe$!zNRmr7>5vp^{ay93}B9pPk}g8)!@` zMbXBgW4j6sam;=f3I*vqQLgJ-781I3+0^qOoU^Ht>r{CAZMMBHJ7>KGoqX&gppJTR z=EM1`XjY3=p^KT|CT7qAQaF?V>Z6C_KyMKw7$L23bV#;y_!Z%kk?K=5_&Dd!imkM> zY;yKyN_B7rD%AxzmM~wKstt{iGsa?0c=Lu$lljb{U|>sNefcq+`_+(y=t094jF_&t z2aW1)!znoEnO_1rfl@|ci+>y7&nk*)&DWt@WVz>AXLT*`1-3yDW50?<7_cnx^@9hH zWi_3qW$F(Z(a*r)3UXtPrwxp8iBD;UBG;gTkMIlBki80^z<*^+v8!BF>KCW@-1Jsn zsxU-r_G9265!(Q0$EBanR4TYh@!cf*@Cm2lF^FQJ?M z{neKDL~sH~-Jk%h%QCnvYh6~GOMv>TbgLHQHM<(B#S~X90*{7Pt=Ctv;J2WwJ)@z| zu)A3DF0NB3HxCne7?}k~ozow88pf*; zrh8(q`VBU%jmFtEwdqVCtocd*QYS*If&*!d zT7fuAN^>DA_)PAiMZ7E~acS0)nzrmW1Qje~jwPf@bbwEbO1yFa0&UHX{kG9!iix*l zA23@`!Un^*Q@y+kmbGo0=>wm4$NsLg0pD))aZ?Kp4&a0-qt$T4llfrTNTR(9>DNKj zCJ*ogt$k{W{Ihd`$YNL!SK2JGj{S{P&yb*vj#1JB(vN8cQ#67M>|6C%l~$iXf>Wy# z2yh>$zw$3!6S~1J*BvoJ_AaC3Anq~Qy~vp3ysTi$*u;9~&XRr1T(~!UW3vEmA30aZ zN|aSQKdJM=z>sCd&Sut3@}=kOb~9Jf6X3OqlH|HPDR1&;pUR@_oYrgC2b3yppr7J! zJ|IxP9kX6OY9=R0?*sGqu5#x;)7F*8pxGkYknHF@{Cndp^ap!O8 z9-b0rm2<}@=-BWFrvM`sD_sq8Oz2Zyy};iGb-|m8b}#UkY7Gp;6@%RSE;nU!G__v4 z$3Zsi)%vZX_g0rEeI9KmSDiYCo2su2(Z}NK4bCJm`;KDQ-FK(3qm%&HNx~hxV(Nfw2g0GVm%69bgS`@YC;GqFxI}(-%f9O8C-vd>%2~< zD=aerp^Verr#yunp}J2x)|9!cw-tu%$M{>rIex-?rZ^oG+e_I79; z<_-0?Q);J|sR13*OnRqMsUFux&UDxwhD&Zh+L>Saps`oUGCd-9X)wcgj+i>=VuP#F zM*mnxSKmorPnL?_Y%G@Yrm=Zv8W}r9u2@hUuV(>4qjGGAiFWvef?Lh+UMBZ1VL9J+ zj;IjjNb_o6Kl97k+4aI3TGA}|umz376QcNazg+~JPqbXj%vt^|{#-beF?}OO)FrTe zu?l0m0{SZCJT;-i0RL>VjJz+9CM~PYQ)g!m36xLsrEm8eGvkdJc;sd@*BseTT5{i^ z$L~diuf4Kt0mW?Wi|cKFc*ee*zO6xv9ITp{Wmb68$s8i7-D&vvf&VGxEQ8|k)isW5 zad&rHtgyH)?ykk%DN@|s3Y6j$r)9AgD5bc&yR#H6zPRn>{Lh)W=kvXpNuIounKv`} zkVz(ae$VgW-|LOmhKTK@J9AU4(wUw~P0}{nGAV9SuB zSg0l2S?J@X7N@E&DPB82UkVAE(DHiUArTACiaj5|P@;8EK$Eu-H}T8iCFH2#wAF?_ z?tPTfoL;y7y$I)7$F$TdTc64#+zo%0v5EW1Gq;8ej#znhA9bs5Tk3440~@;aqMI*I zA)nP9F^_$QsW$ACD2<;gSr+S<%XjxhhLwl$hOX*(@Q)uK%1cBDA>JghuluOnR_*i2^e}<*Hw(EQ9Y4!T`f_GfZK^;FuUj%cZ~!>^QnB3b zi{)A9Yw|Cl3kz};?#!pcYsNU5g0rZJ#=fM)Z0g+C^)WT~ujl3i#a+d=&k{gcKK6}z zJRR=fdM>OCQ<@1&qQD|1$G56ZOJVoS{e#cuiAF>3-GiPgXe5MRU3L%~_ut(PLLb!F zVcnz5@{UDBk_z!bbj>b+)egS-;urcn94jMLC{D*7s{n1AG zI9+-5=1Q5|8oENB;n*n})|C+zBXI}M7YuKCUWXqW3?fOs)h=vn?QtU%_22vLogY+H z+V?9XFN>QJkl2m7R~A*RljU~4=M4H44yd#L*;rvoewo(BAV&eVsUa8gny3K-lxR-PjwR@yHk{%K!rM;-Bnt!fN9f3ju)Z!`zIkNdj=OA>Mj5T_jm5N3 zE-;JcF?LG*&@iRkqfO9E>leO4K4f?M%Pb*207r~9ul_ek97}_LxSrmFsV;s&%E{L# z!_y(9qM`I7eN8Lyr$4tyTOyLl6)l}Zse#z2F*(&h zjNGRYq+DT#V9TV{-b*BvbYxL1txm=*r;-c4w0!QP1J?@rd7)2m__RB^a7J6UWawKS z(=7(9J#i3t$T6ldn7LxtwtiZl0iF>QW{9az7KZ}nV-@_pl}{rsRv(q3QyS9_$YIBt zlOiV^RP;I(79>T!L)_5?wqmJxvf^-8U&K+g*yyy|J67zS!pmq@u&z=yy3!G4Ie{{G zO+1PQneq;HOc@{i8F9vG`mj~?6U2iTuzcH>CodvC`o?-#e5#f%^KRK&`4Wdtx|KG) z^37A|k}rvjVpb$FG7CEn%{{U>5+}CGgC;gouGo)(*;eS}>&ZYfwIL&jroYr^I<{$2 zR$);6B9j%HI3`lnC>yes6Bp^uhmDRQZat;TfZcfFaj^!XOd#}sDm9H)VcZ?fb+v|{ zkmJ<%7DNJHuizTEe$!qmh#g6vk5s`2ur=qD6}SWw^LIot+Ig6$u^J;YRGWV#$iIQF z?(|YN%byYftV|GR5L3jdoA{)*zxbUS!<(~2FNUYeu$vs@T6!|H5pS||<>^GBWDjoD z0BD`D{8MpG4O12L-8Xp6f2@i%F&a~GMD0}&TWQo%^vVn;kNOy11B)ed!#6fgb#C&A#5*poy>lc~-zB2G<8& zwWCYv4|xUC$UGbbf?vMlX|MbK8S+0q3&nDGq1-swd^M3o*|u5Zs)haZ|AQ8J^Q^!u zYl0+~1%s)tR)y6s41S;o|2fASK#D^vaYHd=(;#natOX2Vd0CJ0`aE0ohvoSQ zH5c=fWf)0iD$hlIvv+m)4o2tvNlic}cF((Y=~K15v(E0*GKAI>>7jR}aHVjrWkG=9 z@pa;bTp>ypVh|QVnwm1De`c;v2f>=jCDBz3BeeM4bnZZ3p03?EX?8FghL7Sz%tH3= z$DLxp&u)vic_+RS2LgFd0LjiVD09ZLE%Ce8=kc5|73$!4gNEF=#7zX2T*yt9|8OBk8{ZV~r8n6v=n=-$ zrKMUmFkEX|+OfFeN*~5r=M4V{u=ZNg0`4RYZglI#VUW`1Lrs$OH}RPYLt_UJNQo#e zUt~=={JgN#Sd*N~lf+pIz;WoS?s;&kr=r*% znNe_*sVfQcP;eY^l>u0Ir8y9t`0e|fuD>0|HgmE`++g4HFZ)XZgF0UrDPFvZ-`)0$ z@SFdJ6bz2poIJOlggkGvU2{|}IJ@N@$O?-k>v4iFQC2}=^JJt@#d(_dHxUla!uf7E z)%v=5TWGw>Z-1-orI^I_F6Jsw*5NC(TTK!f90Nn>QYbXuP1F9Ex;;b?=P~=c%(K`k zFcmAz-l#c=)C!->(mHKR2 zv#7MR$(ZIca?5@6Q*VWB`g&(EI~01{a&yWp?tkPTJe#2TqV=_xrd@D*L#V60q0)}Z zubG^}a8_w*!^NnrUDcgu=j0PxOXMMNdr$mn_|*V@3UPOBx%ay+x@0+9AdvuwaERUn zaraRKH@@(WePSQze*>OuNwqpH{du!p6PdwlfXPP3Zhh^*07rr2wl+p1>;>z79M&MO zg4OM}wO$;!-*v)pgo{^yU`?V^#4-d^3X3gw!V{*le?`_K9*|!4J}#p8DJ8o15f_?oMOeZ}YI%l0E8*E3 zWYSNcYS^8(X5car(o-WcSuO4}0NB|trwbXi|amBv>VA2*;3AZr}OUXeHn?@4u+Q!MJ+EtR3jdy0JL1bT+yzsn*COOXM+PDWWg3dxhwzl#8-bq~l5%EHH)S&q+t=|c=`^Nl{@BzA z&Sg`YoN5jTAuoGw4U4c>nMa z=DmWx_r`anr^pW_B6z3R7W$I2431~}AC37PTG3;cIG%nwUSUJsaN1?8KUj+&<(vsc ze&8}^f3%yU){37Xm`@m;k@%q^X!*`QX*Bz*om+$Uz6B0Js@KWakz+OTzXl)Atpq3h z-TiMe7p>l!JZexxOo77mG1uL&j?Pfs&%vofGGkq(+EAUd%_q|7l@d}VY`2iAI{~cJrZl@d zs7dWr*~n=J>q#<|0O1R&1EK*s6eXAhCPS<4Z#?`FFuJQS;y@YX2?sI4;NQz zYf|Bve}I|6X1nX-2NRpp9cYT%EkneuhKz zQ1+$=mfY~I>v85@o46}^-TuV&BI#9)#EWd%_xSzN+}pv!^LYj=!BJ@{l*&sgc`^Z^ z2UsVJy`qOPyoPHx4>z+kFc(kX&&&DZ2jf6RW{wpG`2N*7mj;{bB2h1M7r#Nta-_a0 zQk~Q5$1^>vdNNJ+iY|2V6XnJlE~loX@pohQSV{dW!+jHNT1F8F3In`ta=;Q(q&_LwACzAfPqJiG@2W&^Y`WK}cPvOyD~TDGsGFfA@3k!wTB3Z+o`y$>nWk%++)2Uk zDbdY76vRWs07e%jB%s$nT5zjHiwhIoRCq4w!GwJ|pAjF+&!SLUf=da8}6Bk6_O zkWg%^K$_8Y0HPq8dFnNod z*Zg&x3#4hE;7>8D#+i+8iTd{A z=p+XQ9)4N(=mqLI`%NQ(-+=B1k?9SboQlmg#uEj}W-}C`8*2M^!sN8b8@ke_8W}}? z`kzWp1C4U%VeIe0p5bLO=`jh+x1Z20sgR+g(N(AdQnDF>B2g^j-|={4+;8uY{(s71T^wyes?>V3>V8ePc|U z_=&}dxX6e-Rn(HfJXb=2>eEuxXe>_hy1j3!ymFdhBPh+|glza*CvuH?c{pn_nYXnZ zeBl=iJc$fcgTb9N<}fIQPYL8g32G}~xFiYgf8JV>g{VN#O>y@|b_Md1os@DB`L$KS z38D)YcH2l6L=E`fFBWvAag$mX_ZPg=vZT;aLu&}2ixU-V%u*hnmq4{U z7Y#)v9gbD?PxYS;{<<7A6mN4);f`OJWw!*rZG~bspD%7*F z4i{U3CXjxp!nTy2aNhMyj+~yJuFnP5n{FD^*|(#FRMMWt2*yJFgW2KYmDu>6zL+{g zD-f@=?MZ|5vhxyXB-nKt7FH#}xkV~##05GiV zcb-iz3HQZMxd|GPYrCD8QJQw;_vla2YcRyL%J`~(n24{;L<<{_ITIpYrozoVj!3al zlrLz#zYL3wNuM{5V3Z5L!T3_#sE7oLgmB7In4|yUEPlG%L}0FYF|%tQg(H-Phr-8; zqNu!%t#yCt{vI9XA4HzFS*OLJEH!lFN76s{-lE6&637et?R=p5#QoMvl zWJ6*6J0va3K~kL9TF_8bq|zm<-tSWR$a)+pQ@ymv3-V0D(lx9IOAwLyE%FFYe+ji+2x?|9!n`_&s;WRV+y$O?JPEP) zX*lAKJFWy`ADLnhlY?;A-M!Q;bqwU*um_n?C^f8+BCQ!=MkWqmH75)GL4un|f4Cc# zz#{WJi9uv9-}8o3f%XOv)(xY0^YSL^4NKUe0u}2(6awBBO16zOKAyc4GMfbfGA$V9 ztx2c257U52!tb)fTT;~q{%gG~rXqR-Vwmn|OW{jVt+96K2dtC!NnyM>yyF%ky;mtl zvCFadm@0VA7!)*l_<5MC48AlsSjRlV6&~as%pU675Qx|I(N@49)qr^XBXTO@B(phi z17kxl=xvZvka*DTojdv+`g?R!fKklYYw`UeJQ z+TR)}3bnGQpV|_i#O{MHaR?0w1qe+Ey$Bx&C0OlPskOZ{MJh~7+d%S)wh0XZXOyQTphU0wpWr= zE|%XaZ4OCwSrinfTSjk_F))`34rmRSG1D`9tG?tgXP*KH0GRwH_7hgrwjEUQ(Gwrqo_NXf`mI5AsDBq zC;DOxKrc-^uw-`{RQS%y5w^cCXqi z%)CWAjJ#KuqA+oSO}k^FnOgzpT_5Er(aRL|PRW5cy81~bF&s^Pm0KyTkGF~jv+a}}Ev`Bg$j z^>Isl5+(3PJpPHs9eA&zc7t*$m~(Q@5eQz@*L%FeaDthrM(gPt{W|xJ6<;%jJnp&cRD?R|2?i1l;otJa7c=&IR|cfO}iPgAXoU zF)n=rEJ;yXtU+y_2o$M z<;3>o*x=>VXJ8m2FfI}pB@0aI1x7Fc6H0+G*1(hO#Xh^FK7+#3T;kC{(Tgt0ilE5vE{Wbju{JNMHlc`;mjsef%+5=SPAF<ZZjR&nzhtKRioIRA?tjIp-MDh$tB+H`e*{!{VV-PWx_BTM z@E@r$uU$lnG z!53>-18gbu^eF|AZPf_W!@UFwWzSx>*{LQW!N1fq9mn z2@b9W9u{2>pA4r`kEUtZ01uyH)Br-^Fr=%;HBzZ3)PC)R8Bx`vaF`kz)f003iw~ + + + + Global | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Global

      + + + + +
      + +
      +

      + +

      + + +
      + +
      +
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + + + + + + + + + + +

      Members

      + +
      + + +
      +
      +

      _setMoveStyle

      +
      + +
      +
      + +
      +

      Set CSS style values to move elements

      +

      Initialize setting up checking if browser support transform css property. +If browser doesn't support transform, then use left/top properties instead.

      +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + +
      + + + +

      Methods

      + +
      + +
      +
      +

      + + * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}() +

      + + + + +
      + + +
      +
      + + +
      +

      Apply css prefix cssHooks

      +
      + + +
      +

      자동으로 css prefix가 적용되지 않는 jQuery 1.4.3 ~ 1.8.x에서 css prefix을 자동으로 등록하는 cssHooks이다.

      +
      + + + + + + + + + + + + + + + + + + + +
      Example
      + + + +

      $("#ID").css("transform", "translate('10px', '10px'); +$("#ID").css("Transform", "translate('10px', '10px'); +$("#ID").css("webkitTransform", "translate('10px', '10px'); +$("#ID").css("transform"); +$("#ID").css("webkitTransform");

      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _addClonePanels(){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      To fulfill minimum panel count cloning original node when circular or previewPadding option are set

      +
      + + + + + + + + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + +
      true : added clone node, false : not added
      +
      true : added clone node, false : not added
      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _adjustContainerCss(phase, coords) +

      + + + + +
      + + +
      +
      + + +
      +

      Adjust container's css value to handle Android 2.x link highlighting bug

      +
      + + + + + + + + + + +
        + +
      • + +
        + phase + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        start - set left/top value to 0 + end - set translate value to 0

        +

        start - set left/top value to 0 + end - set translate value to 0

        + +
        + + + +
      • + +
      • + +
        + coords + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        coordinate value

        +

        coordinate value

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _animationEndHandler() +

      + + + + +
      + + +
      +
      + + +
      +

      'animationEnd' event handler

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _animationStartHandler() +

      + + + + +
      + + +
      +
      + + +
      +

      'animationStart' event handler

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _applyPanelsCss() +

      + + + + +
      + + +
      +
      + + +
      +

      Callback function for applying CSS values to each panels

      +

      Need to be initialized before use, to set up for Android 2.x browsers or others.

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _applyPanelsPos() +

      + + + + +
      + + +
      +
      + + +
      +

      Set each panel's position in DOM

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _arrangePanelPosition(direction, indexToMove) +

      + + + + +
      + + +
      +
      + + +
      +

      Move nodes

      +
      + + + + + + + + + + +
        + +
      • + +
        + direction + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + indexToMove + + + +
        + + +
        Type: +Number + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _arrangePanels(sort, indexToMove) +

      + + + + +
      + + +
      +
      + + +
      +

      Arrange panels' position

      +
      + + + + + + + + + + +
        + +
      • + +
        + sort + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +

        Need to sort panel's position

        +

        Need to sort panel's position

        + +
        + + + +
      • + +
      • + +
        + indexToMove + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        Number to move from current position (negative: left, positive: right)

        +

        Number to move from current position (negative: left, positive: right)

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _bindEvents(bind) +

      + + + + +
      + + +
      +
      + + +
      +

      Bind events

      +
      + + + + + + + + + + +
        + +
      • + +
        + bind + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _build() +

      + + + + +
      + + +
      +
      + + +
      +

      Build and set panel nodes to make flicking structure

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _changeHandler() +

      + + + + +
      + + +
      +
      + + +
      +

      'change' event handler

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _checkPadding() +

      + + + + +
      + + +
      +
      + + +
      +

      Update panel's previewPadding size according options.previewPadding

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _getBasePositionIndex() +

      + + + + +
      + + +
      +
      + + +
      +

      Get the base position index of the panel

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _getCoordsValue(coords){Object} +

      + + + + +
      + + +
      +
      + + +
      +

      Get coordinate value with unit

      +
      + + + + + + + + + + +
        + +
      • + +
        + coords + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        x,y numeric value

        +

        x,y numeric value

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Object + + + + +
      x,y coordinate value with unit
      +
      x,y coordinate value with unit
      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _getDataByDirection(value){Array} +

      + + + + +
      + + +
      +
      + + +
      +

      Get data according options.horizontal value

      +
      + + + + + + + + + + +
        + +
      • + +
        + value + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        primary data to handle

        +

        primary data to handle

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Array + + + + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _getElement(direction, element, physical){jQuery|Number} +

      + + + + +
      + + +
      +
      + + +
      +

      Get next/prev panel element/index.

      +
      + + + + + + + + + + +
        + +
      • + +
        + direction + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + element + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +

        true:to get element, false:to get index

        +

        true:to get element, false:to get index

        + +
        + + + +
      • + +
      • + +
        + physical + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        true : physical, false : logical

        +

        true : physical, false : logical

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + jQuery + | + + Number + + + + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _getNumByDirection() +

      + + + + +
      + + +
      +
      + + +
      +

      Get positive or negative according direction

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _getNumValue(val, defVal){Number} +

      + + + + +
      + + +
      +
      + + +
      +

      Check and parse value to number

      +
      + + + + + + + + + + +
        + +
      • + +
        + val + + + +
        + + +
        Type: +Number +| + +String + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + defVal + + + +
        + + +
        Type: +Number + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Number + + + + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _getUnitValue(val){String} +

      + + + + +
      + + +
      +
      + + +
      +

      Return unit formatted value

      +
      + + + + + + + + + + +
        + +
      • + +
        + val + + + +
        + + +
        Type: +Number +| + +String + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + String + + + + +
      val Value formatted with unit
      +
      val Value formatted with unit
      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _holdHandler() +

      + + + + +
      + + +
      +
      + + +
      +

      'hold' event handler

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _isMovable() +

      + + + + +
      + + +
      +
      + + +
      +

      Check if panel passed through threshold pixel

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _movePanel(next, duration) +

      + + + + +
      + + +
      +
      + + +
      +

      Move panel to the given direction

      +
      + + + + + + + + + + +
        + +
      • + +
        + next + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + duration + + + +
        + + +
        Type: +Number + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _movePanelByPhase(method, coords, duration) +

      + + + + +
      + + +
      +
      + + +
      +

      Move panel applying start/end phase value

      +
      + + + + + + + + + + +
        + +
      • + +
        + method + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        movableCoord method name

        +

        movableCoord method name

        + +
        + + + +
      • + +
      • + +
        + coords + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        coordinate array value

        +

        coordinate array value

        + +
        + + + +
      • + +
      • + +
        + duration + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        duration value

        +

        duration value

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _movePanelPosition(count, append) +

      + + + + +
      + + +
      +
      + + +
      +

      Move panel's position within array

      +
      + + + + + + + + + + +
        + +
      • + +
        + count + + + +
        + + +
        Type: +Number + +
        + + + +
        + +

        element counts to move

        +

        element counts to move

        + +
        + + + +
      • + +
      • + +
        + append + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +

        where the list to be appended(moved) (true: to the end, false: to the beginning)

        +

        where the list to be appended(moved) (true: to the end, false: to the beginning)

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _releaseHandler() +

      + + + + +
      + + +
      +
      + + +
      +

      'release' event handler

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _revertPanelNo() +

      + + + + +
      + + +
      +
      + + +
      +

      Revert panel number

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setConfig($children, _prefix) +

      + + + + +
      + + +
      +
      + + +
      +

      Set config values

      +
      + + + + + + + + + + +
        + +
      • + +
        + $children + + + +
        + + +
        Type: +jQuery + +
        + + + +
        + +

        wrappers' children elements

        +

        wrappers' children elements

        + +
        + + + +
      • + +
      • + +
        + _prefix + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        event prefix

        +

        event prefix

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setDefaultPanel(index) +

      + + + + +
      + + +
      +
      + + +
      +

      Set default panel to show

      +
      + + + + + + + + + + +
        + +
      • + +
        + index + + + +
        + + +
        Type: +Number + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setHint() +

      + + + + +
      + + +
      +
      + + +
      +

      Set hint for browser to decide efficient way of doing transform changes(or animation) +https://dev.opera.com/articles/css-will-change-property/

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setInputEvent(bind){eg.Flicking} +

      + + + + +
      + + +
      +
      + + +
      +

      Set input event biding

      +
      + + + + + + + + + + +
        + +
      • + +
        + bind + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +

        true: bind, false: unbind

        +

        true: bind, false: unbind

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.Flicking + + + + +
      instance of itself
      +
      instance of itself
      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setMovableCoord(method, coord, isDirVal, duration){eg.MovableCoord} +

      + + + + +
      + + +
      +
      + + +
      +

      Set MovableCoord coord value

      +
      + + + + + + + + + + +
        + +
      • + +
        + method + + + +
        + + +
        Type: +String + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + coord + + + +
        + + +
        Type: +Array + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + isDirVal + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + duration + + + +
        + + +
        Type: +Number + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + eg.MovableCoord + + + + +
      MovableCoord instance
      +
      MovableCoord instance
      + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setOptions(options) +

      + + + + +
      + + +
      +
      + + +
      +

      Set options values

      +
      + + + + + + + + + + +
        + +
      • + +
        + options + + + +
        + + +
        Type: +Object + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setPadding(padding, build) +

      + + + + +
      + + +
      +
      + + +
      +

      Set preview padding value

      +
      + + + + + + + + + + +
        + +
      • + +
        + padding + + + +
        + + +
        Type: +Array + +
        + + + +
        + +
        + + + +
      • + +
      • + +
        + build + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setPanelNo(obj) +

      + + + + +
      + + +
      +
      + + +
      +

      Set the panel number

      +
      + + + + + + + + + + +
        + +
      • + +
        + obj + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        number object

        +

        number object

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setPhaseValue(phase, pos) +

      + + + + +
      + + +
      +
      + + +
      +

      Set value when panel changes

      +
      + + + + + + + + + + +
        + +
      • + +
        + phase + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        [start|end]

        +

        [start|end]

        + +
        + + + +
      • + +
      • + +
        + pos + + + +
        + + +
        Type: +Object + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setPointerEvents(e) +

      + + + + +
      + + +
      +
      + + +
      +

      Set pointerEvents css property on container element due to the iOS click bug

      +
      + + + + + + + + + + +
        + +
      • + +
        + e + + + +
        + + +
        Type: +Event + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setTranslate(coords) +

      + + + + +
      + + +
      +
      + + +
      +

      Set translate property value

      +
      + + + + + + + + + + +
        + +
      • + +
        + coords + + + +
        + + +
        Type: +Array + +
        + + + +
        + +

        coordinate x,y value

        +

        coordinate x,y value

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _setValueToMove(next) +

      + + + + +
      + + +
      +
      + + +
      +

      Set value to force move panels when duration is 0

      +
      + + + + + + + + + + +
        + +
      • + +
        + next + + + +
        + + +
        Type: +Boolean + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _triggerBeforeRestore(e) +

      + + + + +
      + + +
      +
      + + +
      +

      Trigger beforeRestore event

      +
      + + + + + + + + + + +
        + +
      • + +
        + e + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        event object

        +

        event object

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _triggerEvent(name, param){Boolean} +

      + + + + +
      + + +
      +
      + + +
      +

      Trigger custom events

      +
      + + + + + + + + + + +
        + +
      • + +
        + name + + + +
        + + +
        Type: +String + +
        + + + +
        + +

        event name

        +

        event name

        + +
        + + + +
      • + +
      • + +
        + param + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        additional event value

        +

        additional event value

        + +
        + + + +
      • + +
      + + + + + + + + + + + +
      Returns:
      + + + + + + + + + + + + + + + + + + + + +
      TypeDescription
      + + Boolean + + + + + + +
      + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + _triggerRestore() +

      + + + + +
      + + +
      +
      + + +
      +

      Trigger restore event

      +
      + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +

      + + construct(element, options) +

      + + + + +
      + + +
      +
      + + +
      +

      Constructor

      +
      + + + + + + + + + + +
        + +
      • + +
        + element + + + +
        + + +
        Type: +HTMLElement +| + +String +| + +jQuery + +
        + + + +
        + +

        base element

        +

        base element

        + +
        + + + +
      • + +
      • + +
        + options + + + +
        + + +
        Type: +Object + +
        + + + +
        + +
        + + + +
      • + +
      + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      + + + + + + + +
      + +
      + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:17 GMT+0900 (KST) +
      +
      +
      + + + + + \ No newline at end of file diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 00000000..d91aedb5 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,806 @@ + + + + + Index | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Index

      + + + + + + +

      + + + + + + + + + + + + + +
      +

      egjs

      +

      Build Status Test coverage

      +

      egjs is a jQuery-based JavaScript library consisting of UI interactions, effects, and utilities, which brings easiest and fastest way to build a web application in your way.

      + +

      Components

      +

      The following is a list of egjs components.

      + +

      jQuery Extensions

      +

      egjs provides methods and events extended from jQuery.

      +

      Methods

      +

      The following is a list of methods extended from jQuery.

      +
        +
      • persist() method: Stores the current state of a webpage into a key in JSON. +
      • +
      • prefixCss() method: Enables to add CSS vendor prefixes when you use jQuery that does not support them.
      • +
      • animate() method: A method extended from the jQuery animate() method. It supports CSS transform property and 3D acceleration. +
      • +
      • pause() and resume() methods: Pauses and resumes animation executed by the jQuery animate() method. +
      • +
      +

      Events

      +

      The following is a list of events extended from jQuery.

      + +

      Downloads and Installation

      +

      In order to use egjs, you should download the JavaScript files or install it using Bower or npm.

      +

      For development (Uncompressed)

      +

      You can download the uncompressed files for development version from the following locations:

      + +

      For production (Compressed)

      +

      You can download the compressed files for production version from the following locations: + Latest: http://naver.github.io/egjs/latest/dist/eg.min.js + Specific version: http://naver.github.io/egjs/[VERSION]/dist/eg.min.js

      +

      Using CDN

      +

      To create a link to a file provided over CDN, you must check the file URL in the CDN service.

      + +

      Installation with Bower

      +

      If you do not have Bower installed, install it using npm as follows:

      +
      $ npm install bower -g
      +

      The following code shows how to install egjs using Bower.

      +
      $ bower install egjs
      +

      Installation with npm

      +

      The following code shows how to install egjs using npm.

      +
      $ npm install egjs
      +

      Supported Browsers

      +

      The following table shows browsers supported by egjs.

      + + + + + + + + + + + + + + + + + + + + + +
      Internet ExplorerChromeFirefoxSafariiOSAndroid
      7+LatestLatestLatest7+2.3+(except 3.x)
      +
      +

      Supported browser types and versions may vary depending on modules. For more information, see API documentation.

      +
      +

      Dependency

      +

      egjs has the dependencies for the following libraries:

      + + + + + + + + + + + + + +
      jQuery (required)Hammer.JS
      1.7.0+2.0.4+
      +
      +

      Except jQuery, library dependencies may vary depending on modules. For more information, see API documentation.

      +
      +

      How to Use

      +

      Let egjs load after jQuery loads.

      +
      ...
      +<!-- Load jQuery -->
      +<script src="bower_components/jquery/jquery.js"></script>
      +
      +<!-- Load egjs packaged with all dependencies (Hammer.js) -->
      +<!-- Load from your local installation -->
      +<script src="bower_components/egjs/dist/pkgd/eg.pkgd.min.js"></script>
      +
      +<!-- Or load from CDN -->
      +<script src="https://cdnjs.cloudflare.com/ajax/libs/egjs/1.3.0/pkgd/eg.pkgd.min.js"></script>
      +...
      +
      +

      Note
      For more information on loading dependency files except jQuery, see the "Download and Using egjs" page on GitHub Wikis.

      +
      +

      You need to add the namespace, "eg", to use the egjs components as shown in the example below.

      +
      var Klass = eg.Class({
      +    "construct" : function(){}
      +});
      +var Komponent = eg.Class.extend(eg.Component,{
      +    "construct" : function(){}
      +});
      +

      egjs Development

      +

      For anyone interested to develop egjs, follow the instructions below.

      +

      Development Environment

      +

      1. Install grunt-cli and Bower

      +

      Install grunt-cli and Bower globally.

      +
      $ npm install grunt-cli -g  # Install grunt-cli
      +$ npm install bower -g  # Install Bower
      +

      2. Clone the repository and install dependencies

      +

      Clone the egjs depository and install the Bower and npm dependency modules.

      +
      # Create and move a folder.
      +$ mkdir egjs && cd egjs
      +
      +# Clone a repository.
      +$ git clone https://github.com/naver/egjs.git
      +
      +# Install the Bower dependency module.
      +$ bower install
      +
      +# Install the node dependency module.
      +$ npm install
      +

      3. Build

      +

      Use Grunt to build egjs.

      +
      $ grunt build
      +

      Two folders will be created after complete build is completed.

      +
        +
      • dist folder: Includes the eg.js and eg.min.js files.
      • +
      • doc folder: Includes API documentation. The home page for the documentation is doc/index.html.
      • +
      +

      Test

      +

      Once you create a branch and done with development, you must perform a test using the "grunt test" command before you push code to a remote repository.

      +
      $ grunt test
      +

      Running a "grunt test" command will start JShint, JSCS, QUnit, and istanbul. + JShint and JSCS: Performs static checking and code style checking. + QUnit: Performs unit tests of egjs. + istanbul: Measures test coverage. The test results can be verified once the Grunt task is completed. Or you can use the *./report/index.html file to verify them.

      +

      Bug Report

      +

      If you find a bug, please report it to us using the Issues page on GitHub.

      +

      License

      +

      egjs is released under the MIT license.

      +
      Copyright (c) 2015 NAVER Corp.
      +
      +Permission is hereby granted, free of charge, to any person obtaining a copy
      +of this software and associated documentation files (the "Software"), to deal
      +in the Software without restriction, including without limitation the rights
      +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      +copies of the Software, and to permit persons to whom the Software is
      +furnished to do so, subject to the following conditions:
      +
      +The above copyright notice and this permission notice shall be included in
      +all copies or substantial portions of the Software.
      +
      +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
      +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      +THE SOFTWARE.
      +

      Analytics

      +
      + + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:17 GMT+0900 (KST) +
      +
      +
      + + + + + \ No newline at end of file diff --git a/doc/infiniteGrid.js.html b/doc/infiniteGrid.js.html new file mode 100644 index 00000000..549a88d3 --- /dev/null +++ b/doc/infiniteGrid.js.html @@ -0,0 +1,1429 @@ + + + + + Source: infiniteGrid.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Source: infiniteGrid.js

      + + + + +
      +
      +
      /**
      +* Copyright (c) 2015 NAVER Corp.
      +* egjs projects are licensed under the MIT license
      +*/
      +
      +// jscs:disable validateLineBreaks, maximumLineLength
      +eg.module("infiniteGrid", ["jQuery", eg, window, document], function($, ns, global, doc) {
      +	"use strict";
      +
      +	/**
      +	 * A module used to arrange card elements including content infinitely on a grid layout. With this module, you can implement a grid-pattern user interface composed of different card elements whose sizes vary. It guarantees performance by maintaining the number of DOMs the module is handling under any circumstance
      +	 * @group egjs
      +	 * @ko 콘텐츠가 있는 카드 엘리먼트를 그리드 레이아웃에 무한으로 배치하는 모듈. 다양한 크기의 카드 엘리먼트를 격자 모양으로 배치하는 UI를 만들 수 있다. 카드 엘리먼트의 개수가 계속 늘어나도 모듈이 처리하는 DOM의 개수를 일정하게 유지해 최적의 성능을 보장한다
      +	 * @class
      +	 * @name eg.InfiniteGrid
      +	 * @extends eg.Component
      +	 *
      +	 * @param {HTMLElement|String|jQuery} element A base element for a module <ko>모듈을 적용할 기준 엘리먼트</ko>
      +	 * @param {Object} [options] The option object of the eg.InfiniteGrid module <ko>eg.InfiniteGrid 모듈의 옵션 객체</ko>
      +	 * @param {String} [options.itemSelector] A selector to select card elements that make up the layout (@deprecated since 1.3.0)<ko>레이아웃을 구성하는 카드 엘리먼트를 선택할 선택자(selector) (@deprecated since 1.3.0)</ko>
      +	 * @param {Number} [options.count=30] The number of DOMs handled by module. If the count value is greater than zero, the number of DOMs is maintained. If the count value is zero or less than zero, the number of DOMs will increase as card elements are added. <ko>모듈이 유지할 실제 DOM의 개수. count 값이 0보다 크면 DOM 개수를 일정하게 유지한다. count 값이 0 이하면 카드 엘리먼트가 추가될수록 DOM 개수가 계속 증가한다.</ko>
      +	 * @param {String} [options.defaultGroupKey=null] The default group key configured in a card element contained in the markup upon initialization of a module object <ko>모듈 객체를 초기화할 때 마크업에 있는 카드 엘리먼트에 설정할 그룹 키 </ko>
      +	 * @param {Boolean} [options.isEqualSize=false] Indicates whether sizes of all card elements are equal to one another. If sizes of card elements to be arranged are all equal and this option is set to "true", the performance of layout arrangement can be improved. <ko>카드 엘리먼트의 크기가 동일한지 여부. 배치될 카드 엘리먼트의 크기가 모두 동일할 때 이 옵션을 'true'로 설정하면 레이아웃 배치 성능을 높일 수 있다</ko>
      +	 * @param {Number} [options.threshold=300] The threshold size of an event area where card elements are added to a layout.<br>- append event: If the current vertical position of the scroll bar is greater than "the bottom property value of the card element at the top of the layout" plus "the value of the threshold option", the append event will occur.<br>- prepend event: If the current vertical position of the scroll bar is less than "the bottom property value of the card element at the top of the layout" minus "the value of the threshold option", the prepend event will occur. <ko>−	레이아웃에 카드 엘리먼트를 추가하는 이벤트가 발생하는 기준 영역의 크기.<br>- append 이벤트: 현재 스크롤의 y 좌표 값이 '레이아웃의 맨 아래에 있는 카드 엘리먼트의 top 속성의 값 + threshold 옵션의 값'보다 크면 append 이벤트가 발생한다.<br>- prepend 이벤트: 현재 스크롤의 y 좌표 값이 '레이아웃의 맨 위에 있는 카드 엘리먼트의 bottom 속성의 값 - threshold 옵션의 값'보다 작으면 prepend 이벤트가 발생한다</ko>
      +	 *
      +	 * @codepen {"id":"zvrbap", "ko":"InfiniteGrid 데모", "en":"InfiniteGrid example", "collectionId":"DPYEww", "height": 403}
      +	 *  @support {"ie": "8+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
      +	 *
      +	 * @example
      +		<!-- HTML -->
      +		<ul id="grid">
      +			<li class="card">
      +				<div>test1</div>
      +			</li>
      +			<li class="card">
      +				<div>test2</div>
      +			</li>
      +			<li class="card">
      +				<div>test3</div>
      +			</li>
      +			<li class="card">
      +				<div>test4</div>
      +			</li>
      +			<li class="card">
      +				<div>test5</div>
      +			</li>
      +			<li class="card">
      +				<div>test6</div>
      +			</li>
      +		</ul>
      +		<script>
      +		var some = new eg.InfiniteGrid("#grid").on("layoutComplete", function(e) {
      +			// ...
      +		});
      +		</script>
      +	 */
      +	var EVENTS = {
      +		"layoutComplete": "layoutComplete",
      +		"append": "append",
      +		"prepend": "prepend"
      +	};
      +	ns.InfiniteGrid = ns.Class.extend(ns.Component, {
      +		_events: function() {
      +			return EVENTS;
      +		},
      +		construct: function(el, options, _prefix) {
      +			this.options = $.extend({
      +				isEqualSize: false,
      +				defaultGroupKey: null,
      +				count: 30,
      +				threshold: 300
      +			}, options);
      +
      +			// if el is jQuery instance, el should change to HTMLElement.
      +			this.$el = el instanceof $ ? el : $(el);
      +			this.el = this.$el.get(0);
      +			this.el.style.position = "relative";
      +			this._prefix = _prefix || "";
      +			this._isIos = /iPhone|iPad/.test(global.navigator.userAgent);
      +			this._isIE10lower = !!(doc.documentMode && doc.documentMode < 10);
      +			this._appendCols = this._prependCols = [];
      +			this.$view = $(global);
      +			this._reset();
      +			this._refreshViewport();
      +			if (this.el.children.length > 0) {
      +				this.items = this._itemize($.makeArray(this.el.children), this.options.defaultGroupKey, true);
      +				this.layout(this.items, true);
      +			}
      +
      +			this._onScroll = $.proxy(this._onScroll, this);
      +			this._onResize = $.proxy(this._onResize, this);
      +			this.$view.on("scroll", this._onScroll)
      +				.on("resize", this._onResize);
      +		},
      +		_getScrollTop: function() {
      +			return doc.body.scrollTop || doc.documentElement.scrollTop;
      +		},
      +		_onScroll: function() {
      +			if (this.isProcessing()) {
      +				return;
      +			}
      +			var scrollTop = this._getScrollTop();
      +			var prevScrollTop = this._prevScrollTop;
      +
      +			if (this._isIos && scrollTop === 0 || prevScrollTop === scrollTop) {
      +				return;
      +			}
      +			var ele;
      +			var rect;
      +			if (prevScrollTop < scrollTop) {
      +				if ($.isEmptyObject(this._bottomElement)) {
      +					this._bottomElement = this.getBottomElement();
      +					if (this._bottomElement == null) {
      +						return;
      +					}
      +				}
      +				ele = this._bottomElement;
      +				rect = ele.getBoundingClientRect();
      +				if (rect.top <= this._clientHeight + this.options.threshold) {
      +					/**
      +					 * This event is fired when a card element must be added at the bottom of a grid layout because there is no card to be displayed on screen when a user scrolls near bottom.
      +					 * @ko 카드 엘리먼트가 그리드 레이아웃의 아래에 추가돼야 할 때 발생하는 이벤트. 사용자가 아래로 스크롤해서 화면에 표시될 카드가 없을 때 발생한다
      +					 * @name eg.InfiniteGrid#append
      +					 * @event
      +					 *
      +					 * @param {Object} param The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
      +					 * @param {Number} param.scrollTop Current vertical position of the scroll bar<ko>현재 스크롤의 y 좌표 값</ko>
      +					 */
      +					this.trigger(this._prefix + EVENTS.append, {
      +						scrollTop: scrollTop
      +					});
      +				}
      +			} else {
      +				if (this.isRecycling() && this._removedContent > 0) {
      +					if ($.isEmptyObject(this._topElement)) {
      +						this._topElement = this.getTopElement();
      +						if (this._topElement == null) {
      +							return;
      +						}
      +					}
      +					ele = this._topElement;
      +					rect = ele.getBoundingClientRect();
      +					if (rect.bottom >= -this.options.threshold) {
      +						/**
      +						 * This event is fired when a card element must be added at the top of a grid layout because there is no card to be displayed on screen when a user scrolls near top. This event is available only if the isRecycling() method returns true.
      +						 * @ko 카드가 그리드 레이아웃의 위에 추가돼야 할 때 발생하는 이벤트. 사용자가 위로 스크롤해서 화면에 표시될 카드가 없을 때 발생한다. 이 이벤트는 isRecycling() 메서드의 반환값이 'true'일 때만 발생한다
      +						 * @name eg.InfiniteGrid#prepend
      +						 * @event
      +						 *
      +						 * @param {Object} param The object of data to be sent to an event<ko>이벤트에 전달되는 데이터 객체</ko>
      +						 * @param {Number} param.scrollTop Current vertical position of the scroll bar<ko>현재 스크롤의 y 좌표 값</ko>
      +						 */
      +						var croppedDistance = this.fit();
      +						if (croppedDistance > 0) {
      +							scrollTop -= croppedDistance;
      +							this.$view.scrollTop(scrollTop);
      +						}
      +						this.trigger(this._prefix + EVENTS.prepend, {
      +							scrollTop: scrollTop
      +						});
      +					}
      +				}
      +			}
      +			this._prevScrollTop = scrollTop;
      +		},
      +		_onResize: function() {
      +			if (this._resizeTimeout) {
      +				clearTimeout(this._resizeTimeout);
      +			}
      +			var self = this;
      +			this._resizeTimeout = setTimeout(function() {
      +				self._refreshViewport();
      +				(self.$el.innerWidth() !== self._containerWidth) && self.layout(self.items, true);
      +				self._resizeTimeout = null;
      +			}, 100);
      +		},
      +		_refreshViewport: function() {
      +			this._clientHeight = this.$view.height();
      +		},
      +		/**
      +		 * Returns the current state of a module such as location information. You can use the setStatus() method to restore the information returned through a call to this method.
      +		 * @ko 카드의 위치 정보 등 모듈의 현재 상태 정보를 반환한다. 이 메서드가 반환한 정보를 저장해 두었다가 setStatus() 메서드로 복원할 수 있다
      +		 * @method eg.InfiniteGrid#getStatue
      +		 * @return {Object} State object of the eg.InfiniteGrid module<ko>eg.InfiniteGrid 모듈의 상태 객체</ko>
      +		 */
      +		getStatus: function() {
      +			var data = {};
      +			var p;
      +			for (p in this) {
      +				if (this.hasOwnProperty(p) && /^_/.test(p) &&
      +					typeof this[p] !== "function" && !(this[p] instanceof Element)) {
      +					data[p] = this[p];
      +				}
      +			}
      +			return {
      +				prop: data,
      +				options: $.extend({}, this.options),
      +				items: $.map(this.items, function(v) {
      +					var clone = $.extend({}, v);
      +					delete clone.el;
      +					return clone;
      +				}),
      +				html: this.el.innerHTML,
      +				cssText: this.el.style.cssText
      +			};
      +		},
      +		/**
      +		 * Sets the state of the eg.InfiniteGrid module with the information returned through a call to the getStatue() method.
      +		 * @ko getStatue() 메서드가 저장한 정보로 eg.InfiniteGrid 모듈의 상태를 설정한다.
      +		 * @method eg.InfiniteGrid#setStatus
      +		 * @param {Object} status State object of the eg.InfiniteGrid module <ko>eg.InfiniteGrid 모듈의 상태 객체</ko>
      +		 * @return {eg.InfiniteGrid} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		setStatus: function(status) {
      +			if (!status || !status.cssText || !status.html ||
      +				!status.prop || !status.items) {
      +				return this;
      +			}
      +			this.el.style.cssText = status.cssText;
      +			this.el.innerHTML = status.html;
      +			$.extend(this, status.prop);
      +			this._topElement = this._bottomElement = null;
      +			this.items = $.map(this.el.children, function(v, i) {
      +				status.items[i].el = v;
      +				return status.items[i];
      +			});
      +			return this;
      +		},
      +		/**
      +		 * Checks whether a card element is being added.
      +		 * @ko 카드 엘리먼트 추가가 진행 중인지 확인한다
      +		 * @method eg.InfiniteGrid#isProcessing
      +		 * @return {Boolean} Indicates whether a card element is being added <ko>카드 엘리먼트 추가 진행 중 여부</ko>
      +		 */
      +		isProcessing: function() {
      +			return this._isProcessing;
      +		},
      +		/**
      +		 * Checks whether the total number of added card elements is greater than the value of the count option. Note that the value of the count option is always greater than zero. If it returns true, the number of DOMs won't increase even though card elements are added; instead of adding a new DOM, existing DOMs are recycled to maintain the number of DOMs.
      +		 * @ko 추가된 카드 엘리먼트의 전체 개수가 count 옵션의 값보다 큰지 확인한다. 단, count 옵션의 값은 0보다 크다. 'true'가 반환되면 카드 엘리먼트가 더 추가돼도 DOM의 개수를 증가하지 않고 기존 DOM을 재활용(recycle)해 DOM의 개수를 일정하게 유지한다
      +		 * @method eg.InfiniteGrid#isRecycling
      +		 * @return {Boolean} Indicates whether the total number of added card elements is greater than the value of the count option. <ko>추가된 카드 엘리먼트의 전체 개수가 count 옵션의 값보다 큰지 여부</ko>
      +		 */
      +		isRecycling: function() {
      +			return (this.options.count > 0) && this._isRecycling;
      +		},
      +		/**
      +		 * Returns the list of group keys which belongs to card elements currently being maintained. You can use the append() or prepend() method to configure group keys so that multiple card elements can be managed at once. If you do not use these methods to configure group keys, it returns undefined as a group key.
      +		 * @ko 현재 유지하고 있는 카드 엘리먼트의 그룹 키 목록을 반환한다. 여러 개의 카드 엘리먼트를 묶어서 관리할 수 있도록 append() 메서드나 prepend() 메서드에서 그룹 키를 지정할 수 있다. append() 메서드나 prepend() 메서드에서 그룹 키를 지정하지 않았다면 'undefined'가 그룹 키로 반환된다
      +		 * @method eg.InfiniteGrid#getGroupKeys
      +		 * @return {Array} List of group keys <ko>그룹 키의 목록</ko>
      +		 */
      +		getGroupKeys: function() {
      +			return $.map(this.items, function(v) {
      +				return v.groupKey;
      +			});
      +		},
      +		/**
      +		 * Rearranges a layout.
      +		 * @ko 레이아웃을 다시 배치한다.
      +		 * @method eg.InfiniteGrid#layout
      +		 * @return {eg.InfiniteGrid} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		layout: function(items, isRefresh) {
      +			items = items || this.items;
      +			isRefresh = typeof isRefresh === "undefined" ? true : isRefresh;
      +			this._isProcessing = true;
      +			isRefresh && (items = $.map(items, function(v) {
      +				v.isAppend = true;
      +				return v;
      +			}));
      +			this._waitResource(items, isRefresh);
      +			return this;
      +		},
      +		_layoutItems: function(items) {
      +			var self = this;
      +
      +			// for performance
      +			$.each(
      +				$.map(items, function(v) {
      +					v.position = self._getItemLayoutPosition(v);
      +					return v;
      +				}),
      +				function(i, v) {
      +					if (v.el) {
      +						var style = v.el.style;
      +						style.left = v.position.x + "px";
      +						style.top = v.position.y + "px";
      +					}
      +				});
      +		},
      +		/**
      +		 * Adds a card element at the bottom of a grid layout. This method is available only if the isProcessing() method returns false.
      +		 * @ko 카드 엘리먼트를 그리드 레이아웃의 아래에 추가한다. isProcessing() 메서드의 반환값이 'false'일 때만 이 메서드를 사용할 수 있다
      +		 * 이 메소드는 isProcessing()의 반환값이 false일 경우에만 사용 가능하다.
      +		 * @method eg.InfiniteGrid#append
      +		 * @param {Array|String|jQuery} elements Array of the card elements to be added <ko>추가할 카드 엘리먼트의 배열</ko>
      +		 * @param {Number|String} [groupKey] The group key to be configured in a card element. It is set to "undefined" by default.<ko>추가할 카드 엘리먼트에 설정할 그룹 키. 생략하면 값이 'undefined'로 설정된다</ko>
      +		 * @return {Number} The number of added card elements <ko>추가된 카드 엘리먼트의 개수</ko>
      +		 */
      +		append: function($elements, groupKey) {
      +			if (this._isProcessing || $elements.length === 0) {
      +				return;
      +			}
      +
      +			// convert jQuery instance
      +			$elements = $($elements);
      +			this._isProcessing = true;
      +			if (!this.isRecycling()) {
      +				this._isRecycling =
      +				(this.items.length + $elements.length) >= this.options.count;
      +			}
      +			this._insert($elements, groupKey, true);
      +			return $elements.length;
      +		},
      +		/**
      +		 * Adds a card element at the top of a grid layout. This method is available only if the isProcessing() method returns false and the isRecycling() method returns true.
      +		 * @ko 카드 엘리먼트를 그리드 레이아웃의 위에 추가한다. isProcessing() 메서드의 반환값이 'false'이고, isRecycling() 메서드의 반환값이 'true'일 때만 이 메서드를 사용할 수 있다
      +		 * @method eg.InfiniteGrid#prepend
      +		 * @param {Array|String|jQuery} elements Array of the card elements to be added <ko>추가할 카드 엘리먼트 배열</ko>
      +		 * @param {Number|String} [groupKey] The group key to be configured in a card element. It is set to "undefined" by default.<ko>추가할 카드 엘리먼트에 설정할 그룹 키. 생략하면 값이 'undefined'로 설정된다</ko>
      +		 * @return {Number} The number of added card elements <ko>추가된 카드 엘리먼트의 개수</ko>
      +		 */
      +		prepend: function($elements, groupKey) {
      +			if (!this.isRecycling() || this._removedContent === 0 ||
      +				this._isProcessing || $elements.length === 0) {
      +				return;
      +			}
      +
      +			// convert jQuery instance
      +			$elements = $($elements);
      +
      +			this._isProcessing = true;
      +			this._fit();
      +			if ($elements.length > this._removedContent) {
      +				$elements = $elements.slice(0, this._removedContent);
      +			}
      +			this._insert($elements, groupKey, false);
      +			return $elements.length;
      +		},
      +		/**
      +		 * Clears added card elements and data.
      +		 * @ko 추가된 카드 엘리먼트와 데이터를 모두 지운다.
      +		 * @method eg.InfiniteGrid#clear
      +		 * @return {eg.InfiniteGrid} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
      +		 */
      +		clear: function() {
      +			this.el.innerHTML = "";
      +			this.el.style.height = "";
      +			this._reset();
      +			return this;
      +		},
      +
      +		_getTopItem: function() {
      +			var item = null;
      +			var min = Infinity;
      +			$.each(this._getColItems(false), function(i, v) {
      +				if (v && v.position.y < min) {
      +					min = v.position.y;
      +					item = v;
      +				}
      +			});
      +			return item;
      +		},
      +
      +		/**
      +		 * Returns a card element at the top of a layout.
      +		 * @ko 레이아웃의 맨 위에 있는 카드 엘리먼트를 반환한다.
      +		 * @method eg.InfiniteGrid#getTopElement
      +		 *
      +		 * @return {HTMLElement} Card element at the top of a layout <ko>레이아웃의 맨 위에 있는 카드 엘리먼트</ko>
      +		 */
      +		getTopElement: function() {
      +			var item = this._getTopItem();
      +			return item && item.el;
      +		},
      +
      +		_getBottomItem: function() {
      +			var item = null;
      +			var max = -Infinity;
      +			$.each(this._getColItems(true), function(i, v) {
      +				if (v && v.position.y + v.size.height > max) {
      +					max = v.position.y + v.size.height;
      +					item = v;
      +				}
      +			});
      +			return item;
      +		},
      +
      +		/**
      +		 * Returns a card element at the bottom of a layout.
      +		 * @ko 레이아웃의 맨 아래에 있는 카드 엘리먼트를 반환한다.
      +		 * @method eg.InfiniteGrid#getBottomElement
      +		 *
      +		 * @return {HTMLElement} Card element at the bottom of a layout <ko>레이아웃의 맨 아래에 있는 카드 엘리먼트</ko>
      +		 */
      +		getBottomElement: function() {
      +			var item = this._getBottomItem();
      +			return item && item.el;
      +		},
      +
      +		_postLayout: function(items) {
      +			if (!this._isProcessing || items.length <= 0) {
      +				return;
      +			}
      +
      +			var size = this._getContainerSize();
      +			this.el.style.width = size.width + "px";
      +			this.el.style.height = size.height + "px";
      +
      +			// refresh element
      +			this._topElement = this.getTopElement();
      +			this._bottomElement = this.getBottomElement();
      +
      +			var distance = 0;
      +			var isAppend = items[0].isAppend;
      +			if (!isAppend) {
      +				this._isFitted = false;
      +				this._fit(true);
      +				distance = items.length >= this.items.length ?
      +					0 : this.items[items.length].position.y;
      +				if (distance > 0) {
      +					this._prevScrollTop = this._getScrollTop() + distance;
      +					this.$view.scrollTop(this._prevScrollTop);
      +				}
      +			}
      +
      +			// reset flags
      +			this._isProcessing = false;
      +
      +			/**
      +			 * This event is fired when layout is successfully arranged through a call to the append(), prepend(), or layout() method.
      +			 * @ko 레이아웃 배치가 완료됐을 때 발생하는 이벤트. append() 메서드나 prepend() 메서드, layout() 메서드 호출 후 카드의 배치가 완료됐을 때 발생한다
      +			 * @name eg.InfiniteGrid#layoutComplete
      +			 * @event
      +			 *
      +			 * @param {Object} param The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
      +			 * @param {Array} param.target Rearranged card elements<ko>재배치된 카드 엘리먼트들</ko>
      +			 * @param {Boolean} param.isAppend Checks whether the append() method is used to add a card element. It returns true even though the layoutComplete event is fired after the layout() method is called. <ko>카드 엘리먼트가 append() 메서드로 추가됐는지 확인한다. layout() 메서드가 호출된 후 layoutComplete 이벤트가 발생해도 'true'를 반환한다.</ko>
      +			 * @param {Number} param.distance Distance the card element at the top of a grid layout has moved after the layoutComplete event is fired. In other words, it is the same as an increased height with a new card element added using the prepend() method <ko>그리드 레이아웃의 맨 위에 있던 카드 엘리먼트가 layoutComplete 이벤트 발생 후 이동한 거리. 즉, prepend() 메서드로 카드 엘리먼트가 추가돼 늘어난 높이다.</ko>
      +			 * @param {Number} param.croppedCount The number of deleted card elements to maintain the number of DOMs<ko>일정한 DOM 개수를 유지하기 위해, 삭제한 카드 엘리먼트들의 개수</ko>
      +			 */
      +			this.trigger(this._prefix + EVENTS.layoutComplete, {
      +				target: items.concat(),
      +				isAppend: isAppend,
      +				distance: distance,
      +				croppedCount: this._removedContent
      +			});
      +		},
      +
      +		// $elements => $([HTMLElement, HTMLElement, ...])
      +		_insert: function($elements, groupKey, isAppend) {
      +			if ($elements.length === 0) {
      +				return;
      +			}
      +			var elements = $elements.toArray();
      +			var $cloneElements = $(elements);
      +			var dummy = -this._clientHeight + "px";
      +			$.each(elements, function(i, v) {
      +				v.style.position = "absolute";
      +				v.style.top = dummy;
      +			});
      +			var items = this._itemize(elements, groupKey, isAppend);
      +			if (isAppend) {
      +				this.items = this.items.concat(items);
      +			} else {
      +				this.items = items.concat(this.items);
      +				items = items.reverse();
      +			}
      +			this.isRecycling() && this._adjustRange(isAppend, $cloneElements);
      +
      +			this.$el[isAppend ? "append" : "prepend"]($cloneElements);
      +			this.layout(items, false);
      +		},
      +		_waitResource: function(items, isRefresh) {
      +			var needCheck = this._checkImageLoaded();
      +			var self = this;
      +			var callback = function() {
      +				if (self._isProcessing) {
      +					if (isRefresh || !self._appendCols.length) {
      +						$.each(items, function(i, v) {
      +							v.el.style.position = "absolute";
      +						});
      +						self._measureColumns();
      +					}
      +					self._layoutItems(items);
      +					self._postLayout(items);
      +				}
      +			};
      +			if (needCheck.length > 0) {
      +				this._waitImageLoaded(needCheck, callback);
      +			} else {
      +				// convert to async
      +				setTimeout(function() {
      +					callback && callback();
      +				}, 0);
      +			}
      +		},
      +		_adjustRange: function (isTop, $elements) {
      +			var diff = this.items.length - this.options.count;
      +			var targets;
      +			var idx;
      +			if (diff <= 0 || (idx = this._getDelimiterIndex(isTop, diff)) < 0) {
      +				return;
      +			}
      +			if (isTop) {
      +				targets = this.items.splice(0, idx);
      +				this._isFitted = false;
      +			} else {
      +				targets = this.items.splice(idx, this.items.length - idx);
      +			}
      +
      +			// @todo improve performance
      +			$.each(targets, function(i, v) {
      +				idx = $elements.index(v.el);
      +				if (idx !== -1) {
      +					$elements.splice(idx, 1);
      +				} else {
      +					v.el.parentNode.removeChild(v.el);
      +				}
      +			});
      +			this._removedContent += isTop ? targets.length : -targets.length;
      +		},
      +		_getDelimiterIndex: function(isTop, removeCount) {
      +			var len = this.items.length;
      +			var i;
      +			var idx = 0;
      +			var baseIdx = isTop ? removeCount - 1 : len - removeCount;
      +			var targetIdx = baseIdx + (isTop ? 1 : -1);
      +			var groupKey = this.items[baseIdx].groupKey;
      +			if (groupKey != null && groupKey === this.items[targetIdx].groupKey) {
      +				if (isTop) {
      +					for (i = baseIdx; i > 0; i--) {
      +						if (groupKey !== this.items[i].groupKey) {
      +							break;
      +						}
      +					}
      +					idx =  i === 0 ? -1 : i + 1;
      +				} else {
      +					for (i = baseIdx; i < len; i++) {
      +						if (groupKey !== this.items[i].groupKey) {
      +							break;
      +						}
      +					}
      +					idx = i === len ? -1 : i;
      +				}
      +			} else {
      +				idx = isTop ? targetIdx : baseIdx;
      +			}
      +			return idx;
      +		},
      +
      +		// fit size
      +		_fit: function(applyDom) {
      +			// for caching
      +			if (this.options.count <= 0) {
      +				this._fit = function() {
      +					return false;
      +				};
      +				this._isFitted = true;
      +				return false;
      +			}
      +
      +			if (this._isFitted) {
      +				return false;
      +			}
      +			var y = this._updateCols();	// for prepend
      +			$.each(this.items, function(i, v) {
      +				v.position.y -= y;
      +				applyDom && (v.el.style.top = v.position.y + "px");
      +			});
      +			this._updateCols(true);	// for append
      +			var height = this._getContainerSize().height;
      +			applyDom && (this.el.style.height = height + "px");
      +			this._isFitted = true;
      +			return true;
      +		},
      +
      +		/**
      +		* Removes extra space caused by adding card elements.
      +		* @ko 카드 엘리먼트를 추가한 다음 생긴 빈 공간을 제거한다
      +		* @method eg.InfiniteGrid#fit
      +		* @deprecated since version 1.3.0
      +		* @return {Number} Actual length of space removed (unit: px) <ko>빈 공간이 제거된 실제 길이(단위: px)</ko>
      +		*/
      +		fit: function() {
      +			var item = this._getTopItem();
      +			var distance = item ? item.position.y : 0;
      +			this._fit(true);
      +			return distance;
      +		},
      +		_reset: function() {
      +			this._isProcessing = false;
      +			this._topElement = null;
      +			this._bottomElement = null;
      +			this._isFitted = true;
      +			this._isRecycling = false;
      +			this._removedContent = 0;
      +			this._prevScrollTop = 0;
      +			this._equalItemSize = 0;
      +			this._resizeTimeout = null;
      +			this._resetCols(this._appendCols.length || 0);
      +			this.items = [];
      +		},
      +		_checkImageLoaded: function() {
      +			return this.$el.find("img").filter(function(k, v) {
      +				if (v.nodeType && ($.inArray(v.nodeType, [1,9,11]) !== -1)) {
      +					return !v.complete;
      +				}
      +			}).toArray();
      +		},
      +		_waitImageLoaded: function(needCheck, callback) {
      +			var checkCount = needCheck.length;
      +			var onCheck = function(e) {
      +				checkCount--;
      +				$(e.target).off("load error");
      +				checkCount <= 0 && callback && callback();
      +			};
      +			var $el;
      +			var self = this;
      +			$.each(needCheck, function(i, v) {
      +				$el = $(v);
      +
      +				// for IE10 lower
      +				if (self._isIE10lower) {
      +					var url = v.getAttribute("src");
      +					v.setAttribute("src", "");
      +					v.setAttribute("src", url);
      +				}
      +				$el.on("load error", onCheck);
      +			});
      +		},
      +		_measureColumns: function() {
      +			this.el.style.width = null;
      +			this._containerWidth = this.$el.innerWidth();
      +			this._columnWidth = this._getColumnWidth() || this._containerWidth;
      +			var cols = this._containerWidth / this._columnWidth;
      +			var excess = this._columnWidth - this._containerWidth % this._columnWidth;
      +
      +			// if overshoot is less than a pixel, round up, otherwise floor it
      +			cols = Math.max(Math[ excess && excess <= 1 ? "round" : "floor" ](cols), 1);
      +
      +			// reset column Y
      +			this._resetCols(cols || 0);
      +		},
      +		_resetCols: function(count) {
      +			count = typeof count === "undefined" ? 0 : count;
      +			var arr = [];
      +			while (count--) {
      +				arr.push(0);
      +			}
      +			this._appendCols = arr.concat();
      +			this._prependCols = arr.concat();
      +		},
      +		_getContainerSize: function() {
      +			return {
      +				height: Math.max.apply(Math, this._appendCols),
      +				width: this._containerWidth
      +			};
      +		},
      +		_getColumnWidth: function() {
      +			var el = this.items[0] && this.items[0].el;
      +			var width = 0;
      +			if (el) {
      +				var $el = $(el);
      +				width = $el.innerWidth();
      +				if (this.options.isEqualSize) {
      +					this._equalItemSize = {
      +						width: width,
      +						height: $el.innerHeight()
      +					};
      +				}
      +			}
      +			return width;
      +		},
      +		_updateCols: function(isAppend) {
      +			var col = isAppend ? this._appendCols : this._prependCols;
      +			var items = this._getColItems(isAppend);
      +			var base = this._isFitted || isAppend ? 0 : this._getMinY(items);
      +			var i = 0;
      +			var len = col.length;
      +			var item;
      +			for (; i < len; i++) {
      +				if (item = items[i]) {
      +					col[i] = item.position.y + (isAppend ? item.size.height : -base);
      +				} else {
      +					col[i] = 0;
      +				}
      +			}
      +			return base;
      +		},
      +		_getMinY: function(items) {
      +			return Math.min.apply(Math, $.map(items, function(v) {
      +				return v ? v.position.y : 0;
      +			}));
      +		},
      +		_getColIdx: function(item) {
      +			return parseInt(item.position.x / parseInt(this._columnWidth, 10), 10);
      +		},
      +		_getColItems: function(isTail) {
      +			var len = this._appendCols.length;
      +			var colItems = new Array(len);
      +			var item;
      +			var idx;
      +			var count = 0;
      +			var i = isTail ? this.items.length - 1 : 0;
      +			while (item = this.items[i]) {
      +				idx = this._getColIdx(item);
      +				if (!colItems[idx]) {
      +					colItems[idx] = item;
      +					if (++count === len) {
      +						return colItems;
      +					}
      +				}
      +				i += isTail ? -1 : 1;
      +			}
      +			return colItems;
      +		},
      +		_itemize: function(elements, groupKey, isAppend) {
      +			return $.map(elements, function(v) {
      +				return {
      +					el: v,
      +					position: {
      +						x: 0,
      +						y: 0
      +					},
      +					isAppend: typeof isAppend === "undefined" ? true : isAppend,
      +					groupKey: typeof groupKey === "undefined" ? null : groupKey
      +				};
      +			});
      +		},
      +		_getItemLayoutPosition: function(item) {
      +			if (!item.el) {
      +				return;
      +			}
      +			var $el = $(item.el);
      +			item.size = this._equalItemSize || {
      +				width: $el.innerWidth(),
      +				height: $el.innerHeight()
      +			};
      +			var isAppend = item.isAppend;
      +			var cols = isAppend ? this._appendCols : this._prependCols;
      +			var y = Math[isAppend ? "min" : "max"].apply(Math, cols);
      +			var shortColIndex;
      +			if (isAppend) {
      +				shortColIndex = $.inArray(y, cols);
      +			} else {
      +				var i = cols.length;
      +				while (i-- >= 0) {
      +					if (cols[i] === y) {
      +						shortColIndex = i;
      +						break;
      +					}
      +				}
      +			}
      +			cols[shortColIndex] = y + (isAppend ? item.size.height : -item.size.height);
      +
      +			return {
      +				x: this._columnWidth * shortColIndex,
      +				y: isAppend ? y : y - item.size.height
      +			};
      +		},
      +		/**
      +		 * Destroys elements, properties, and events used on a grid layout.
      +		 * @ko 그리드 레이아웃에 사용한 엘리먼트와 속성, 이벤트를 해제한다
      +		 * @method eg.InfiniteGrid#destroy
      +		 */
      +		destroy: function() {
      +			this.off();
      +			this.$view.off("resize", this._onResize)
      +				.off("scroll", this._onScroll);
      +			this._reset();
      +		}
      +	});
      +});
      +/**
      + * A jQuery plugin available in the eg.InfiniteGrid module.
      + * @ko eg.InfiniteGrid 모듈의 jQuery 플러그인
      + * @method jQuery.infiniteGrid
      + * @example
      +		 <ul id="grid">
      +				<li class="item">
      +					<div>test1</div>
      +				</li>
      +				<li class="item">
      +					<div>test3</div>
      +				</li>
      +			</ul>
      +		<script>
      +	// create
      +	$("#grid").infiniteGrid();
      +	// method
      +	$("#grid").infiniteGrid("option","count","60"); //Set option
      +	$("#grid").infiniteGrid("instance"); // Return infiniteGrid instance
      +	$("#grid").infiniteGrid("getBottomElement"); // Get bottom element
      +	</script>
      + * @see eg.InfiniteGrid
      + */
      +/**
      + * A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a layout is successfully arranged.
      + *
      + * @ko eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 레이아웃 배치가 완료됐을 때 발생한다
      + * @name jQuery#infiniteGrid:layoutComplete
      + * @event
      + * @example
      +		 <ul id="grid">
      +				<li class="item">
      +					<div>test1</div>
      +				</li>
      +				<li class="item">
      +					<div>test3</div>
      +				</li>
      +			</ul>
      +		<script>
      +	// create
      +	$("#grid").infiniteGrid();
      +	// event
      +	$("#grid").on("infiniteGrid:layoutComplete",callback);
      +	$("#grid").off("infiniteGrid:layoutComplete",callback);
      +	$("#grid").trigger("infiniteGrid:layoutComplete",callback);
      +	</script>
      + * @see eg.InfiniteGrid#event:layoutComplete
      + */
      +/**
      + * A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a card element must be added at the bottom of a grid layout
      + *
      + * @ko eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 그리드 레이아웃 아래에 카드 엘리먼트가 추가돼야 할 때 발생한다.
      + * @name jQuery#infiniteGrid:append
      + * @event
      + * @example
      +		 <ul id="grid">
      +				<li class="item">
      +					<div>test1</div>
      +				</li>
      +				<li class="item">
      +					<div>test3</div>
      +				</li>
      +			</ul>
      +		<script>
      +	// create
      +	$("#grid").infiniteGrid();
      +	// event
      +	$("#grid").on("infiniteGrid:append",callback);
      +	$("#grid").off("infiniteGrid:append",callback);
      +	$("#grid").trigger("infiniteGrid:append",callback);
      +	</script>
      + * @see eg.InfiniteGrid#event:append
      + */
      +/**
      + * A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a card element must be added at the top of a grid layout
      + *
      + * @ko eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 그리드 레이아웃 위에 카드 엘리먼트가 추가돼야 할 때 발생한다
      + * @name jQuery#infiniteGrid:prepend
      + * @event
      + * @example
      +		 <ul id="grid">
      +				<li class="item">
      +					<div>test1</div>
      +				</li>
      +				<li class="item">
      +					<div>test3</div>
      +				</li>
      +			</ul>
      +		<script>
      +	// create
      +	$("#grid").infiniteGrid();
      +	// event
      +	$("#grid").on("infiniteGrid:prepend",callback);
      +	$("#grid").off("infiniteGrid:prepend",callback);
      +	$("#grid").trigger("infiniteGrid:prepend",callback);
      +	</script>
      + * @see eg.InfiniteGrid#event:prepend
      + */
      +
      +
      +
      + + + + + + + + +
      + + comments powered by Disqus + + + +
      + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:14 GMT+0900 (KST) +
      +
      +
      + + + + + diff --git a/doc/jQuery.html b/doc/jQuery.html new file mode 100644 index 00000000..ac42038c --- /dev/null +++ b/doc/jQuery.html @@ -0,0 +1,3130 @@ + + + + + Namespace: jQuery | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      +

      Namespace: jQuery

      + + + + +
      + +
      +

      + jQuery +

      + + +
      + +
      +
      + + + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + + + + + + + + + + + + + +

      Methods

      + +
      + +
      +
      +

      + + staticjQuery.flicking() +

      + + + + +
      + + +
      +
      + + +
      +

      A jQuery plugin available in the eg.Flicking module.

      +
      + + +
      +

      eg.Flicking 모듈의 jQuery 플러그인

      +
      + + + + + + + + + + + + + + + + + + + +
      Example
      + + + +
      <div id="content">
      +    <div>
      +        <p>Layer 0</p>
      +    </div>
      +    <div>
      +        <p>Layer 1</p>
      +    </div>
      +    <div>
      +        <p>Layer 2</p>
      +    </div>
      +</div>
      +<script>
      +// create
      +$("#content").flicking({
      +    circular : true,
      +     threshold : 50
      +});
      + // method
      +$("#content").flicking("option","circular",true); //Set option
      +$("#content").flicking("instance"); // Return flicking instance
      +$("#content").flicking("getNextIndex",1); // Get next panel index
      + </script>
      + + + + + +
      + + + + + + + + + + + + + + + + + + + +
      See:
      +
      + +
      + + + + + + +
      + +
      + + + +
      +
      +

      + + staticjQuery.infiniteGrid() +

      + + + + +
      + + +
      +
      + + +
      +

      A jQuery plugin available in the eg.InfiniteGrid module.

      +
      + + +
      +

      eg.InfiniteGrid 모듈의 jQuery 플러그인

      +
      + + + + + + + + + + + + + + + + + + + +
      Example
      + + + +
           <ul id="grid">
      +            <li class="item">
      +                <div>test1</div>
      +            </li>
      +            <li class="item">
      +                <div>test3</div>
      +            </li>
      +        </ul>
      +    <script>
      +// create
      +$("#grid").infiniteGrid();
      +// method
      +$("#grid").infiniteGrid("option","count","60"); //Set option
      +$("#grid").infiniteGrid("instance"); // Return infiniteGrid instance
      +$("#grid").infiniteGrid("getBottomElement"); // Get bottom element
      +</script>
      + + + + + +
      + + + + + + + + + + + + + + + + + + + +
      See:
      +
      + +
      + + + + + + +
      + +
      + + + +
      +
      +

      + + staticjQuery.persist(state) +

      + + + + +
      + + +
      +
      + + +
      +

      Stores the current state of the web page in a default key using JSON.

      +
      + + +
      +

      웹 페이지의 현재 상태를 기본 키에 JSON 형식으로 저장한다.

      +
      + + + + + + + + + +
        + +
      • + +
        + state + + + +
        + + +
        Type: +Object + +
        + + + +
        + +

        The state information of the web page written in JSON

        +

        JSON 객체로 정의한 웹 페이지의 상태 정보

        + +
        + + + +
      • + +
      + + + + + + + + + + + + + +
      Example
      + + + +
      $("a").on("click",function(e){
      +    e.preventdefault();
      +    // save state
      +    $.persist(state);
      +});
      + + + + + +
      + + + + + + + +
      Deprecated
      • since version 1.2.0
        + + + + + + + + + + + + + + + + + + +
        + +
        + + + +
        +
        +

        + + staticjQuery.persist(key, state) +

        + + + + +
        + + +
        +
        + + +
        +

        Stores the current state of the web page using JSON.

        +
        + + +
        +

        웹 페이지의 현재 상태를 JSON 형식으로 저장한다

        +
        + + + + + + + + + +
          + +
        • + +
          + key + + + +
          + + +
          Type: +String + +
          + + + +
          + +

          The key of the state information to be stored

          +

          저장할 상태 정보의 키

          + +
          + + + +
        • + +
        • + +
          + state + + + +
          + + +
          Type: +Object + +
          + + + +
          + +

          The value to be stored in a given key

          +

          키에 저장할 값

          + +
          + + + +
        • + +
        + + + + + + + + + + + + + +
        Example
        + + + +
        $("a").on("click",function(e){
        +    e.preventdefault();
        +    // save state
        +    $.persist("KEY",state);
        +});
        + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + + + +
        +
        +

        + + staticjQuery.persist(key){Object} +

        + + + + +
        + + +
        +
        + + +
        +

        Returns the state of stored web pages.

        +
        + + +
        +

        저장된 웹 페이지의 상태를 반환한다

        +
        + + + + + + + + + +
          + +
        • + +
          + key + + + +
          + + +
          Type: +String + +
          + + + +
          + +

          The name of the key to be checked

          +

          값을 확인할 키의 이름

          + +
          + + + +
        • + +
        + + + + + + + + + + + +
        Returns:
        + + + + + + + + + + + + + + + + + + + + +
        TypeDescription
        + + Object + + + + +
        The value of the key
        +

        키의 값

        + + + +
        + + + + +
        Example
        + + + +
        $("a").on("click",function(e){
        +    e.preventdefault();
        +    // get state
        +    var state = $.persist("KEY");
        +});
        + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + + + +
        +
        +

        + + staticjQuery.visible() +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery plugin available in the eg.Visible module.

        +
        + + +
        +

        eg.Visible 모듈의 jQuery 플러그인

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +
        // create
        +$("body").visible();
        +
        + // event
        + $("body").on("visible:change",callback);
        + $("body").off("visible:change",callback);
        + $("body").trigger("visible:change",callback);
        +
        + // method
        + $("body").visible("option","circular",true); //Set option
        + $("body").visible("instance"); // Return flicking instance
        + $("body").visible("check",10); // Check to change target elements.
        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        +
          +
        • eg.Visble#event:change
        • +
        +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + animate(properties, duration, easing, complete) +

        + + + + +
        + + +
        +
        + + +
        +

        A method that extends the .animate() method provided by jQuery. With this method, you can use the transform property and 3D acceleration

        +
        + + +
        +

        jQuery의animate() 메서드를 확장한 메서드. CSS의 transform 속성과 3D 가속을 사용할 수 있다.

        +
        + + + + + + + + + +
          + +
        • + +
          + properties + + + + + + + + +
          + + +
          Type: +Object + +
          + + + +
          + +

          An object composed of the CSS property and value which will be applied to an animation

          +

          애니메이션을 적용할 CSS 속성과 값으로 구성된 객체

          + +
          + + + +
        • + +
        • + +
          + duration + + (default: 4000) + + + + + optional + + + + + +
          + + +
          Type: +Number +| + +String + +
          + + + +
          + +

          Duration of the animation (unit: ms)

          +

          애니메이션 진행 시간(단위: ms)

          + +
          + + + +
        • + +
        • + +
          + easing + + (default: "swing") + + + + + optional + + + + + +
          + + +
          Type: +String + +
          + + + +
          + +

          The easing function to apply to an animation

          +

          애니메이션에 적용할 easing 함수

          + +
          + + + +
        • + +
        • + +
          + complete + + + + + optional + + + + + +
          + + +
          Type: +function + +
          + + + +
          + +

          A function that is called once the animation is complete.

          +

          애니메이션을 완료한 다음 호출할 함수

          + +
          + + + +
        • + +
        + + + + + + + + + + + + + +
        Example
        + + + +

        $("#box") + .animate({"transform" : "translate3d(150px, 100px, 0px) rotate(20deg) scaleX(1)"} , 3000) + .animate({"transform" : "+=translate3d(150px, 10%, -20px) rotate(20deg) scale3d(2, 4.2, 1)"} , 3000);

        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + pause() +

        + + + + +
        + + +
        +
        + + +
        +

        Pauses the animation executed through a call to the jQuery .animate() method.

        +
        + + +
        +

        jQuery의animate() 메서드가 실행한 애니메이션을 일시 정지한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +

        $("#box").pause(); //paused the current animation

        + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + + + +
        +
        +

        + + resume() +

        + + + + +
        + + +
        +
        + + +
        +

        Resumes the animation paused through a call to the pause() method.

        +
        + + +
        +

        pause() 메서드가 일시 정지한 애니메이션을 다시 실행한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +

        $("#box").resume(); //resume the paused animation

        + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + +
        + + + + + +

        Events

        + +
        + +
        +
        +

        + + rotate +

        + + + + +
        + + +
        +
        + + +
        +

        This jQuery custom event is fired when device rotates.

        +
        + + +
        +

        기기가 회전할 때 발생하는 jQuery 커스텀 이벤트

        +
        + + + + + + + + + +
          + +
        • + +
          + e + + + +
          + + +
          Type: +Event + +
          + + + +
          + +

          The Event object in jQuery

          +

          jQuery의 Event 객체

          + +
          + + + +
        • + +
        • + +
          + info + + + +
          + + +
          Type: +Object + +
          + + + +
          + +

          The object of data to be sent when the event is fired

          +

          이벤트가 발생할 때 전달되는 데이터 객체

          + +
          + + + + + +
            + +
          • + +
            + isVertical + + + +
            + + +
            Type: +Boolean + +
            + + + +
            + +

            The orientation of the device (true: portrait, false: landscape)

            +

            기기의 화면 방향(true: 수직 방향, false: 수평 방향)

            + +
            + + + +
          • + +
          + +
        • + +
        + + + + + + + + + + + + + +
        Example
        + + + +

        $(window).on("rotate",function(e, info){ + info.isVertical; +});

        + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + + + +
        +
        +

        + + scrollEnd +

        + + + + +
        + + +
        +
        + + +
        +

        A custom event in jQuery occurs when scroll ends.

        +
        + + +
        +

        스크롤이 끝날 때 발생하는 jQuery 커스텀 이벤트

        +
        + + + + + + + + + +
          + +
        • + +
          + e + + + +
          + + +
          Type: +Event + +
          + + + +
          + +

          The Event object in jQuery

          +

          jQuery의 Event 객체

          + +
          + + + +
        • + +
        • + +
          + info + + + +
          + + +
          Type: +Object + +
          + + + +
          + +

          The object of data to be sent when the event is fired

          +

          이벤트가 발생할 때 전달되는 데이터 객체

          + +
          + + + + + +
            + +
          • + +
            + top + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The size of the vertical scroll pane (unit: px)

            +

            세로 스크롤 영역의 크기(단위: px)

            + +
            + + + +
          • + +
          • + +
            + left + + + +
            + + +
            Type: +Number + +
            + + + +
            + +

            The size of horizontal scroll pane (unit: px)

            +

            가로 스크롤 영역의 크기(단위: px)

            + +
            + + + +
          • + +
          + +
        • + +
        + + + + + + + + + + + + + +
        Example
        + + + +

        $(window).on("scrollend",function(e, info){ + info.top; + info.left; +});

        + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + + + +
        +
        +

        + + flicking:beforeFlickStart +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.Flicking module, which occurs before the flicking starts.

        +
        + + +
        +

        eg.Flicking 모듈의 jQuery 커스텀 이벤트. 플리킹을 시작하기 전에 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +

        $("#mflick").on("flicking:beforeFlickStart",callback); + $("#mflick").off("flicking:beforeFlickStart",callback); + $("#mflick").trigger("flicking:beforeFlickStart",callback);

        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + flicking:beforeRestore +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.Flicking module. This event is fired before an element is restored to its original position when user action is done while the element is not dragged until a certain distance threshold is reached.

        +
        + + +
        +

        eg.Flicking 모듈의 jQuery 커스텀 이벤트. 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원되기 전에 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +

        $("#mflick").on("flicking:beforeRestore",callback); + $("#mflick").off("flicking:beforeRestore",callback); + $("#mflick").trigger("flicking:beforeRestore",callback);

        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + flicking:flick +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.Flicking module. This event is fired when panel moves.

        +
        + + +
        +

        eg.Flicking 모듈의 jQuery 커스텀 이벤트. 패널이 이동될 때 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +

        $("#mflick").on("flicking:flick",callback); + $("#mflick").off("flicking:flick",callback); + $("#mflick").trigger("flicking:flick",callback);

        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + flicking:flickEnd +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.Flicking module. This event is fired after the panel moves.

        +
        + + +
        +

        eg.Flicking 모듈의 jQuery 커스텀 이벤트. 패널이 이동된 뒤 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +

        $("#mflick").on("flicking:flickEnd",callback); + $("#mflick").off("flicking:flickEnd",callback); + $("#mflick").trigger("flicking:flickEnd",callback);

        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + flicking:restore +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.Flicking module. This event is fired after an element is restored to its original position when user action is done while the element has not bene dragged until a certain distance threshold is reached.

        +
        + + +
        +

        eg.Flicking 모듈의 jQuery 커스텀 이벤트. 다음 패널로 바뀌는 기준 이동 거리만큼 이동하기 전에 사용자의 동작이 끝났을 때 원래 패널로 복원된 다음 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +

        $("#mflick").on("flicking:restore",callback); + $("#mflick").off("flicking:restore",callback); + $("#mflick").trigger("flicking:restore",callback);

        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + infiniteGrid:append +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a card element must be added at the bottom of a grid layout

        +
        + + +
        +

        eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 그리드 레이아웃 아래에 카드 엘리먼트가 추가돼야 할 때 발생한다.

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +
             <ul id="grid">
        +            <li class="item">
        +                <div>test1</div>
        +            </li>
        +            <li class="item">
        +                <div>test3</div>
        +            </li>
        +        </ul>
        +    <script>
        +// create
        +$("#grid").infiniteGrid();
        +// event
        +$("#grid").on("infiniteGrid:append",callback);
        +$("#grid").off("infiniteGrid:append",callback);
        +$("#grid").trigger("infiniteGrid:append",callback);
        +</script>
        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + infiniteGrid:layoutComplete +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a layout is successfully arranged.

        +
        + + +
        +

        eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 레이아웃 배치가 완료됐을 때 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +
             <ul id="grid">
        +            <li class="item">
        +                <div>test1</div>
        +            </li>
        +            <li class="item">
        +                <div>test3</div>
        +            </li>
        +        </ul>
        +    <script>
        +// create
        +$("#grid").infiniteGrid();
        +// event
        +$("#grid").on("infiniteGrid:layoutComplete",callback);
        +$("#grid").off("infiniteGrid:layoutComplete",callback);
        +$("#grid").trigger("infiniteGrid:layoutComplete",callback);
        +</script>
        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + infiniteGrid:prepend +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.InfiniteGrid module. This event is fired when a card element must be added at the top of a grid layout

        +
        + + +
        +

        eg.InfiniteGrid 모듈의 jQuery 커스텀 이벤트. 그리드 레이아웃 위에 카드 엘리먼트가 추가돼야 할 때 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +
             <ul id="grid">
        +            <li class="item">
        +                <div>test1</div>
        +            </li>
        +            <li class="item">
        +                <div>test3</div>
        +            </li>
        +        </ul>
        +    <script>
        +// create
        +$("#grid").infiniteGrid();
        +// event
        +$("#grid").on("infiniteGrid:prepend",callback);
        +$("#grid").off("infiniteGrid:prepend",callback);
        +$("#grid").trigger("infiniteGrid:prepend",callback);
        +</script>
        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        + +
        + + + + + + +
        + +
        + + + +
        +
        +

        + + visible:change +

        + + + + +
        + + +
        +
        + + +
        +

        A jQuery custom event of the eg.Visible module. This event is fired when the event is compared with the last verified one and there is an element of which the visibility property has changed.

        +
        + + +
        +

        eg.Visible 모듈의 jQuery 커스텀 이벤트. 마지막으로 확인한 결과와 비교해 visibility 속성이 변경된 엘리먼트가 있을 때 발생한다

        +
        + + + + + + + + + + + + + + + + + + + +
        Example
        + + + +
        // create
        +$("body").visible();
        +
        + // event
        + $("body").on("visible:change",callback);
        + $("body").off("visible:change",callback);
        + $("body").trigger("visible:change",callback);
        + + + + + +
        + + + + + + + + + + + + + + + + + + + +
        See:
        +
        +
          +
        • eg.Visble
        • +
        +
        + + + + + + +
        + +
        + +
        + + + +
        + +
        + + + + + + + +
        + + comments powered by Disqus + + + +
        + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:22 GMT+0900 (KST) +
        +
        +
        + + + + + \ No newline at end of file diff --git a/doc/module.js.html b/doc/module.js.html new file mode 100644 index 00000000..0ee98472 --- /dev/null +++ b/doc/module.js.html @@ -0,0 +1,817 @@ + + + + + Source: module.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + +
        +

        Source: module.js

        + + + + +
        +
        +
        /**
        +* Copyright (c) 2015 NAVER Corp.
        +* egjs projects are licensed under the MIT license
        +*/
        +
        +(function(jQueryName, ns, global) {
        +	"use strict";
        +
        +	var eg;
        +	if (!global[ns]) {
        +		global[ns] = {};
        +	}
        +	eg = global[ns];
        +
        +	var $ = global[jQueryName];
        +
        +	var dependency = {
        +		"jQuery": {
        +			"url": "http://jquery.com/"
        +		},
        +		"Hammer": {
        +			"url": "http://hammerjs.github.io/"
        +		}
        +	};
        +
        +	// jscs:disable maximumLineLength
        +	var templateMessage = [
        +		"[egjs] The {{name}} library must be loaded before {{componentName}}.",
        +		"[egjs] For AMD environment (like RequireJS), \"{{name}}\" must be declared, which is required by {{componentName}}.",
        +        "[egjs] The {{index}} argument of {{componentName}} is missing.\r\nDownload {{name}} from [{{url}}].",
        +		"[egjs] The {{name}} parameter of {{componentName}} is not valid.\r\nPlease check and try again.",
        +        "[egjs] The {{index}} argument of {{componentName}} is undefined.\r\nPlease check and try again."
        +	];
        +
        +	// jscs:enable maximumLineLength
        +
        +	var ordinal = [ "1st", "2nd", "3rd"];
        +
        +	function changeOrdinal(index) {
        +		return index > 2 ? (index + 1) + "th" : ordinal[index];
        +	}
        +
        +	function replaceStr(str, obj) {
        +		var i;
        +		for (i in obj) {
        +			str = str.replace(new RegExp("{{" + i + "}}","gi"), obj[i]);
        +		}
        +		return str;
        +	}
        +
        +	function checkDependency(componentName, di) {
        +		var i = 0;
        +		var l = di.length;
        +		var message = [];
        +		var paramList = [];
        +		var require = global.require;
        +		var dependencyInfo;
        +		var param;
        +		var messageInfo;
        +		var isString;
        +		var isUndefined;
        +		var registedDependency;
        +		var isNotGlobal;
        +		var specifiedAMD;
        +
        +		for (; i < l; i++) {
        +			param = di[i];
        +			messageInfo = {
        +				"index": changeOrdinal(i),
        +				"name": param,
        +				"componentName": componentName
        +			};
        +
        +			isString = typeof di[i] === "string";
        +			isUndefined = di[i] === undefined;
        +			registedDependency = isString && (dependencyInfo = dependency[di[i]]);
        +			isNotGlobal = isString && dependencyInfo && !global[di[i]];
        +			specifiedAMD = isNotGlobal &&
        +				require && require.specified && require.specified(di[i]);
        +
        +			// Message decision flow
        +			//             argument
        +			// |--------------|--------------|
        +			// undefined    string    !string&&!undefined
        +			// |              |              |
        +			// msg(4)         |             (OK)
        +			//         defined dependency
        +			//                |
        +			// |-----------------------------|
        +			// |                             |
        +			// msg(3)                     in global
        +			//                               |
        +			//                 |------------------------------|
        +			//              use AMD                          (OK)
        +			//                 |
        +			//  |------------------------------|
        +			//  msg(2)                  require.specified
        +			// 	                               |
        +			// 	                |------------------------------|
        +			//                  msg(1)                  require.defined
        +			// 	                                               |
        +			//                                  |------------------------------|
        +			//                                  msg(0)                        (OK)
        +
        +			if (!isString && !isUndefined) {
        +				paramList.push(param);
        +				continue;
        +			}
        +
        +			if (specifiedAMD && require.defined(di[i])) {
        +				param = require(di[i]);
        +				paramList.push(param);
        +				continue;
        +			}
        +
        +			if (specifiedAMD && !require.defined(di[i])) {
        +				messageInfo.url = dependencyInfo.url;
        +				message.push(replaceStr(templateMessage[0], messageInfo));
        +				continue;
        +			}
        +
        +			if (isNotGlobal && require &&
        +				require.specified && !require.specified(di[i])) {
        +				messageInfo.url = dependencyInfo.url;
        +				message.push(replaceStr(templateMessage[1], messageInfo));
        +				continue;
        +			}
        +
        +			if (isNotGlobal && !require) {
        +				messageInfo.url = dependencyInfo.url;
        +				message.push(replaceStr(templateMessage[2], messageInfo));
        +				continue;
        +			}
        +
        +			if (registedDependency && global[di[i]]) {
        +				param = global[di[i]];
        +				paramList.push(param);
        +				continue;
        +			}
        +
        +			if (isString && !dependencyInfo) {
        +				message.push(replaceStr(templateMessage[3], messageInfo));
        +				continue;
        +			}
        +
        +			if (di[i] === undefined) {
        +				message.push(replaceStr(templateMessage[4], messageInfo));
        +				continue;
        +			}
        +		}
        +
        +		return [paramList, message];
        +	}
        +
        +	function capitalizeFirstLetter(str) {
        +		return str.charAt(0).toUpperCase() + str.slice(1);
        +	}
        +
        +	function plugin(name) {
        +		var upperCamelCase = capitalizeFirstLetter(name);
        +		var events;
        +		var special;
        +		var componentMethodNames;
        +
        +		if (!(eg[upperCamelCase] && eg[upperCamelCase].prototype &&
        +			eg[upperCamelCase].prototype._events)) {
        +			return false;
        +		}
        +
        +		// jscs:disable validateLineBreaks, maximumLineLength
        +		if ($.fn[name]) {
        +			throw new Error("The name '" + upperCamelCase + "' has already been used and registered as plugin. Try with different one.");
        +		}
        +
        +		// jscs:enable validateLineBreaks, maximumLineLength
        +
        +		// Extend method.
        +		$.fn[name] = function(options) {
        +			var ins;
        +			var result;
        +			if (typeof options === "string") {
        +				ins = this.data(ns + "-" + name);
        +				if (options === "instance") {
        +					return ins;
        +				} else {
        +					result = ins[options].apply(ins, Array.prototype.slice.call(arguments, 1));
        +					return result === ins ? this : result;
        +				}
        +			}
        +
        +			if (options === undefined || $.isPlainObject(options)) {
        +				this.data(ns + "-" + name, new eg[upperCamelCase](
        +					this, options || {}, name + ":"
        +				));
        +			}
        +			return this;
        +		};
        +
        +		componentMethodNames = {
        +			trigger: "trigger",
        +			add: "on",
        +			remove: "off"
        +		};
        +		events = eg[upperCamelCase].prototype._events();
        +
        +		for (var i in events) {
        +			special = $.event.special[name + ":" + events[i]] = {};
        +
        +			// to not bind native event
        +			special.setup = function() {
        +				return true;
        +			};
        +
        +			for (var j in componentMethodNames) {
        +				// jscs:disable validateLineBreaks, maximumLineLength
        +				/*jshint loopfunc: true */
        +				special[j] = (function(componentMethodName) {
        +					return function(event, param) {
        +						$(this).data(ns + "-" + name)[componentMethodName](
        +							event.type,
        +							componentMethodName === "trigger" ? param : event.handler
        +						);
        +						return false;
        +					};
        +				})(componentMethodNames[j]);
        +
        +				// jscs:enable validateLineBreaks, maximumLineLength
        +			}
        +		}
        +	}
        +
        +	var warn = function(msg) {
        +		/* jshint ignore:start */
        +		if (global.console && global.console.warn) {
        +			warn = function(msg) {
        +				global.console.warn(msg);
        +			};
        +		} else {
        +			warn = function(msg) {
        +			};
        +		}
        +		/* jshint ignore:end */
        +		warn(msg);
        +	};
        +
        +	/**
        +	 * Regist module.
        +	 * @private
        +	 */
        +	if (!eg.module) {
        +		eg.module = function(name, di, fp) {
        +			var result = checkDependency(name, di);
        +			if (result[1].length) {
        +				warn(result[1].join("\r\n"));
        +			} else {
        +				fp.apply(global, result[0]);
        +				plugin(name);
        +			}
        +		};
        +	}
        +
        +})("jQuery", "eg", window);
        +
        +
        + + + + + + + + +
        + + comments powered by Disqus + + + +
        + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:13 GMT+0900 (KST) +
        +
        +
        + + + + + diff --git a/doc/movableCoord.js.html b/doc/movableCoord.js.html new file mode 100644 index 00000000..b8a64edf --- /dev/null +++ b/doc/movableCoord.js.html @@ -0,0 +1,1424 @@ + + + + + Source: movableCoord.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + +
        +

        Source: movableCoord.js

        + + + + +
        +
        +
        /**
        +* Copyright (c) 2015 NAVER Corp.
        +* egjs projects are licensed under the MIT license
        +*/
        +
        +// jscs:disable maximumLineLength
        +eg.module("movableCoord", ["jQuery", eg, window, "Hammer"], function($, ns, global, HM) {
        +	"use strict";
        +
        +	var SUPPORT_TOUCH = "ontouchstart" in global;
        +
        +	// jscs:enable maximumLineLength
        +	/**
        +	 * A module used to change the information of user action entered by various input devices such as touch screen or mouse into logical coordinates within the virtual coordinate system. The coordinate information sorted by time events occurred is provided if animations are made by user actions. You can implement a user interface by applying the logical coordinates provided. For more information on the eg.MovableCoord module, see demos.
        +	 * @group egjs
        +	 * @ko 터치 입력 장치나 마우스와 같은 다양한 입력 장치로 전달 받은 사용자의 동작을 가상 좌표계의 논리적 좌표로 변경하는 모듈. 사용자의 동작으로 애니메이션이 일어나면 시간순으로 변경되는 좌표 정보도 제공한다. 변경된 논리적 좌표를 반영해 UI를 구현할 수 있다. eg.MovableCoord 모듈의 자세한 작동 방식은 데모를 참고한다.
        +	 * @class
        +	 * @name eg.MovableCoord
        +	 * @extends eg.Component
        +	 *
        +	 * @param {Object} options The option object of the eg.MovableCoord module<ko>eg.MovableCoord 모듈의 옵션 객체</ko>
        +	 * @param {Array} options.min The minimum value of X and Y coordinates <ko>좌표계의 최솟값</ko>
        +	 * @param {Number} [options.min.0=0] The X coordinate of the minimum <ko>최소 x좌표</ko>
        +	 * @param {Number} [options.min.1=0] The Y coordinate of the minimum <ko>최소 y좌표</ko>
        +	 *
        +	 * @param {Array} options.max The maximum value of X and Y coordinates <ko>좌표계의 최댓값</ko>
        +	 * @param {Number} [options.max.0=100] The X coordinate of the maximum<ko>최대 x좌표</ko>
        +	 * @param {Number} [options.max.1=100] The Y coordinate of the maximum<ko>최대 y좌표</ko>
        +	 *
        +	 * @param {Array} options.bounce The size of bouncing area. The coordinates can exceed the coordinate area as much as the bouncing area based on user action. If the coordinates does not exceed the bouncing area when an element is dragged, the coordinates where bouncing effects are applied are retuned back into the coordinate area<ko>바운스 영역의 크기. 사용자의 동작에 따라 좌표가 좌표 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 사용자가 끌어다 놓는 동작을 했을 때 좌표가 바운스 영역에 있으면, 바운스 효과가 적용된 좌표가 다시 좌표 영역 안으로 들어온다</ko>
        +	 * @param {Boolean} [options.bounce.0=10] The size of top area <ko>위쪽 바운스 영역의 크기</ko>
        +	 * @param {Boolean} [options.bounce.1=10] The size of right area <ko>오른쪽 바운스 영역의 크기</ko>
        +	 * @param {Boolean} [options.bounce.2=10] The size of bottom area <ko>아래쪽 바운스 영역의 크기</ko>
        +	 * @param {Boolean} [options.bounce.3=10] The size of left area <ko>왼쪽 바운스 영역의 크기</ko>
        +	 *
        +	 * @param {Array} options.margin The size of accessible space outside the coordinate area. If an element is dragged outside the coordinate area and then dropped, the coordinates of the element are returned back into the coordinate area. The size of margins that can be exceeded <ko>−	좌표 영역을 넘어 이동할 수 있는 바깥 영역의 크기. 사용자가 좌표를 바깥 영역까지 끌었다가 놓으면 좌표가 좌표 영역 안으로 들어온다.</ko>
        +	 * @param {Boolean} [options.margin.0=0] The size of top margin <ko>위쪽 바깥 영역의 크기</ko>
        +	 * @param {Boolean} [options.margin.1=0] The size of right margin <ko>오른쪽 바깥 영역의 크기</ko>
        +	 * @param {Boolean} [options.margin.2=0] The size of bottom margin <ko>아래쪽 바깥 영역의 크기</ko>
        +	 * @param {Boolean} [options.margin.3=0] The size of left margin <ko>왼쪽 바깥 영역의 크기</ko>
        +	 * @param {Array} options.circular Indicates whether a circular element is available. If it is set to "true" and an element is dragged outside the coordinate area, the element will appear on the other side.<ko>순환 여부. 'true'로 설정한 방향의 좌표 영역 밖으로 엘리먼트가 이동하면 반대 방향에서 엘리먼트가 나타난다</ko>
        +	 * @param {Boolean} [options.circular.0=false] Indicates whether to circulate to top <ko>위로 순환 여부</ko>
        +	 * @param {Boolean} [options.circular.1=false] Indicates whether to circulate to right <ko>오른쪽으로 순환 여부</ko>
        +	 * @param {Boolean} [options.circular.2=false] Indicates whether to circulate to bottom  <ko>아래로 순환 여부</ko>
        +	 * @param {Boolean} [options.circular.3=false] Indicates whether to circulate to left  <ko>왼쪽으로 순환 여부</ko>
        +	 *
        +	 * @param {Function} [options.easing=easing.easeOutCubic] The easing function to apply to an animation <ko>애니메이션에 적용할 easing 함수</ko>
        +	 * @param {Number} [options.maximumDuration=Infinity] Maximum duration of the animation <ko>가속도에 의해 애니메이션이 동작할 때의 최대 좌표 이동 시간</ko>
        +	 * @param {Number} [options.deceleration=0.0006] Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time. <ko>사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다</ko>
        +	 * @see HammerJS {@link http://hammerjs.github.io}
        +	 * @see •	Hammer.JS applies specific CSS properties by default when creating an instance (See {@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}). The eg.MovableCoord module removes all default CSS properties provided by Hammer.JS <ko>Hammer.JS는 인스턴스를 생성할 때 기본으로 특정 CSS 속성을 적용한다(참고: @link{http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}). 특정한 상황에서는 Hammer.JS의 속성 때문에 사용성에 문제가 있을 수 있다. eg.MovableCoord 모듈은 Hammer.JS의 기본 CSS 속성을 모두 제거했다</ko>
        +	 *
        +	 * @codepen {"id":"jPPqeR", "ko":"MovableCoord Cube 예제", "en":"MovableCoord Cube example", "collectionId":"AKpkGW", "height": 403}
        +	 *
        +	 * @see Easing Functions Cheat Sheet {@link http://easings.net/}
        +	 * @see If you want to try a different easing function, use the jQuery easing plugin ({@link http://gsgd.co.uk/sandbox/jquery/easing}) or the jQuery UI easing library ({@link https://jqueryui.com/easing}) <ko>다른 easing 함수를 사용하려면 jQuery easing 플러그인({@link http://gsgd.co.uk/sandbox/jquery/easing})이나, jQuery UI easing 라이브러리({@lin https://jqueryui.com/easing})를 사용한다</ko>
        +	 *
        +	 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
        +	 */
        +	var MC = ns.MovableCoord = ns.Class.extend(ns.Component, {
        +		construct: function(options) {
        +			$.extend(this.options = {
        +				min: [0, 0],
        +				max: [100, 100],
        +				bounce: [10, 10, 10, 10],
        +				margin: [0,0,0,0],
        +				circular: [false, false, false, false],
        +				easing: $.easing.easeOutCubic,
        +				maximumDuration: Infinity,
        +				deceleration: 0.0006
        +			}, options);
        +			this._reviseOptions();
        +			this._status = {
        +				grabOutside: false,		// check whether user's action started on outside
        +				curHammer: null,		// current hammer instance
        +				moveDistance: null,		// a position of the first user's action
        +				animationParam: null,	// animation information
        +				prevented: false		//  check whether the animation event was prevented
        +			};
        +			this._hammers = {};
        +			this._pos = this.options.min.concat();
        +			this._subOptions = {};
        +			this._raf = null;
        +			this._animationEnd = $.proxy(this._animationEnd, this);	// for caching
        +			this._restore = $.proxy(this._restore, this);	// for caching
        +			this._panmove = $.proxy(this._panmove, this);	// for caching
        +			this._panend = $.proxy(this._panend, this);	// for caching
        +		},
        +		/**
        +		 * Registers an element to use the eg.MovableCoord module.
        +		 * @ko eg.MovableCoord 모듈을 사용할 엘리먼트를 등록한다
        +		 * @method eg.MovableCoord#bind
        +		 * @param {HTMLElement|String|jQuery} element Element to use the eg.MovableCoord module<ko>−	eg.MovableCoord 모듈을 사용할 엘리먼트</ko>
        +		 * @param {Object} options The option object of the bind() method <ko>bind() 메서드의 옵션 객체</ko>
        +		 * @param {Number} [options.direction=eg.MovableCoord.DIRECTION_ALL] Coordinate direction that a user can move<br>- eg.MovableCoord.DIRECTION_ALL: All directions available.<br>- eg.MovableCoord.DIRECTION_HORIZONTAL: Horizontal direction only.<br>- eg.MovableCoord.DIRECTION_VERTICAL: Vertical direction only<ko>사용자의 동작으로 움직일 수 있는 좌표의 방향.<br>- eg.MovableCoord.DIRECTION_ALL: 모든 방향으로 움직일 수 있다.<br>- eg.MovableCoord.DIRECTION_HORIZONTAL: 가로 방향으로만 움직일 수 있다.<br>- eg.MovableCoord.DIRECTION_VERTICAL: 세로 방향으로만 움직일 수 있다.</ko>
        +		 * @param {Array} options.scale Coordinate scale that a user can move<ko>사용자의 동작으로 이동하는 좌표의 배율</ko>
        +		 * @param {Number} [options.scale.0=1] X-axis scale <ko>x축 배율</ko>
        +		 * @param {Number} [options.scale.1=1] Y-axis scale <ko>y축 배율</ko>
        +		 * @param {Number} [options.thresholdAngle=45] The threshold value that determines whether user action is horizontal or vertical (0~90) <ko>사용자의 동작이 가로 방향인지 세로 방향인지 판단하는 기준 각도(0~90)</ko>
        +		 * @param {Number} [options.interruptable=true] Indicates whether an animation is interruptible.<br>- true: It can be paused or stopped by user action or the API.<br>- false: It cannot be paused or stopped by user action or the API while it is running.<ko>진행 중인 애니메이션 중지 가능 여부.<br>- true: 사용자의 동작이나 API로 애니메이션을 중지할 수 있다.<br>- false: 애니메이션이 진행 중일 때는 사용자의 동작이나 API가 적용되지 않는다</ko>
        +		 * @param {Array} [options.inputType] Types of input devices. (default: ["touch", "mouse"])<br>- touch: Touch screen<br>- mouse: Mouse <ko>입력 장치 종류.(기본값: ["touch", "mouse"])<br>- touch: 터치 입력 장치<br>- mouse: 마우스</ko>
        +		 *
        +		 * @return {eg.MovableCoord} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
        +		 */
        +		bind: function(el, options) {
        +			var $el = $(el);
        +			var keyValue = $el.data(MC._KEY);
        +			var subOptions = {
        +				direction: MC.DIRECTION_ALL,
        +				scale: [ 1, 1 ],
        +				thresholdAngle: 45,
        +				interruptable: true,
        +				inputType: [ "touch", "mouse" ]
        +			};
        +
        +			$.extend(subOptions, options);
        +
        +			var inputClass = this._convertInputType(subOptions.inputType);
        +			if (!inputClass) {
        +				return this;
        +			}
        +
        +			if (keyValue) {
        +				this._hammers[keyValue].inst.destroy();
        +			} else {
        +				keyValue = Math.round(Math.random() * new Date().getTime());
        +			}
        +			this._hammers[keyValue] = {
        +				inst: this._createHammer(
        +					$el.get(0),
        +					subOptions,
        +					inputClass
        +				),
        +				options: subOptions
        +			};
        +			$el.data(MC._KEY, keyValue);
        +			return this;
        +		},
        +
        +		_createHammer: function(el, subOptions, inputClass) {
        +			try {
        +				// create Hammer
        +				var hammer = new HM.Manager(el, {
        +						recognizers: [
        +							[
        +								HM.Pan, {
        +									direction: subOptions.direction,
        +									threshold: 0
        +								}
        +							]
        +						],
        +
        +						// css properties were removed due to usablility issue
        +						// http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html
        +						cssProps: {
        +							userSelect: "none",
        +							touchSelect: "none",
        +							touchCallout: "none",
        +							userDrag: "none"
        +						},
        +						inputClass: inputClass
        +					});
        +
        +				return this._attachHammerEvents(hammer, subOptions);
        +			} catch (e) {}
        +		},
        +
        +		_attachHammerEvents: function(hammer, options) {
        +			return hammer.on("hammer.input", $.proxy(function(e) {
        +					if (e.isFirst) {
        +						// apply options each
        +						this._subOptions = options;
        +						this._status.curHammer = hammer;
        +						this._panstart(e);
        +					} else if (e.isFinal) {
        +						// substitute .on("panend tap", this._panend); Because it(tap, panend) cannot catch vertical(horizontal) movement on HORIZONTAL(VERTICAL) mode.
        +						this._panend(e);
        +					}
        +				}, this))
        +				.on("panstart panmove", this._panmove);
        +		},
        +
        +		_detachHammerEvents: function(hammer) {
        +			hammer.off("hammer.input panstart panmove panend");
        +		},
        +
        +		_convertInputType: function(inputType) {
        +			var hasTouch = false;
        +			var hasMouse = false;
        +			inputType = inputType || [];
        +			$.each(inputType, function(i, v) {
        +				switch (v) {
        +					case "mouse" : hasMouse = true; break;
        +					case "touch" : hasTouch = SUPPORT_TOUCH;
        +				}
        +			});
        +
        +			return hasTouch && HM.TouchInput || hasMouse && HM.MouseInput || null;
        +		},
        +
        +		/**
        +		 * Detaches elements using the eg.MovableCoord module.
        +		 * @ko eg.MovableCoord 모듈을 사용하는 엘리먼트를 해제한다
        +		 * @method eg.MovableCoord#unbind
        +		 * @param {HTMLElement|String|jQuery} element Elements from which the eg.MovableCoord module is detached<ko>eg.MovableCoord 모듈을 해제할 엘리먼트</ko>
        +		 * @return {eg.MovableCoord} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
        +		 */
        +		unbind: function(el) {
        +			var $el = $(el);
        +			var key = $el.data(MC._KEY);
        +			if (key) {
        +				this._hammers[key].inst.destroy();
        +				delete this._hammers[key];
        +				$el.data(MC._KEY, null);
        +			}
        +			return this;
        +		},
        +
        +		_grab: function() {
        +			if (this._status.animationParam) {
        +				this.trigger("animationEnd");
        +				var pos = this._getCircularPos(this._pos);
        +				if (pos[0] !== this._pos[0] || pos[1] !== this._pos[1]) {
        +					this._pos = pos;
        +					this._triggerChange(this._pos, true);
        +				}
        +				this._status.animationParam = null;
        +				this._raf && ns.cancelAnimationFrame(this._raf);
        +				this._raf = null;
        +			}
        +		},
        +
        +		_getCircularPos: function(pos, min, max, circular) {
        +			min = min || this.options.min;
        +			max = max || this.options.max;
        +			circular = circular || this.options.circular;
        +
        +			if (circular[0] && pos[1] < min[1]) { // up
        +				pos[1] = (pos[1] - min[1]) % (max[1] - min[1] + 1) + max[1];
        +			}
        +			if (circular[1] && pos[0] > max[0]) { // right
        +				pos[0] = (pos[0] - min[0]) % (max[0] - min[0] + 1) + min[0];
        +			}
        +			if (circular[2] && pos[1] > max[1]) { // down
        +				pos[1] = (pos[1] - min[1]) % (max[1] - min[1] + 1) + min[1];
        +			}
        +			if (circular[3] && pos[0] < min[0]) { // left
        +				pos[0] = (pos[0] - min[0]) % (max[0] - min[0] + 1) + max[0];
        +			}
        +			pos[0] = +pos[0].toFixed(5), pos[1] = +pos[1].toFixed(5);
        +
        +			return pos;
        +		},
        +
        +		// determine outside
        +		_isOutside: function(pos, min, max) {
        +			return pos[0] < min[0] || pos[1] < min[1] ||
        +				pos[0] > max[0] || pos[1] > max[1];
        +		},
        +
        +		// from outside to outside
        +		_isOutToOut: function(pos, destPos) {
        +			var min = this.options.min;
        +			var max = this.options.max;
        +			return (pos[0] < min[0] || pos[0] > max[0] ||
        +				pos[1] < min[1] || pos[1] > max[1]) &&
        +				(destPos[0] < min[0] || destPos[0] > max[0] ||
        +				destPos[1] < min[1] || destPos[1] > max[1]);
        +		},
        +
        +		// panstart event handler
        +		_panstart: function(e) {
        +			if (!this._subOptions.interruptable && this._status.prevented) {
        +				return;
        +			}
        +			this._setInterrupt(true);
        +			var pos = this._pos;
        +			this._grab();
        +			/**
        +			 * This event is fired when a user holds an element on the screen of the device.
        +			 * @ko 사용자가 기기의 화면에 손을 대고 있을 때 발생하는 이벤트
        +			 * @name eg.MovableCoord#hold
        +			 * @event
        +			 * @param {Object} param The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
        +			 * @param {Array} param.pos coordinate <ko>좌표 정보</ko>
        +			 * @param {Number} param.pos.0 The X coordinate<ko>x 좌표</ko>
        +			 * @param {Number} param.pos.1 The Y coordinate<ko>y 좌표</ko>
        +			 * @param {Object} param.hammerEvent The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.<ko>Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다.</ko>
        +			 *
        +			 */
        +			this.trigger("hold", {
        +				pos: pos.concat(),
        +				hammerEvent: e
        +			});
        +			this._status.moveDistance = pos.concat();
        +			this._status.grabOutside = this._isOutside(
        +				pos,
        +				this.options.min,
        +				this.options.max
        +			);
        +		},
        +
        +		// panmove event handler
        +		_panmove: function(e) {
        +			if (!this._isInterrupting() || !this._status.moveDistance) {
        +				return;
        +			}
        +			var tv;
        +			var tn;
        +			var tx;
        +			var pos = this._pos;
        +			var min = this.options.min;
        +			var max = this.options.max;
        +			var bounce = this.options.bounce;
        +			var margin = this.options.margin;
        +			var direction = this._subOptions.direction;
        +			var scale = this._subOptions.scale;
        +			var userDirection = this._getDirection(e.angle);
        +			var out = [
        +				margin[0] + bounce[0],
        +				margin[1] + bounce[1],
        +				margin[2] + bounce[2],
        +				margin[3] + bounce[3]
        +			];
        +			var prevent  = false;
        +
        +			// not support offset properties in Hammerjs - start
        +			var prevInput = this._status.curHammer.session.prevInput;
        +			if (prevInput) {
        +				e.offsetX = e.deltaX - prevInput.deltaX;
        +				e.offsetY = e.deltaY - prevInput.deltaY;
        +			} else {
        +				e.offsetX = e.offsetY = 0;
        +			}
        +
        +			// not support offset properties in Hammerjs - end
        +			if (direction === MC.DIRECTION_ALL ||
        +				(direction & MC.DIRECTION_HORIZONTAL &&
        +				userDirection & MC.DIRECTION_HORIZONTAL)
        +			) {
        +				this._status.moveDistance[0] += (e.offsetX * scale[0]);
        +				prevent = true;
        +			}
        +			if (direction === MC.DIRECTION_ALL ||
        +				(direction & MC.DIRECTION_VERTICAL &&
        +				userDirection & MC.DIRECTION_VERTICAL)
        +			) {
        +				this._status.moveDistance[1] += (e.offsetY * scale[1]);
        +				prevent = true;
        +			}
        +			if (prevent) {
        +				e.srcEvent.preventDefault();
        +				e.srcEvent.stopPropagation();
        +			}
        +
        +			e.preventSystemEvent = prevent;
        +			pos[0] = this._status.moveDistance[0];
        +			pos[1] = this._status.moveDistance[1];
        +			pos = this._getCircularPos(pos, min, max);
        +
        +			// from outside to inside
        +			if (this._status.grabOutside && !this._isOutside(pos, min, max)) {
        +				this._status.grabOutside = false;
        +			}
        +
        +			// when move pointer is held in outside
        +			if (this._status.grabOutside) {
        +				tn = min[0] - out[3], tx = max[0] + out[1], tv = pos[0];
        +				pos[0] = tv > tx ? tx : (tv < tn ? tn : tv);
        +				tn = min[1] - out[0], tx = max[1] + out[2], tv = pos[1];
        +				pos[1] = tv > tx ? tx : (tv < tn ? tn : tv);
        +			} else {
        +
        +				// when start pointer is held in inside
        +				// get a initialization slope value to prevent smooth animation.
        +				var initSlope = this._initSlope();
        +				if (pos[1] < min[1]) { // up
        +					tv = (min[1] - pos[1]) / (out[0] * initSlope);
        +					pos[1] = min[1] - this._easing(tv) * out[0];
        +				} else if (pos[1] > max[1]) { // down
        +					tv = (pos[1] - max[1]) / (out[2] * initSlope);
        +					pos[1] = max[1] + this._easing(tv) * out[2];
        +				}
        +				if (pos[0] < min[0]) { // left
        +					tv = (min[0] - pos[0]) / (out[3] * initSlope);
        +					pos[0] = min[0] - this._easing(tv) * out[3];
        +				} else if (pos[0] > max[0]) { // right
        +					tv = (pos[0] - max[0]) / (out[1] * initSlope);
        +					pos[0] = max[0] + this._easing(tv) * out[1];
        +				}
        +
        +			}
        +			this._triggerChange(pos, true, e);
        +		},
        +
        +		// panend event handler
        +		_panend: function(e) {
        +			var pos = this._pos;
        +
        +			if (!this._isInterrupting() || !this._status.moveDistance) {
        +				return;
        +			}
        +
        +			// Abort the animating post process when "tap" occurs
        +			if (e.distance === 0 /*e.type === "tap"*/) {
        +				this._setInterrupt(false);
        +				this.trigger("release", {
        +					depaPos: pos.concat(),
        +					destPos: pos.concat(),
        +					hammerEvent: e || null
        +				});
        +			} else {
        +				var direction = this._subOptions.direction;
        +				var scale = this._subOptions.scale;
        +				var vX =  Math.abs(e.velocityX);
        +				var vY = Math.abs(e.velocityY);
        +
        +				!(direction & MC.DIRECTION_HORIZONTAL) && (vX = 0);
        +				!(direction & MC.DIRECTION_VERTICAL) && (vY = 0);
        +
        +				var offset = this._getNextOffsetPos([
        +					vX * (e.deltaX < 0 ? -1 : 1) * scale[0],
        +					vY * (e.deltaY < 0 ? -1 : 1) * scale[1]
        +				]);
        +				var destPos = [ pos[0] + offset[0], pos[1] + offset[1] ];
        +				destPos = this._getPointOfIntersection(pos, destPos);
        +				/**
        +				 * This event is fired when a user release an element on the screen of the device.
        +				 * @ko 사용자가 기기의 화면에서 손을 뗐을 때 발생하는 이벤트
        +				 * @name eg.MovableCoord#release
        +				 * @event
        +				 *
        +				 * @param {Object} param The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
        +				 * @param {Array} param.depaPos The coordinates when releasing an element<ko>손을 뗐을 때의 좌표현재 </ko>
        +				 * @param {Number} param.depaPos.0 The X coordinate <ko> x 좌표</ko>
        +				 * @param {Number} param.depaPos.1 The Y coordinate <ko> y 좌표</ko>
        +				 * @param {Array} param.destPos The coordinates to move to after releasing an element<ko>손을 뗀 뒤에 이동할 좌표</ko>
        +				 * @param {Number} param.destPos.0 The X coordinate <ko>x 좌표</ko>
        +				 * @param {Number} param.destPos.1 The Y coordinate <ko>y 좌표</ko>
        +				 * @param {Object} param.hammerEvent The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.<ko>Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다</ko>
        +				 *
        +				 */
        +				this.trigger("release", {
        +					depaPos: pos.concat(),
        +					destPos: destPos,
        +					hammerEvent: e || null
        +				});
        +
        +				if (pos[0] !== destPos[0] || pos[1] !== destPos[1]) {
        +					this._animateTo(destPos, null, e || null);
        +				} else {
        +					this._setInterrupt(false);
        +				}
        +			}
        +			this._status.moveDistance = null;
        +		},
        +
        +		_isInterrupting: function() {
        +			// when interruptable is 'true', return value is always 'true'.
        +			return this._subOptions.interruptable || this._status.prevented;
        +		},
        +
        +		// get user's direction
        +		_getDirection: function(angle) {
        +			var thresholdAngle = this._subOptions.thresholdAngle;
        +			if (thresholdAngle < 0 || thresholdAngle > 90) {
        +				return MC.DIRECTION_NONE;
        +			}
        +			angle = Math.abs(angle);
        +			return angle > thresholdAngle && angle < 180 - thresholdAngle ?
        +					MC.DIRECTION_VERTICAL : MC.DIRECTION_HORIZONTAL;
        +		},
        +
        +		_getNextOffsetPos: function(speeds) {
        +			var normalSpeed = Math.sqrt(
        +				speeds[0] * speeds[0] + speeds[1] * speeds[1]
        +			);
        +			var duration = Math.abs(normalSpeed / -this.options.deceleration);
        +			return [
        +				speeds[0] / 2 * duration,
        +				speeds[1] / 2 * duration
        +			];
        +		},
        +
        +		_getDurationFromPos: function(pos) {
        +			var normalPos = Math.sqrt(pos[0] * pos[0] + pos[1] * pos[1]);
        +			var duration = Math.sqrt(
        +				normalPos / this.options.deceleration * 2
        +			);
        +
        +			// when duration is under 100, then value is zero
        +			return duration < 100 ? 0 : duration;
        +		},
        +
        +		_getPointOfIntersection: function(depaPos, destPos) {
        +			var circular = this.options.circular;
        +			var bounce = this.options.bounce;
        +			var min = this.options.min;
        +			var max = this.options.max;
        +			var boxLT = [ min[0] - bounce[3], min[1] - bounce[0] ];
        +			var boxRB = [ max[0] + bounce[1], max[1] + bounce[2] ];
        +			var xd;
        +			var yd;
        +			destPos = [destPos[0], destPos[1]];
        +			xd = destPos[0] - depaPos[0], yd = destPos[1] - depaPos[1];
        +			if (!circular[3]) {
        +				destPos[0] = Math.max(boxLT[0], destPos[0]);
        +			} // left
        +			if (!circular[1]) {
        +				destPos[0] = Math.min(boxRB[0], destPos[0]);
        +			} // right
        +			destPos[1] = xd ?
        +							depaPos[1] + yd / xd * (destPos[0] - depaPos[0]) :
        +							destPos[1];
        +
        +			if (!circular[0]) {
        +				destPos[1] = Math.max(boxLT[1], destPos[1]);
        +			} // up
        +			if (!circular[2]) {
        +				destPos[1] = Math.min(boxRB[1], destPos[1]);
        +			} // down
        +			destPos[0] = yd ?
        +							depaPos[0] + xd / yd * (destPos[1] - depaPos[1]) :
        +							destPos[0];
        +			return [
        +				Math.min(max[0], Math.max(min[0], destPos[0])),
        +				Math.min(max[1], Math.max(min[1], destPos[1]))
        +			];
        +		},
        +
        +		_isCircular: function(destPos) {
        +			var circular = this.options.circular;
        +			var min = this.options.min;
        +			var max = this.options.max;
        +			return (circular[0] && destPos[1] < min[1]) ||
        +					(circular[1] && destPos[0] > max[0]) ||
        +					(circular[2] && destPos[1] > max[1]) ||
        +					(circular[3] && destPos[0] < min[0]);
        +		},
        +
        +		_prepareParam: function(absPos, duration, hammerEvent) {
        +			var pos = this._pos;
        +			var destPos = this._getPointOfIntersection(pos, absPos);
        +			destPos = this._isOutToOut(pos, destPos) ? pos : destPos;
        +			var distance = [
        +				Math.abs(destPos[0] - pos[0]),
        +				Math.abs(destPos[1] - pos[1])
        +			];
        +			duration = duration == null ? this._getDurationFromPos(distance) : duration;
        +			duration = this.options.maximumDuration > duration ?
        +						duration : this.options.maximumDuration;
        +			return {
        +				depaPos: pos.concat(),
        +				destPos: destPos.concat(),
        +				isBounce: this._isOutside(destPos, this.options.min, this.options.max),
        +				isCircular: this._isCircular(absPos),
        +				duration: duration,
        +				distance: distance,
        +				hammerEvent: hammerEvent || null,
        +				done: this._animationEnd
        +			};
        +		},
        +
        +		_restore: function(complete, hammerEvent) {
        +			var pos = this._pos;
        +			var min = this.options.min;
        +			var max = this.options.max;
        +			this._animate(this._prepareParam([
        +				Math.min(max[0], Math.max(min[0], pos[0])),
        +				Math.min(max[1], Math.max(min[1], pos[1]))
        +			], null, hammerEvent), complete);
        +		},
        +
        +		_animationEnd: function() {
        +			this._status.animationParam = null;
        +			this._pos = this._getCircularPos([
        +				Math.round(this._pos[0]),
        +				Math.round(this._pos[1])
        +			]);
        +			this._setInterrupt(false);
        +			/**
        +			 * This event is fired when animation ends.
        +			 * @ko 에니메이션이 끝났을 때 발생한다.
        +			 * @name eg.MovableCoord#animationEnd
        +			 * @event
        +			 */
        +			this.trigger("animationEnd");
        +		},
        +
        +		_animate: function(param, complete) {
        +			param.startTime = new Date().getTime();
        +			this._status.animationParam = param;
        +			if (param.duration) {
        +				var info = this._status.animationParam;
        +				var self = this;
        +				(function loop() {
        +					self._raf = null;
        +					if (self._frame(info) >= 1) {
        +						// deferred.resolve();
        +						complete();
        +						return;
        +					} // animationEnd
        +					self._raf = ns.requestAnimationFrame(loop);
        +				})();
        +			} else {
        +				this._triggerChange(param.destPos, false);
        +				complete();
        +			}
        +		},
        +
        +		_animateTo: function(absPos, duration, hammerEvent) {
        +			var param = this._prepareParam(absPos, duration, hammerEvent);
        +			var retTrigger = this.trigger("animationStart", param);
        +
        +			// You can't stop the 'animationStart' event when 'circular' is true.
        +			if (param.isCircular && !retTrigger) {
        +				throw new Error(
        +					"You can't stop the 'animation' event when 'circular' is true."
        +				);
        +			}
        +
        +			if (retTrigger) {
        +				var self = this;
        +				var queue = [];
        +				var dequeue = function() {
        +					var task = queue.shift();
        +					task && task.call(this);
        +				};
        +				if (param.depaPos[0] !== param.destPos[0] ||
        +					param.depaPos[1] !== param.destPos[1]) {
        +					queue.push(function() {
        +						self._animate(param, dequeue);
        +					});
        +				}
        +				if (this._isOutside(param.destPos, this.options.min, this.options.max)) {
        +					queue.push(function() {
        +						self._restore(dequeue, hammerEvent);
        +					});
        +				}
        +				queue.push(function() {
        +					self._animationEnd();
        +				});
        +				dequeue();
        +			}
        +		},
        +
        +		// animation frame (0~1)
        +		_frame: function(param) {
        +			var curTime = new Date() - param.startTime;
        +			var easingPer = this._easing(curTime / param.duration);
        +			var pos = [ param.depaPos[0], param.depaPos[1] ];
        +
        +			for (var i = 0; i < 2 ; i++) {
        +				(pos[i] !== param.destPos[i]) &&
        +				(pos[i] += (param.destPos[i] - pos[i]) * easingPer);
        +			}
        +			pos = this._getCircularPos(pos);
        +			this._triggerChange(pos, false);
        +			return easingPer;
        +		},
        +
        +		// set up 'css' expression
        +		_reviseOptions: function() {
        +			var key;
        +			var self = this;
        +			$.each(["bounce", "margin", "circular"], function(i, v) {
        +				key = self.options[v];
        +				if (key != null) {
        +					if ($.isArray(key)) {
        +						self.options[v] = key.length === 2 ?
        +							key.concat(key) : key.concat();
        +					} else if (/string|number|boolean/.test(typeof key)) {
        +						self.options[v] = [ key, key, key, key ];
        +					} else {
        +						self.options[v] = null;
        +					}
        +				}
        +			});
        +		},
        +
        +		// trigger 'change' event
        +		_triggerChange: function(pos, holding, e) {
        +			/**
        +			 * This event is fired when coordinate changes.
        +			 * @ko 좌표가 변경됐을 때 발생하는 이벤트
        +			 * @name eg.MovableCoord#change
        +			 * @event
        +			 *
        +			 * @param {Object} param The object of data to be sent when the event is fired <ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
        +			 * @param {Array} param.pos departure coordinate  <ko>좌표</ko>
        +			 * @param {Number} param.pos.0 The X coordinate <ko>x 좌표</ko>
        +			 * @param {Number} param.pos.1 The Y coordinate <ko>y 좌표</ko>
        +			 * @param {Boolean} param.holding Indicates whether a user holds an element on the screen of the device.<ko>사용자가 기기의 화면을 누르고 있는지 여부</ko>
        +			 * @param {Object} param.hammerEvent The event information of Hammer.JS. It returns null if the event is fired through a call to the setTo() or setBy() method.<ko>Hammer.JS의 이벤트 정보. setTo() 메서드나 setBy() 메서드를 호출해 이벤트가 발생했을 때는 'null'을 반환한다.</ko>
        +			 *
        +			 */
        +			this._pos = pos.concat();
        +			this.trigger("change", {
        +				pos: pos.concat(),
        +				holding: holding,
        +				hammerEvent: e || null
        +			});
        +		},
        +
        +		/**
        +		 * Returns the current position of the logical coordinates.
        +		 * @ko 논리적 좌표의 현재 위치를 반환한다
        +		 * @method eg.MovableCoord#get
        +		 * @return {Array} pos <ko>좌표</ko>
        +		 * @return {Number} pos.0 The X coordinate <ko>x 좌표</ko>
        +		 * @return {Number} pos.1 The Y coordinate <ko>y 좌표</ko>
        +		 */
        +		get: function() {
        +			return this._pos.concat();
        +		},
        +
        +		/**
        +		 * Moves an element to specific coordinates.
        +		 * @ko 좌표를 이동한다.
        +		 * @method eg.MovableCoord#setTo
        +		 * @param {Number} x The X coordinate to move to <ko>이동할 x좌표</ko>
        +		 * @param {Number} y The Y coordinate to move to  <ko>이동할 y좌표</ko>
        +		 * @param {Number} [duration=0] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
        +		 * @return {eg.MovableCoord} An instance of a module itself <ko>자신의 인스턴스</ko>
        +		 */
        +		setTo: function(x, y, duration) {
        +			this._grab();
        +			var pos = this._pos.concat();
        +			var circular = this.options.circular;
        +			var min = this.options.min;
        +			var max = this.options.max;
        +			if (x === pos[0] && y === pos[1]) {
        +				return this;
        +			}
        +			this._setInterrupt(true);
        +			if (x !== pos[0]) {
        +				if (!circular[3]) {
        +					x = Math.max(min[0], x);
        +				}
        +				if (!circular[1]) {
        +					x = Math.min(max[0], x);
        +				}
        +			}
        +			if (y !== pos[1]) {
        +				if (!circular[0]) {
        +					y = Math.max(min[1], y);
        +				}
        +				if (!circular[2]) {
        +					y = Math.min(max[1], y);
        +				}
        +			}
        +			if (duration) {
        +				this._animateTo([ x, y ], duration);
        +			} else {
        +				this._pos = this._getCircularPos([ x, y ]);
        +				this._triggerChange(this._pos, false);
        +				this._setInterrupt(false);
        +			}
        +			return this;
        +		},
        +		/**
        +		 * Moves an element from the current coordinates to specific coordinates. The change event is fired when the method is executed.
        +		 * @ko 현재 좌표를 기준으로 좌표를 이동한다. 메서드가 실행되면 change 이벤트가 발생한다
        +		 * @method eg.MovableCoord#setBy
        +		 * @param {Number} x The X coordinate to move to <ko>이동할 x좌표</ko>
        +		 * @param {Number} y The Y coordinate to move to <ko>이동할 y좌표</ko>
        +		 * @param {Number} [duration=0] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
        +		 * @return {eg.MovableCoord} An instance of a module itself <ko>자신의 인스턴스</ko>
        +		 */
        +		setBy: function(x, y, duration) {
        +			return this.setTo(
        +				x != null ? this._pos[0] + x : this._pos[0],
        +				y != null ? this._pos[1] + y : this._pos[1],
        +				duration
        +			);
        +		},
        +
        +		_easing: function(p) {
        +			return p > 1 ? 1 : this.options.easing(p, p, 0, 1, 1);
        +		},
        +
        +		_initSlope: function() {
        +			var easing = this.options.easing;
        +			var isIn = false;
        +			var p;
        +			for (p in $.easing) {
        +				if ($.easing[p] === easing) {
        +					isIn = !~p.indexOf("Out");
        +					break;
        +				}
        +			}
        +			return isIn ?
        +					easing(0.9999, 0.9999, 0, 1, 1) / 0.9999 :
        +					easing(0.00001, 0.00001, 0, 1, 1) / 0.00001;
        +		},
        +
        +		_setInterrupt: function(prevented) {
        +			!this._subOptions.interruptable &&
        +			(this._status.prevented = prevented);
        +		},
        +
        +		/**
        +		 * Destroys elements, properties, and events used in a module.
        +		 * @ko 모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다.
        +		 * @method eg.MovableCoord#destroy
        +		 */
        +		destroy: function() {
        +			this.off();
        +			for (var p in this._hammers) {
        +				this._hammers[p].inst.destroy();
        +				this._hammers[p] = null;
        +			}
        +		}
        +	});
        +	MC._KEY = "__MOVABLECOORD__";
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_NONE
        +	 * @constant
        +	 * @type {Number}
        +	 */
        +	MC.DIRECTION_NONE = 1;
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_LEFT
        +	 * @constant
        +	 * @type {Number}
        +	*/
        +	MC.DIRECTION_LEFT = 2;
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_RIGHT
        +	 * @constant
        +	 * @type {Number}
        +	*/
        +	MC.DIRECTION_RIGHT = 4;
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_UP
        +	 * @constant
        +	 * @type {Number}
        +	  */
        +	MC.DIRECTION_UP = 8;
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_DOWN
        +	 * @constant
        +	 * @type {Number}
        +	*/
        +	MC.DIRECTION_DOWN = 16;
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_HORIZONTAL
        +	 * @constant
        +	 * @type {Number}
        +	*/
        +	MC.DIRECTION_HORIZONTAL = 2 | 4;
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_VERTICAL
        +	 * @constant
        +	 * @type {Number}
        +	*/
        +	MC.DIRECTION_VERTICAL = 8 | 16;
        +
        +	/**
        +	 * @name eg.MovableCoord.DIRECTION_ALL
        +	 * @constant
        +	 * @type {Number}
        +	*/
        +	MC.DIRECTION_ALL = MC.DIRECTION_HORIZONTAL | MC.DIRECTION_VERTICAL;
        +
        +	return {
        +		"MovableCoord": ns.MovableCoord
        +	};
        +});
        +
        +
        + + + + + + + + +
        + + comments powered by Disqus + + + +
        + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:15 GMT+0900 (KST) +
        +
        +
        + + + + + diff --git a/doc/pauseResume.js.html b/doc/pauseResume.js.html new file mode 100644 index 00000000..f7595d5b --- /dev/null +++ b/doc/pauseResume.js.html @@ -0,0 +1,912 @@ + + + + + Source: hook/pauseResume.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + +
        +

        Source: hook/pauseResume.js

        + + + + +
        +
        +
        /**
        +* Copyright (c) 2015 NAVER Corp.
        +* egjs projects are licensed under the MIT license
        +*/
        +eg.module("pauseResume", ["jQuery"], function($) {
        +	"use strict";
        +
        +	var animateFn = $.fn.animate;
        +	var stopFn = $.fn.stop;
        +	var delayFn = $.fn.delay;
        +	var uuid = 1;
        +
        +	function AniProperty(type, el, prop, optall) {
        +		this.el = el;
        +		this.opt = optall;
        +		this.start = -1;
        +		this.elapsed = 0;
        +		this.paused = false;
        +		this.uuid = uuid++;
        +		this.easingNames = [];
        +		this.prop = prop;
        +		this.type = type;
        +	}
        +
        +	/**
        +	 * Generate a new absolute value maker.
        +	 *
        +	 * function to avoid JS Hint error "Don't make functions within a loop"
        +	 */
        +	function generateAbsoluteValMaker(prevValue, propName, sign) {
        +		return function absoluteValMaker(match) {
        +			if (!prevValue || prevValue === "auto") {
        +				// Empty strings, null, undefined and "auto" are converted to 0.
        +				// This solution is somewhat extracted from jQuery Tween.propHooks._default.get
        +				// TODO: Should we consider adopting a Tween.propHooks?
        +				prevValue = 0;
        +			} else {
        +				prevValue = parseFloat(prevValue);
        +			}
        +			return prevValue + (match * sign);
        +		};
        +	}
        +
        +	AniProperty.prototype.init = function() {
        +		var currValue;
        +		this.start = $.now();
        +		this.elapsed = 0;
        +
        +		for (var propName in this.prop) {
        +			var propValue = this.prop[propName];
        +			var markIndex;
        +			var sign;
        +
        +			// DO NOT SUPPORT TRANSFORM YET
        +			// TODO: convert from relative value to absolute value on transform
        +			if (propName === "transform") {
        +				continue;
        +			}
        +
        +			//If it has a absoulte value.
        +			if (typeof propValue !== "string" ||
        +				(markIndex = propValue.search(/[+|-]=/)) < 0) {
        +				// this.prop[propName] = propValue;
        +				continue;
        +			}
        +
        +			//If it has a relative value
        +			sign = propValue.charAt(markIndex) === "-" ? -1 : 1;
        +
        +			// Current value
        +			currValue = $.css(this.el, propName);
        +
        +			// CurrValue + (relativeValue)
        +			this.prop[propName] = propValue
        +				.replace(/([-|+])*([\d|\.])+/g,
        +					generateAbsoluteValMaker(currValue, propName, sign))
        +				.replace(/[-|+]+=/g, "");
        +		}
        +	};
        +
        +	AniProperty.prototype.addEasingFn = function(easingName) {
        +		this.easingNames.push(easingName);
        +	};
        +
        +	AniProperty.prototype.clearEasingFn = function() {
        +		var easing;
        +		while (easing = this.easingNames.shift()) {
        +			delete $.easing[easing];
        +		}
        +		this.easingNames = [];
        +	};
        +
        +	function addAniProperty(type, el, prop, optall) {
        +		var newProp;
        +
        +		newProp = new AniProperty(type, el, prop, optall);
        +		el.__aniProps = el.__aniProps || [];
        +
        +		//Animation is excuted immediately.
        +		if (el.__aniProps.length === 0) {
        +			newProp.init();
        +		}
        +		el.__aniProps.push(newProp);
        +	}
        +
        +	function removeAniProperty(el) {
        +		var removeProp = el.__aniProps.shift();
        +		removeProp && removeProp.clearEasingFn();
        +
        +		el.__aniProps[0] && el.__aniProps[0].init();
        +	}
        +
        +	$.fn.animate = function(prop, speed, easing, callback) {
        +		return this.each(function() {
        +			//optall should be made for each elements.
        +			var optall = $.speed(speed, easing, callback);
        +			var userCallback = optall.old;//hook a user callback.
        +
        +			//Override to check current animation is done.
        +			optall.complete = function() {
        +				//Dequeue animation property that was ended.
        +				var removeProp = this.__aniProps.shift();
        +				removeProp.clearEasingFn();
        +
        +				// Callback should be called before aniProps.init()
        +				if (userCallback && typeof userCallback === "function") {
        +					userCallback.call(this);
        +				}
        +
        +				// If next ani property exists
        +				this.__aniProps[0] && this.__aniProps[0].init();
        +			};
        +
        +			//Queue animation property to recover the current animation.
        +			addAniProperty("animate", this, prop, optall);
        +			animateFn.call($(this), prop, optall);
        +		});
        +
        +		// TODO: Below code is more reasonable?
        +		// return animateFn.call(this, prop, optall); // and declare optall at outside this.each loop.
        +	};
        +
        +	// Check if this element can be paused/resume.
        +	function getStatus(el) {
        +		if (!el.__aniProps || el.__aniProps.length === 0) {
        +			// Current element doesn't have animation information.
        +			// Check 'animate' is applied to this element.
        +			return "empty";
        +		}
        +
        +		return el.__aniProps[0].paused ? "paused" : "inprogress";
        +	}
        +
        +	/**
        +	 * Set a timer to delay execution of subsequent items in the queue.
        +	 * And it internally manages "fx"queue to support pause/resume if "fx" type.
        +	 *
        +	 * @param {Number} An integer indicating the number of milliseconds to delay execution of the next item in the queue.
        +	 * @param {String} A string containing the name of the queue. Defaults to fx, the standard effects queue.
        +	 */
        +	$.fn.delay = function(time, type) {
        +		var t;
        +		var isCallByResume = arguments[2];//internal used value.
        +
        +		if (type && type !== "fx") {
        +			return delayFn.call(this, time, type);
        +		}
        +
        +		t = parseInt(time, 10);
        +		t = isNaN(t) ? 0 : t;
        +
        +		return this.each(function() {
        +			if (!isCallByResume) {
        +				// Queue delay property to recover the current animation.
        +				// Don't add property when delay is called by resume.
        +				addAniProperty("delay", this, null, {duration: t});
        +			}
        +
        +			var self = this;
        +			delayFn.call($(this), time).queue(function(next) {
        +				next();
        +
        +				// Remove delay property when delay has been expired.
        +				removeAniProperty(self);
        +			});
        +		});
        +	};
        +
        +	/**
        +	 * Pauses the animation executed through a call to the jQuery <a href=http://api.jquery.com/animate/>.animate()</a> method.
        +	 * @ko jQuery의<a href=http://api.jquery.com/animate/>animate() 메서드</a>가 실행한 애니메이션을 일시 정지한다
        +	 *
        +	 * @name jQuery#pause
        +	 * @method
        +	 * @support {"ie": "10+", "ch" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
        +	 * @example
        +	 * $("#box").pause(); //paused the current animation
        +	 */
        +	$.fn.pause = function() {
        +		return this.each(function() {
        +			var p;
        +			var type = "fx";
        +
        +			if (getStatus(this) !== "inprogress") {
        +				return;
        +			}
        +
        +			//Clear fx-queue except 1 dummy function
        +			//for promise not to be expired when calling stop()
        +			$.queue(this, type || "fx", [$.noop]);
        +			stopFn.call($(this));
        +
        +			//Remember current animation property
        +			if (p = this.__aniProps[0]) {
        +				p.elapsed += $.now() - p.start;
        +				p.paused = true;
        +			}
        +		});
        +	};
        +
        +	/**
        +	 * Resumes the animation paused through a call to the pause() method.
        +	 * @ko pause() 메서드가 일시 정지한 애니메이션을 다시 실행한다
        +	 *
        +	 * @name jQuery#resume
        +	 * @method
        +	 * @support {"ie": "10+", "ch" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
        +	 * @example
        +	 * $("#box").resume(); //resume the paused animation
        +	 */
        +	$.fn.resume = function() {
        +		return this.each(function() {
        +			var type = "fx";
        +			var p;
        +			var i;
        +
        +			if (getStatus(this) !== "paused") {
        +				return;
        +			}
        +
        +			//Clear fx-queue,
        +			//And this queue will be initialized by animate call.
        +			$.queue(this, type || "fx", []);
        +
        +			// Restore __aniProps
        +			i = 0;
        +			while (p = this.__aniProps[i]) {
        +				// Restore easing status
        +				if (p.elapsed > 0 && p.opt.easing) {
        +					var resumePercent = p.elapsed / p.opt.duration;
        +					var remainPercent = 1 - resumePercent;
        +					var originalEasing = $.easing[p.opt.easing];
        +					var startEasingValue = originalEasing(resumePercent);
        +					var scale = scaler([startEasingValue, 1], [0, 1]);
        +					var newEasingName = p.opt.easing + "_" + p.uuid;
        +
        +					// Make new easing function that continues from pause point.
        +					$.easing[newEasingName] = generateNewEasingFunc(
        +						resumePercent, remainPercent, scale, originalEasing);
        +					p.opt.easing = newEasingName;
        +
        +					//Store new easing function to clear it later.
        +					p.addEasingFn(newEasingName);
        +				}
        +
        +				p.paused = false;
        +				p.opt.duration -= p.elapsed;
        +
        +				// If duration remains, request 'animate' with storing aniProps
        +				if (p.opt.duration > 0 || p.elapsed === 0) {
        +					i === 0 && p.init();
        +
        +					if (p.type === "delay") {
        +						// pass last parameter 'true' not to add an aniProperty.
        +						$(this).delay(p.opt.duration, "fx", true);
        +					} else {
        +						animateFn.call($(this), p.prop, p.opt);
        +					}
        +				}
        +
        +				i++;
        +			}
        +		});
        +	};
        +
        +	/**
        +	 * Generate a new easing function.
        +	 *
        +	 * function to avoid JS Hint error "Don't make functions within a loop"
        +	 */
        +	function generateNewEasingFunc(resumePercent, remainPercent, scale, originalEasing) {
        +		return function easingFunc(percent) {
        +			var newPercent = resumePercent + remainPercent * percent;
        +			return scale(originalEasing(newPercent));
        +		};
        +	}
        +
        +	$.fn.stop = function(type, clearQueue) {
        +		var clearQ = clearQueue;
        +		stopFn.apply(this, arguments);
        +
        +		if (typeof type !== "string") {
        +			clearQ = type;
        +		}
        +
        +		return this.each(function() {
        +			var p;
        +
        +			// When this element was not animated properly, do nothing.
        +			if (getStatus(this) === "empty") {
        +				return;
        +			}
        +
        +			if (!clearQ) {
        +				p = this.__aniProps.shift();
        +				p && p.clearEasingFn();
        +			} else {
        +				//If clearQueue is requested,
        +				//then all properties must be initialized
        +				//for element not to be resumed.
        +				while (p = this.__aniProps.shift()) {
        +					p.clearEasingFn();
        +				}
        +				this.__aniProps = [];
        +			}
        +		});
        +	};
        +
        +	jQuery.expr.filters.paused = function(elem) {
        +		return getStatus(elem) === "paused";
        +	};
        +
        +	//Adopt linear scale from d3
        +	function scaler(domain, range) {
        +		var u = uninterpolateNumber(domain[0], domain[1]);
        +		var i = interpolateNumber(range[0], range[1]);
        +
        +		return function(x) {
        +			return i(u(x));
        +		};
        +	}
        +
        +	function interpolateNumber(a, b) {
        +		a = +a, b = +b;
        +		return function(t) {
        +			return a * (1 - t) + b * t;
        +		};
        +	}
        +
        +	function uninterpolateNumber(a, b) {
        +		b = (b -= a = +a) || 1 / b;
        +		return function(x) {
        +			return (x - a) / b;
        +		};
        +	}
        +});
        +
        +
        +
        + + + + + + + + +
        + + comments powered by Disqus + + + +
        + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:13 GMT+0900 (KST) +
        +
        +
        + + + + + diff --git a/doc/persist.js.html b/doc/persist.js.html new file mode 100644 index 00000000..940db3a8 --- /dev/null +++ b/doc/persist.js.html @@ -0,0 +1,835 @@ + + + + + Source: plugin/persist.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + +
        +

        Source: plugin/persist.js

        + + + + +
        +
        +
        /**
        +* Copyright (c) 2015 NAVER Corp.
        +* egjs projects are licensed under the MIT license
        +*/
        +
        +// jscs:disable maximumLineLength
        +eg.module("persist", ["jQuery", window, document], function($, global, doc) {
        +	"use strict";
        +
        +	// jscs:enable maximumLineLength
        +	var wp = global.performance;
        +	var history = global.history;
        +	var isNeeded = (function() {
        +		var ua = global.navigator.userAgent;
        +		var version = ua ? ua.match(/Android\s([^\;]*)/i) : null;
        +
        +		/*
        +		* a isNeeded value is
        +		*  - iOS: false,
        +		*  - Android 4.4+: true
        +		*  - Android 4.4 and less: false
        +		*/
        +		return !(/iPhone|iPad/.test(ua) || (version ? parseFloat(version.pop()) < 4.4 : true));
        +	})();
        +
        +	var JSON = global.JSON;
        +	var CONST_PERSIST = "___persist___";
        +	var GLOBAL_KEY = "KEY" + CONST_PERSIST;
        +	var $global = $(global);
        +	var isPersisted = $global.attr(CONST_PERSIST) === true;
        +
        +	// In case of IE8, TYPE_BACK_FORWARD is undefined.
        +	var isBackForwardNavigated = (wp && wp.navigation &&
        +									(wp.navigation.type === (wp.navigation.TYPE_BACK_FORWARD || 2)));
        +	var isSupportState = "replaceState" in history && "state" in history;
        +
        +	var storage = (function() {
        +		if (isStorageAvailable(global.sessionStorage)) {
        +			return global.sessionStorage;
        +		} else if (isStorageAvailable(global.localStorage)) {
        +			return global.localStorage;
        +		}
        +	})();
        +
        +	function isStorageAvailable(storage) {
        +		if (!storage) {
        +			return;
        +		}
        +		var TMP_KEY = "__tmp__" + CONST_PERSIST;
        +
        +		try {
        +			// In case of iOS safari private mode, calling setItem on storage throws error
        +			storage.setItem(TMP_KEY, CONST_PERSIST);
        +
        +			// In Chrome incognito mode, can not get saved value
        +			// In IE8, calling storage.getItem occasionally makes "Permission denied" error
        +			return storage.getItem(TMP_KEY) === CONST_PERSIST;
        +		} catch (e) {
        +			return false;
        +		}
        +	}
        +	if (!isSupportState && !storage) {
        +		return;
        +	}
        +
        +	// jscs:disable maximumLineLength
        +	/* jshint ignore:start */
        +	if (!JSON) {
        +		console.warn(
        +		"The JSON object is not supported in your browser.\r\n" +
        +		"For work around use polyfill which can be found at:\r\n" +
        +		"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#Polyfill");
        +		return;
        +	}
        +	/* jshint ignore:end */
        +
        +	// jscs:enable maximumLineLength
        +
        +	function onPageshow(e) {
        +		isPersisted = isPersisted || (e.originalEvent && e.originalEvent.persisted);
        +		if (!isPersisted && isBackForwardNavigated) {
        +			$global.trigger("persist");
        +		} else {
        +			reset();
        +		}
        +	}
        +
        +	/*
        +	 * flush current history state
        +	 */
        +	function reset() {
        +		setState(null);
        +	}
        +	/*
        +	 * Get state value
        +	 */
        +	function getState() {
        +		var state;
        +		var stateStr = storage ?
        +			storage.getItem(global.location.href + CONST_PERSIST) : history.state;
        +
        +		// the storage is clean
        +		if (stateStr === null) {
        +			return {};
        +		}
        +
        +		// "null" is not a valid
        +		var isValidStateStr = typeof stateStr === "string" &&
        +									stateStr.length > 0 && stateStr !== "null";
        +		var isValidType;
        +
        +		try {
        +			state = JSON.parse(stateStr);
        +
        +			// like '[ ... ]', '1', '1.234', '"123"' is also not valid
        +			isValidType = !($.type(state) !== "object" || state instanceof Array);
        +
        +			if (!isValidStateStr || !isValidType) {
        +				throw new Error();
        +			}
        +		} catch (e) {
        +			warnInvalidStorageValue();
        +			state = {};
        +		}
        +
        +		// Note2 (Android 4.3) return value is null
        +		return state;
        +	}
        +
        +	function warnInvalidStorageValue() {
        +		/* jshint ignore:start */
        +		console.warn("window.history or session/localStorage has no valid " +
        +				"format data to be handled in persist.");
        +		/* jshint ignore:end */
        +	}
        +
        +	function getStateByKey(key) {
        +		var result = getState()[key];
        +
        +		// some device returns "null" or undefined
        +		if (result === "null" || typeof result === "undefined") {
        +			result = null;
        +		}
        +		return result;
        +	}
        +	/*
        +	 * Set state value
        +	 */
        +	function setState(state) {
        +		if (storage) {
        +			if (state) {
        +				storage.setItem(
        +					global.location.href + CONST_PERSIST, JSON.stringify(state));
        +			} else {
        +				storage.removeItem(global.location.href  + CONST_PERSIST);
        +			}
        +		} else {
        +			try {
        +				history.replaceState(
        +					state === null ? null : JSON.stringify(state),
        +					doc.title,
        +					global.location.href
        +				);
        +			} catch (e) {
        +				/* jshint ignore:start */
        +				console.warn(e.message);
        +				/* jshint ignore:end */
        +			}
        +		}
        +
        +		state ? $global.attr(CONST_PERSIST, true) : $global.attr(CONST_PERSIST, null);
        +	}
        +
        +	function setStateByKey(key, data) {
        +		var beforeData = getState();
        +		beforeData[key] = data;
        +		setState(beforeData);
        +	}
        +	/**
        +	* Stores the current state of the web page in a default key using JSON.
        +	* @ko 웹 페이지의 현재 상태를 기본 키에 JSON 형식으로 저장한다.
        +	* @method jQuery.persist
        +	* @deprecated since version 1.2.0
        +	* @support {"ie": "9+", "ch" : "latest", "ff" : "1.5+",  "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.2+ (except 3.x)"}
        +	* @param {Object} state The state information of the web page written in JSON <ko>JSON 객체로 정의한 웹 페이지의 상태 정보</ko>
        +	* @example
        +	$("a").on("click",function(e){
        +		e.preventdefault();
        +		// save state
        +		$.persist(state);
        +	});
        +	*/
        +	/**
        +	* Return stored state in global namespace as object
        +	* @ko 디폴트 키에 저장된 상태를 반환한다.
        +`	* @method jQuery.persist
        +	* @deprecated since version 1.2.0
        +	* @return {Object}
        +	* @example
        +	$("a").on("click",function(e){
        +		e.preventdefault();
        +		// get state
        +		var state = $.persist();
        +	});
        +	*/
        +	/**
        +	* Stores the current state of the web page using JSON.
        +	* @ko 웹 페이지의 현재 상태를 JSON 형식으로 저장한다
        +	* @method jQuery.persist
        +    * @param {String} key The key of the state information to be stored <ko>저장할 상태 정보의 키</ko>
        +    * @param {Object} state The value to be stored in a given key<ko>키에 저장할 값</ko>
        +	* @example
        +	$("a").on("click",function(e){
        +		e.preventdefault();
        +		// save state
        +		$.persist("KEY",state);
        +	});
        +	*/
        +	/**
        +	* Returns the state of stored web pages.
        +	* @ko 저장된 웹 페이지의 상태를 반환한다
        +	* @method jQuery.persist
        +	* @param {String} key The name of the key to be checked<ko>값을 확인할 키의 이름</ko>
        +	* @return {Object} The value of the key <ko>키의 값</ko>
        +	* @example
        +	$("a").on("click",function(e){
        +		e.preventdefault();
        +		// get state
        +		var state = $.persist("KEY");
        +	});
        +	*/
        +	$.persist = function(state) {
        +		var key;
        +		var data;
        +		if (typeof state === "string") {
        +			key = state;
        +			data = arguments.length === 2 ? arguments[1] : null;
        +		} else {
        +			key = GLOBAL_KEY;
        +			data = arguments.length === 1 ? state : null;
        +		}
        +		data && setStateByKey(key, data);
        +		return getStateByKey(key);
        +	};
        +
        +	/**
        +	* Return whether you need "Persist" module by checking the bfCache support of the current browser
        +	* @ko 현재 브라우저의 bfCache 지원여부에 따라 persist 모듈의 필요여부를 반환한다.
        +	* @method $.persist.isApplicable
        +	* @example
        +	$.persist.isApplicable();
        +	*/
        +	$.persist.isNeeded = function() {
        +		return isNeeded;
        +	};
        +
        +	// in case of reload
        +	!isBackForwardNavigated && reset();
        +
        +	$.event.special.persist = {
        +		setup: function() {
        +			$global.on("pageshow", onPageshow);
        +		},
        +		teardown: function() {
        +			$global.off("pageshow", onPageshow);
        +		},
        +		trigger: function(e) {
        +			//If you use 'persist' event, you can get global-key only!
        +			e.state = getStateByKey(GLOBAL_KEY);
        +		}
        +	};
        +	return {
        +		"isBackForwardNavigated": isBackForwardNavigated,
        +		"onPageshow": onPageshow,
        +		"reset": reset,
        +		"getState": getState,
        +		"setState": setState,
        +		"GLOBALKEY": GLOBAL_KEY
        +	};
        +});
        +
        +
        + + + + + + + + +
        + + comments powered by Disqus + + + +
        + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:13 GMT+0900 (KST) +
        +
        +
        + + + + + diff --git a/doc/rotate.js.html b/doc/rotate.js.html new file mode 100644 index 00000000..00d0ba08 --- /dev/null +++ b/doc/rotate.js.html @@ -0,0 +1,748 @@ + + + + + Source: customEvent/rotate.js | egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + +
        +

        Source: customEvent/rotate.js

        + + + + +
        +
        +
        /**
        +* Copyright (c) 2015 NAVER Corp.
        +* egjs projects are licensed under the MIT license
        +*/
        +
        +// jscs:disable maximumLineLength
        +eg.module("rotate", ["jQuery", eg, window, document], function($, ns, global, doc) {
        +	"use strict";
        +
        +	// jscs:enable maximumLineLength
        +	/**
        +	 * @namespace jQuery
        +	 * @group jQuery Extension
        +	 */
        +	/**
        +	 * This jQuery custom event is fired when device rotates.
        +	 *
        +	 * @ko 기기가 회전할 때 발생하는 jQuery 커스텀 이벤트
        +	 * @name jQuery#rotate
        +	 * @event
        +	 * @param {Event} e The Event object in jQuery<ko>jQuery의 Event 객체</ko>
        +	 * @param {Object} info The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
        +	 * @param {Boolean} info.isVertical The orientation of the device (true: portrait, false: landscape) <ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)</ko>
        +	 * @support { "ios" : "7+", "an" : "2.1+ (except 3.x)"}
        +	 * @example
        +	 * $(window).on("rotate",function(e, info){
        +	 *      info.isVertical;
        +	 * });
        +	 *
        +	 */
        +
        +	var beforeScreenWidth = -1;
        +	var beforeVertical = null;
        +	var rotateTimer = null;
        +	var agent = ns.agent();
        +	var isMobile = /android|ios/.test(agent.os.name);
        +
        +	if (!isMobile) {
        +		ns.isPortrait = function() {
        +			return;
        +		};
        +
        +		return;
        +	}
        +
        +	/**
        +	 * Return event name string for orientationChange according browser support
        +	 */
        +	var orientationChange = function() {
        +		var type;
        +		/**
        +		 * Some platform/broswer returns previous widht/height state value. For workaround, give some delays.
        +		 *
        +		 * Android bug:
        +		 * - Andorid 2.3 - Has orientationchange with bug. Needs 500ms delay.
        +		 *
        +		 *   Note: Samsung's branded Android 2.3
        +		 *   When check orientationchange using resize event, could cause browser crash if user binds resize event on window
        +		 *
        +		 * - Android 2.2 - orientationchange fires twice(at first time width/height are not updated, but second returns well)
        +		 * - Lower than 2.2 - use resize event
        +		 *
        +		 * InApp bug:
        +		 * - Set 200ms delay
        +		 */
        +		if ((agent.os.name === "android" && agent.os.version === "2.1")) {//|| htInfo.galaxyTab2)
        +			type = "resize";
        +		} else {
        +			type = "onorientationchange" in global ? "orientationchange" : "resize";
        +		}
        +
        +		orientationChange = function() {
        +			return type;
        +		};
        +		return type;
        +
        +	};
        +	/**
        +	* When viewport orientation is portrait, return true otherwise false
        +	*/
        +	function isVertical() {
        +		var eventName = orientationChange();
        +		var screenWidth;
        +		var degree;
        +		var vertical;
        +
        +		if (eventName === "resize") {
        +			screenWidth = doc.documentElement.clientWidth;
        +
        +			if (beforeScreenWidth === -1) { //first call isVertical
        +				vertical = screenWidth < doc.documentElement.clientHeight;
        +			} else {
        +				if (screenWidth < beforeScreenWidth) {
        +					vertical = true;
        +				} else if (screenWidth === beforeScreenWidth) {
        +					vertical = beforeVertical;
        +				} else {
        +					vertical = false;
        +				}
        +			}
        +		} else {
        +			degree = global.orientation;
        +			if (degree === 0 || degree === 180) {
        +				vertical = true;
        +			} else if (degree === 90 || degree === -90) {
        +				vertical = false;
        +			}
        +		}
        +		return vertical;
        +	}
        +
        +	/**
        +	* Trigger rotate event
        +	*/
        +	function triggerRotate() {
        +
        +		var currentVertical = isVertical();
        +		if (isMobile) {
        +			if (beforeVertical !== currentVertical) {
        +				beforeVertical = currentVertical;
        +				beforeScreenWidth = doc.documentElement.clientWidth;
        +				$(global).trigger("rotate", {
        +					isVertical: beforeVertical
        +				});
        +			}
        +		}
        +	}
        +
        +	/**
        +	* Trigger event handler
        +	*/
        +	function handler(e) {
        +
        +		var eventName = orientationChange();
        +		var delay;
        +		var screenWidth;
        +
        +		if (eventName === "resize") {
        +			global.setTimeout(function() {
        +				triggerRotate();
        +			}, 0);
        +		} else {
        +			delay = 300;
        +			if (agent.os.name === "android") {
        +				screenWidth = doc.documentElement.clientWidth;
        +				if (e.type === "orientationchange" && screenWidth === beforeScreenWidth) {
        +					global.setTimeout(function() {
        +						handler(e);
        +					}, 500);
        +
        +					// When width value wasn't changed after firing orientationchange, then call handler again after 300ms.
        +					return false;
        +				}
        +			}
        +
        +			global.clearTimeout(rotateTimer);
        +			rotateTimer = global.setTimeout(function() {
        +				triggerRotate();
        +			}, delay);
        +		}
        +	}
        +
        +	$.event.special.rotate = {
        +		setup: function() {
        +			beforeVertical = isVertical();
        +			beforeScreenWidth = doc.documentElement.clientWidth;
        +			$(global).on(orientationChange(), handler);
        +		},
        +		teardown: function() {
        +			$(global).off(orientationChange(), handler);
        +		},
        +		trigger: function(e) {
        +			e.isVertical = beforeVertical;
        +		}
        +	};
        +
        +	/**
        +	 * Checks whether the current orientation of the device is portrait.
        +	 * @ko 기기의 화면이 수직 방향인지 확인한다
        +	 * @method eg#isPortrait
        +	 * @return {Boolean} The orientation of the device (true: portrait, false: landscape) <ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)</ko>
        +	 * @example
        +eg.isPortrait();  // Check if device is in portrait mode
        +	*/
        +	ns.isPortrait = isVertical;
        +
        +	return {
        +		"orientationChange": orientationChange,
        +		"isVertical": isVertical,
        +		"triggerRotate": triggerRotate,
        +		"handler": handler
        +	};
        +});
        +
        +
        + + + + + + + + +
        + + comments powered by Disqus + + + +
        + Documentation generated by JSDoc 3.2.2 on Tue Sep 20 2016 14:54:15 GMT+0900 (KST) +
        +
        +
        + + + + + diff --git a/doc/scripts/bootstrap.min.js b/doc/scripts/bootstrap.min.js new file mode 100644 index 00000000..1a6258ef --- /dev/null +++ b/doc/scripts/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.0.3 (http://getbootstrap.com) + * Copyright 2013 Twitter, Inc. + * Licensed under http://www.apache.org/licenses/LICENSE-2.0 + */ + +if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]'),b=!0;if(a.length){var c=this.$element.find("input");"radio"===c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?b=!1:a.find(".active").removeClass("active")),b&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}b&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/doc/scripts/jquery.min.js b/doc/scripts/jquery.min.js new file mode 100644 index 00000000..9a85bd34 --- /dev/null +++ b/doc/scripts/jquery.min.js @@ -0,0 +1,6 @@ +/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery.min.map +*/ +(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
        ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) +};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
        "],col:[2,"","
        "],tr:[2,"","
        "],td:[3,"","
        "],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("