diff --git a/.gitignore b/.gitignore index 7c79088..3463f02 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,6 @@ report temp *.log *.iml -doc -.idea/ -dist browserstack-run.pid config/browertstack.config.json +.idea/ \ No newline at end of file diff --git a/bower.json b/bower.json index bfe55a0..740db9c 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "egjs", - "version": "1.0.0-snapshot", + "version": "1.1.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 0000000..13d25ec --- /dev/null +++ b/dist/eg.js @@ -0,0 +1,5609 @@ +/** +* 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.1.0 +* @SHA-1 fb4a69e (1.1.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/" + }, + "Outlayer": { + "url": "https://github.com/metafizzy/outlayer/" + } + }; + + // 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._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("eg", ["jQuery", eg, window], function($, ns, global) { +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 version infomation + * @ko 버전 정보 + */ + ns.VERSION = "1.1.0"; + ns.hook = { + // isHWAccelerable : null, + // isTransitional : null, + // agent : null + }; + /** + * Get browser agent information + * + * @ko Agent 정보를 반환한다. 값은 캐싱된다. + * @method eg#agent + * @return {Object} agent + * @return {String} agent.os os infomation os 정보 객체 + * @return {String} agent.os.name os name (android, ios, window, mac) os 이름 (android, ios, window, mac) + * @return {String} agent.os.version os version os 버전 + * @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 check whether browser is webview 웹뷰 브라우저 여부 + * @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; +} +} + */ + /* + * {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 UAParser = { + getBrowserName: function(browserRules) { + return this.getIdentityStringFromArray( + browserRules, + userAgentRules.defaultString.browser + ); + }, + getBrowserVersion: function(browserName) { + var browserVersion; + var versionToken; + + if (!browserName) { + return; + } + + versionToken = + this.getBrowserRule(browserName).versionSearch || browserName; + + browserVersion = this.extractBrowserVersion(versionToken, this.ua); + + return browserVersion; + }, + extractBrowserVersion: function(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; + }, + getOSName: function(osRules) { + return this.getIdentityStringFromArray( + osRules, + userAgentRules.defaultString.os + ); + }, + getOSVersion: function(osName) { + var ua = this.ua; + var osRule = this.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; + }, + getOSRule: function(osName) { + return this.getRule(userAgentRules.os, osName); + }, + getBrowserRule: function(browserName) { + return this.getRule(userAgentRules.browser, browserName); + }, + getRule: function(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 && this.isMatched(this.ua, criteria) : + identityMatched) { + return rule; + } + } + }, + getIdentityStringFromArray: function(rules, defaultStrings) { + for (var i = 0, rule; rule = rules[i]; i++) { + if (this.isMatched(this.ua, rule.criteria)) { + return rule.identity || defaultStrings.name; + } + } + return defaultStrings.name; + }, + isMatched: function(base, target) { + return target && + target.test ? !!target.test(base) : base.indexOf(target) > -1; + }, + isWebview: function() { + var ua = this.ua; + var webviewRules = userAgentRules.webview; + var isWebview = false; + var browserVersion; + + for (var i = 0, rule; rule = webviewRules[i]; i++) { + if (!this.isMatched(ua, rule.criteria)) { + continue; + } + + browserVersion = + this.extractBrowserVersion(rule.browserVersionSearch, ua); + + if (this.isMatched(ua, rule.webviewToken) || + this.isMatched(browserVersion, rule.webviewBrowserVersion)) { + isWebview = true; + break; + } + } + + return isWebview; + } + }; + + UAParser.create = function(useragent) { + UAParser.ua = useragent; + var agent = { + os: {}, + browser: {} + }; + + agent.browser.name = UAParser.getBrowserName(userAgentRules.browser); + agent.browser.version = UAParser.getBrowserVersion(agent.browser.name); + agent.os.name = UAParser.getOSName(userAgentRules.os); + agent.os.version = UAParser.getOSVersion(agent.os.name); + agent.browser.webview = UAParser.isWebview(); + + agent.browser.name = agent.browser.name.toLowerCase(); + agent.os.name = agent.os.name.toLowerCase(); + + return agent; + }; + + ns.agent = function() { + var info = UAParser.create(global.navigator.userAgent); + return resultCache(this, "agent", [info], info); + }; + + /** + * Get a translate string + * + * @ko translate 문자를 반환한다. + * @method eg#translate + * @param {String} x x-coordinate x 좌표 + * @param {String} y y-coordinate y 좌표 + * @param {Boolean} [isHA] isHWAccelerable 하드웨어 가속 여부 + * @return {String} + * @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)" : + ")"); + }; + + /** + * Check hardware acceleration support + * + * @ko 해당 기기에서 하드웨어 가속을 할 수 있다면 true을 반환하며, 값은 캐싱된다. + * @method eg#isHWAccelerable + * @return {Boolean} + * @example +eg.isHWAccelerable(); // Returns 'true' when supports hardware acceleration + +// 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 = (UAParser.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); + }; + + /** + * Check CSS transition support + * + * @ko 해당 기기에서 css transtion을 할 수 있다면 true을 반환하며, 값은 캐싱된다. + * @method eg#isTransitional + * @return {Boolean} + * @example +eg.isTransitional(); // Returns 'true' when supports CSS transition + +// 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/.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 = browser.indexOf("safari") !== -1 || + (browser.indexOf("ie") !== -1 && + parseInt(agent.browser.nativeVersion, 10) >= 10); + break; + default : + result = /chrome|firefox|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); + }; + + /* + * requestAnimationFrame polyfill + * @ko requestAnimationFrame 폴리필 + * @method eg#requestAnimationFrame + * @param {Function} timer function + * @return {Number} key + * @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); + }; + /* + * cancelAnimationFrame polyfill + * @ko cancelAnimationFrame 폴리필 + * @method eg#cancelAnimationFrame + * @param {Number} key + * @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) { +/** + * + * The Class object is used to implement object-oriented style programming + * @group egjs + * @ko Class는 어플리케이션을 객체지향 프로그래밍 방식으로 구현하는데 사용합니다. + * @class + * @name eg.Class + * + * @support {"ie": "7+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * @param {Object} def Class definition of object literal type. 리터럴 형태의 클래스 정의부 + * @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; + + /** + * Retrun instance itself. + * @ko 자신의 인스턴스를 반환한다. + * @method eg.Class#instance + * @return {eg.Class} instance of itself자신의 인스턴스 + */ + typeClass.prototype.instance = function() { + return this; + }; + + typeClass.prototype.constructor = typeClass; + return typeClass; + }; + /** + * Extends class + * @ko extend는 Class를 상속할 때 사용합니다. + * @static + * @method eg.Class.extend + * @param {eg.Class} oSuperClass Super class. 상속하려는 클래스 + * @param {Object} def Class definition of object literal type. 리터럴 형태의 클래스 정의부 + * @return {eg.Class} instance of new eg.Class 새로 생성된 eg.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) { +/** + * Component + * @class + * @group egjs + * @name eg.Component + * + * @support {"ie": "7+", "ch" : "latest", "ff" : "latest", "sf" : "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 = {}; + }, + /** + * Get or set option. + * @ko 옵션을 관리한다. + * @method eg.Component#option + * @param {String} key + * @param {Object} value + * @return {eg.Component|Object} (set)instance of itself or (get)option value (set)자신의 인스턴스 혹은 (get)option 값 + * @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; + }, + /** + * Trigger custom event. + * @ko 커스텀 이벤트를 실행합니다. + * @method eg.Component#trigger + * @param {String} eventName + * @param {Object} customEvent + * @return {Boolean} + * @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; + }, + /** + * Check whether the event has been registered in component. + * @ko 컴포넌트에 등록된 이벤트를 확인합니다. + * @method eg.Component#hasOn + * @param {String} eventName + * @return {Boolean} + * @example + var Some = eg.Class.extend(eg.Component,{ + "some": function(){ + this.hasOn("hi");// check hi event. + } + }); + */ + hasOn: function(eventName) { + return !!this.eventHandler[eventName]; + }, + /** + * Attach an event handler function. + * @ko 이벤트를 등록합니다. + * @method eg.Component#on + * @param {eventName} eventName + * @param {Function} handlerToAttach + * @return {eg.Component} instance of 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; + }, + /** + * Detach an event handler function. + * @ko 이벤트를 해제합니다. + * @method eg.Component#off + * @param {eventName} eventName + * @param {Function} handlerToDetach + * @return {eg.Component} instance of 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 + */ + /** + * Add rotate event support in jQuery + * + * @ko jQuery custom rotate 이벤트 지원 + * @name jQuery#rotate + * @event + * @param {Event} e event + * @param {Boolean} e.isVertical vertical 수직여부 + * @support { "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * @example + * $(window).on("rotate",function(e){ + * e.isVertical; + * }); + * + */ + + var beforeScreenWidth = -1; + var beforeVertical = null; + var rotateTimer = null; + var agent = ns.agent(); + var isMobile = /android|ios/.test(agent.os.name); + + /** + * 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; + } + } + + beforeScreenWidth = screenWidth; + } 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; + $(global).trigger("rotate"); + } + } + } + + /** + * 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; + } + beforeScreenWidth = screenWidth; + } + + 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; + } + }; + + /** + * Check if device is in portrait mode + * @ko 해당 기기가 portait(수직방향) 모드일 경우, true을 반환한다. + * @method eg#isPortrait + * @return {Boolean} + * @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 + /** + * Add scrollEnd event support in jQuery + * @ko jQuery custom scrollEnd 이벤트 지원 + * @name jQuery#scrollEnd + * @event + * @param {Number} e.top top position 상단(top) 위치 값 + * @param {Number} e.left left position 왼쪽(left) 위치 값 + * @support {"ie": "9+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * @example + * $(window).on("scrollend",function(e){ + * e.top; + * e.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; + + // Browsers that trigger scroll event like scrollstop : SCROLLBASE + if (osInfo.name === "ios") { + + // webview : TIMERBASE + if (browserInfo.webview === true) { + retValue = TIMERBASE; + } else if (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 +*/ + +eg.module("animate", ["jQuery", window], function($, global) { +/** + * Extends jQuery animate in order to use 'transform' property + * @ko jQuery animate 사용시 transform을 사용할 수 있도록 확장한 animate 메소드 + * @name jQuery#animate + * @method + * @param {Object} properties An object of CSS properties and values that the animation will move toward. 애니메이션 할 CSS 속성과 값으로 구성된 오브젝트 + * @param {Number|String} [duration=4000] A string or number determining how long the animation will run. 애니메이션 진행 시간 + * @param {String} [easing="swing"] A string indicating which easing function to use for the transition. transition에 사용할 easing 함수명 + * @param {Function} [complete] A function to call 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", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + */ + var supportFloat32Array = "Float32Array" in window; + var CSSMatrix = global.WebKitCSSMatrix || global.MSCSSMatrix || + global.OCSSMatrix || global.MozMatrix || global.CSSMatrix; + + /** + * Utility functions : matrix and toRadian is copied from transform2d + * turns a transform string into its "matrix(A, B, C, D, X, Y)" form (as an array, though) + */ + function matrix(transform) { + transform = transform.split(")"); + var trim = $.trim; + var i = -1; + + // last element of the array is an empty string, get rid of it + var l = transform.length - 1; + var split; + var prop; + var val; + var prev = supportFloat32Array ? new Float32Array(6) : []; + var curr = supportFloat32Array ? new Float32Array(6) : []; + var rslt = supportFloat32Array ? new Float32Array(6) : [1, 0, 0, 1, 0, 0]; + + prev[0] = prev[3] = rslt[0] = rslt[3] = 1; + prev[1] = prev[2] = prev[4] = prev[5] = 0; + + // Loop through the transform properties, parse and multiply them + while (++i < l) { + split = transform[i].split("("); + prop = trim(split[0]); + val = split[1]; + curr[0] = curr[3] = 1; + curr[1] = curr[2] = curr[4] = curr[5] = 0; + + switch (prop) { + case "translateX": + curr[4] = parseInt(val, 10); + break; + + case "translateY": + curr[5] = parseInt(val, 10); + break; + + case "translate": + val = val.split(","); + curr[4] = parseInt(val[0], 10); + curr[5] = parseInt(val[1] || 0, 10); + break; + + case "rotate": + val = toRadian(val); + curr[0] = Math.cos(val); + curr[1] = Math.sin(val); + curr[2] = -Math.sin(val); + curr[3] = Math.cos(val); + break; + + case "scaleX": + curr[0] = +val; + break; + + case "scaleY": + curr[3] = val; + break; + + case "scale": + val = val.split(","); + curr[0] = val[0]; + curr[3] = val.length > 1 ? val[1] : val[0]; + break; + + case "skewX": + curr[2] = Math.tan(toRadian(val)); + break; + + case "skewY": + curr[1] = Math.tan(toRadian(val)); + break; + + case "matrix": + val = val.split(","); + curr[0] = val[0]; + curr[1] = val[1]; + curr[2] = val[2]; + curr[3] = val[3]; + curr[4] = parseInt(val[4], 10); + curr[5] = parseInt(val[5], 10); + break; + } + + // Matrix product (array in column-major order) + rslt[0] = prev[0] * curr[0] + prev[2] * curr[1]; + rslt[1] = prev[1] * curr[0] + prev[3] * curr[1]; + rslt[2] = prev[0] * curr[2] + prev[2] * curr[3]; + rslt[3] = prev[1] * curr[2] + prev[3] * curr[3]; + rslt[4] = prev[0] * curr[4] + prev[2] * curr[5] + prev[4]; + rslt[5] = prev[1] * curr[4] + prev[3] * curr[5] + prev[5]; + + prev = [rslt[0],rslt[1],rslt[2],rslt[3],rslt[4],rslt[5]]; + } + return rslt; + } + + // converts an angle string in any unit to a radian Float + function toRadian(value) { + return ~value.indexOf("deg") ? + parseInt(value, 10) * (Math.PI * 2 / 360) : + ~value.indexOf("grad") ? + parseInt(value, 10) * (Math.PI / 200) : + parseFloat(value); + } + + /** + * 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[2]}; + } + } + + function getTransformGenerateFunction(transform) { + var splitted = transform.split(")"); + var 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] === "scale") { + defaultVal = 1; + } + + 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; + + // 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 = toMatrix(startTf); + end = toMatrix(endTf); + + //If the type of matrix is not equal, then match to matrix3d + if (start[1].length < end[1].length) { + start = toMatrix3d(start); + } else if (start[1].length > end[1].length) { + end = toMatrix3d(end); + } + } + + return function(pos) { + var result = []; + var ret = ""; + + if (isRelative) { + // This means a muliply between a matrix and a transform. + ret = start + end(pos); + return ret; + } + + if (pos === 1) { + ret = data2String(end); + } else { + for (var i = 0, s, e, l = start[1].length; i < l; i++) { + s = parseFloat(start[1][i]); + e = parseFloat(end[1][i]); + result.push(s + (e - s) * pos); + } + + ret = data2String([start[0], result]); + } + + return ret; + }; + } + + /** + * ["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; + } + + function toMatrix(transform) { + var retMatrix = []; + + if (!transform || transform === "none") { + return ["matrix", [ "1", "0", "0", "1", "0", "0"] ]; + } + + retMatrix = CSSMatrix ? parseStyle(new CSSMatrix(transform).toString()) : + ["matrix", matrix(transform)]; + + /** + * Make an unintended 2d matrix to 3d matrix. + * + * WebkitCSSMatrix changes 'transform3d' style to '2d matix' if it is judged as needless. + * But generally, Developers would intend 3d transform by force for a HW Accelation. eg. translate3d(a, b, 0) + */ + if (transform.indexOf("3d") >= 0 && retMatrix[0].indexOf("3d") < 0) { + retMatrix = toMatrix3d(retMatrix); + } + + return retMatrix; + } + + 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: toMatrix, + toMatrix3d: toMatrix3d + }; +}); + +/** +* Copyright (c) 2015 NAVER Corp. +* egjs projects are licensed under the MIT license +*/ + +eg.module("css", ["jQuery", document], function($, doc) { +/** + * Apply css prefix cssHooks + * @ko css prefix cssHooks 적용 + * + * @name jQuery#css + * @method + * + * * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "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 + if ($.fn && $.fn.jquery && $.fn.jquery.replace(/\./, "") >= "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 +*/ + +// jscs:disable maximumLineLength +eg.module("persist", ["jQuery", eg, window, document], function($, ns, global, doc) { +// jscs:enable maximumLineLength + var wp = global.performance; + var history = global.history; + var location = global.location; + var userAgent = global.navigator.userAgent; + 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 (!isSupportState) { + if ("sessionStorage" in global) { + var tmpKey = "__tmp__" + CONST_PERSIST; + sessionStorage.setItem(tmpKey, CONST_PERSIST); + return sessionStorage.getItem(tmpKey) === CONST_PERSIST ? + sessionStorage : + localStorage; + } else { + return global.localStorage; + } + } + })(); + + // jscs:disable maximumLineLength + /* jshint ignore:start */ + if (!isSupportState && !storage || + (!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 stateStr; + var state = {}; + var isValidStateStr = false; + + if (isSupportState) { + stateStr = history.state; + + // "null" is not a valid + isValidStateStr = typeof stateStr === "string" && stateStr !== "null"; + } else { + stateStr = storage.getItem(location.href + CONST_PERSIST); + isValidStateStr = stateStr && stateStr.length > 0; + } + + if (isValidStateStr) { + try { + state = JSON.parse(stateStr); + + // like '[ ... ]', '1', '1.234', '"123"' is also not valid + if (jQuery.type(state) !== "object" || state instanceof Array) { + throw new Error(); + } + } catch (e) { + /* jshint ignore:start */ + console.warn("window.history or session/localStorage has no valid " + + "format data to be handled in persist."); + /* jshint ignore:end */ + } + } + + // Note2 (Android 4.3) return value is null + return state; + } + + 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 (isSupportState) { + try { + history.replaceState( + state === null ? null : JSON.stringify(state), + doc.title, + location.href + ); + } catch (e) { + /* jshint ignore:start */ + console.warn(e.message); + /* jshint ignore:end */ + } + } else { + if (state) { + storage.setItem(location.href + CONST_PERSIST, JSON.stringify(state)); + } else { + storage.removeItem(location.href + CONST_PERSIST); + } + } + state ? $global.attr(CONST_PERSIST, true) : $global.attr(CONST_PERSIST, null); + } + + function setStateByKey(key, data) { + var beforeData = getState(); + beforeData[key] = data; + setState(beforeData); + } + + /** + * Save current state + * @ko 인자로 넘긴 현재 상태정보를 저장한다. + * @method jQuery.persist + * @support {"ie": "9+", "ch" : "latest", "ff" : "1.5+", "sf" : "latest", "ios" : "7+", "an" : "2.2+ (except 3.x)"} + * @param {Object} state State object to be stored in order to restore UI component's state UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체 + * @example + $("a").on("click",function(e){ + e.preventdefault(); + // save state + $.persist(state); + }); + */ + /** + * Return current state + * @ko 인자로 넘긴 현재 상태정보를 반환한다. + * @method jQuery.persist + * @return {Object} state Stored state object 복원을 위해 저장되어있는 상태 객체 + * @example + $("a").on("click",function(e){ + e.preventdefault(); + // get state + var state = $.persist(); + }); + */ + /** + * Save current state + * @ko 인자로 넘긴 현재 상태정보를 저장한다. + * @method jQuery.persist + * @param {String} key State key to be stored in order to restore UI component's state UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키 + * @param {String} state State object to be stored in order to restore UI component's state UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체 + * @return {Object} state Stored state object 복원을 위해 저장되어있는 상태 객체 + * @example + $("a").on("click",function(e){ + e.preventdefault(); + // save state + $.persist("KEY",state); + }); + */ + /** + * Return current state + * @ko 인자로 넘긴 현재 상태정보를 반환한다. + * @method jQuery.persist + * @param {String} key State key to be stored in order to restore UI component's state UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키 + * @return {Object} state Stored state object 복원을 위해 저장되어있는 상태 객체 + * @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 persist needs by checking bfCache support + * @ko Persist 동작 필요여부를 반환한다. + * @method $.persist.isApplicable + * @example + $.persist.isApplicable(); + */ + $.persist.isNeeded = function() { + var agentOs = ns.agent(userAgent).os; + var isNeeded = true; + if (agentOs.name === "ios" || + (agentOs.name === "android" && parseFloat(agentOs.version) < 4.4)) { + isNeeded = false; + } + $.persist.isNeeded = function() { + return isNeeded; + }; + 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, + "persist": $.persist, + "isNeeded": $.persist.isNeeded, + "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) { +/** + * Check element's visible state within viewport, regardless scroll position + * @ko scroll 위치와 상관없이 특정 엘리먼트나 viewport 안에 엘리먼트가 보이는지 확인한다. + * @class + * @name eg.Visible + * @extends eg.Component + * @group egjs + * + * @param {HTMLElement|String|jQuery} [element=document] The parent element that to check targets (wrapper is only one.) 확인할 영역의 상위 엘리먼트 + * @param {Object} options + * @param {String} [options.targetClass="check_visible"] A class name of targets 확인할 엘리먼트가 가진 클래스명 + * @param {Number} [options.expandSize=0] expand size of the wrapper. + * e.g. If a wrapper size is 100 x 100 and 'expandSize' option is 20, visible range is 120 x 120 + * 상위 엘리먼트 기준으로 추가적인 영역을 확인하도록 지정 + * @support {"ie": "7+", "ch" : "latest", "ff" : "latest", "sf" : "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(); + }, + /** + * Update targets + * @ko target들을 갱신한다. + * @method eg.Visible#refresh + * @return {eg.Visible} instance of itself자신의 인스턴스 + * + * @remark + * If targets was added or removed, must be called to refresh + * 확인 대상이 영역 안에 추가 된 경우, 또는 확인 대상이 영역 안에서 삭제 된 경우, 영역 내의 확인 대상을 이 메소드를 호출하여 갱신해야한다. + */ + 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 if the target elements has been changed. + * @ko target들이 변경했는지 확인한다. + * @method eg.Visible#check + * @param {Number} [delay=-1] Delay time in milliseconds 호출 후, 일정 시간이 지난 후에 확인하고자 할때 사용한다. + * @return {eg.Visible} instance of 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); + } + } + /** + * Trigger when the target elements are visible or hidden based on the base area. + * @ko 기준 영역을 기준으로 보이는 엘리먼트와 사라진 엘리먼트가 변경된 경우 발생하는 이벤트 + * @name eg.Visible#change + * @event + * @param {Array} visible The visible elements (the element type is `HTMLElement`) 보여지게 된 엘리먼트들 + * @param {Array} invisible The 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; + } + }); +}); +/** + * Visible in jQuery plugin + * + * @ko Visible in jQuery plugin + * @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 + */ +/** + * visible:change jQuery event plugin + * + * @ko visible:change jQuery 이벤트 plugin + * @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 + // It is scheduled to be removed in case of build process. + // ns.__checkLibrary__( !("Hammer" in window), "You must download Hammerjs. (http://hammerjs.github.io/)\n\ne.g. bower install hammerjs"); + // ns.__checkLibrary__( !("easeOutQuint" in $.easing), "You must download jQuery Easing Plugin(http://gsgd.co.uk/sandbox/jquery/easing/)\n\ne.g. bower install jquery.easing"); + /** + * Easily get computed coordinate values according user actions. + * @group egjs + * @ko MovableCoord는 사용자 행동에 의해, 좌표계를 제어할 수 있다. + * @class + * @name eg.MovableCoord + * @extends eg.Component + * + * @param {Object} options + * @param {Array} options.min The minimum coordinate 좌표계의 최소값 + * @param {Number} [options.min.0=0] The minimum x-coordinate 최소 X좌표 + * @param {Number} [options.min.1=0] The minimum y-coordinate 최소 Y좌표 + * + * @param {Array} options.max The maximum coordinate 좌표계의 최대값 + * @param {Number} [options.max.0=100] The maximum x-coordinate 최대 X좌표 + * @param {Number} [options.max.1=100] The maximum y-coordinate 최대 Y좌표 + * + * @param {Array} options.bounce The area can move using animation. 바운스: 애니메이션에 의해 이동할 수 있는 영역 + * @param {Boolean} [options.bounce.0=10] The bounce top range top 바우스 영역 + * @param {Boolean} [options.bounce.1=10] The bounce right range right 바우스 영역 + * @param {Boolean} [options.bounce.2=10] The bounce bottom range bottom 바우스 영역 + * @param {Boolean} [options.bounce.3=10] The bounce left range left 바우스 영역 + * + * @param {Array} options.margin The area can move using user's action. 영역별 마진 영역: 사용자의 액션에 의해, 추가로 이동할수 있는 영역 + * @param {Boolean} [options.margin.0=0] The margin top range top 마진 영역 + * @param {Boolean} [options.margin.1=0] The margin right range right 마진 영역 + * @param {Boolean} [options.margin.2=0] The margin bottom range bottom 마진 영역 + * @param {Boolean} [options.margin.3=0] The margin left range left 마진 영역 + * @param {Array} options.circular 영역별 순환 여부 + * @param {Boolean} [options.circular.0=false] The circular top range top 순환 영역 + * @param {Boolean} [options.circular.1=false] The circular right range right 순환 영역 + * @param {Boolean} [options.circular.2=false] The circular bottom range bottom 순환 영역 + * @param {Boolean} [options.circular.3=false] The circular left range left 순환 영역 + * + * @param {Function} [options.easing=easing.easeOutCubic] Function of the Easing (jQuery UI Easing, jQuery Easing Plugin). Easing 함수 + * @param {Number} [options.maximumDuration=Infinity] The maximum duration. 최대 좌표 이동 시간 + * @param {Number} [options.deceleration=0.0006] deceleration This value can be altered to change the momentum animation duration. higher numbers make the animation shorter. 감속계수. 높을값이 주어질수록 애니메이션의 동작 시간이 짧아진다. + * @see Hammerjs {@link http://hammerjs.github.io} + * @see There is usability issue due to default CSS properties ({@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}) settings from Hammerjs. movableCoord removes that settings to fix. + * Hammerjs의 기본 CSS 속성({@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}) 으로 인해 사용성 이슈가 있다. 따라서, movableCoord는 hammerjs의 기본 CSS 속성을 제거하였다. + * + * @codepen {"id":"bdVybg", "ko":"MovableCoord 기본 예제", "en":"MovableCoord basic example", "collectionId":"AKpkGW", "height": 403} + * + * @see Easing Functions Cheat Sheet {@link http://easings.net/} + * @see To use other easing functions, import jQuery easing plugin({@link http://gsgd.co.uk/sandbox/jquery/easing/}) or jQuery UI easing.({@link https://jqueryui.com/easing/})다른 easing 함수를 사용하고 싶다면, jQuery easing plugin({@link http://gsgd.co.uk/sandbox/jquery/easing/})이나, jQuery UI easing({@link https://jqueryui.com/easing/}) 라이브러리를 삽입해야 한다. + * + * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + */ + var MC = ns.MovableCoord = ns.Class.extend(ns.Component, { + construct: function(options) { + 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 + }; + this._reviseOptions(options); + 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._panmove = $.proxy(this._panmove, this); // for caching + this._panend = $.proxy(this._panend, this); // for caching + }, + /** + * Bind element + * @ko movableCoord을 사용하기 위한 엘리먼트를 등록한다. + * @method eg.MovableCoord#bind + * @param {HTMLElement|String|jQuery} element A target element. movableCoord을 사용하기 위한 엘리먼트 + * @param {Object} options + * @param {Number} [options.direction=eg.MovableCoord.DIRECTION_ALL] The controllable directions. 움직일수 있는 방향 + * @param {Array} options.scale The moving scale. 이동 배율 + * @param {Number} [options.scale.0=1] x-scale x축 배율 + * @param {Number} [options.scale.1=1] y-scale y축 배율 + * @param {Number} [options.thresholdAngle=45] The threshold angle about direction which range is 0~90 방향에 대한 임계각 (0~90) + * @param {Number} [options.interruptable=true] interruptable This value can be enabled to interrupt cycle of the animation event. 이 값이 true이면, 애니메이션의 이벤트 사이클을 중단할수 있다. + * @param {Array} [options.inputType] inputType you can control input type. a kind of inputs are "touch", "mouse". default value is ["touch", "mouse"] 입력 타입을 지정할수 있다. 입력타입은 "touch", "mouse" 가 있으며, 배열로 입력할 수 있다. (기본값은 ["touch", "mouse"] 이다) + * + * @return {eg.MovableCoord} instance of 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].get("pan").set({ + direction: subOptions.direction + }); + } else { + keyValue = Math.round(Math.random() * new Date().getTime()); + this._hammers[keyValue] = this._createHammer( + $el.get(0), + subOptions, + inputClass + ); + $el.data(MC._KEY, keyValue); + } + return this; + }, + + _createHammer: function(el, subOptions, inputClass) { + try { + // create Hammer + var hammer = new HM.Manager(el, { + recognizers: [ + [ + HM.Tap, { + + // for long tap + time: 30000 + } + ], + [ + HM.Pan, { + direction: subOptions.direction, + threshold: 0 + }, ["tap"] + ] + ], + + // 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 hammer.on("hammer.input", $.proxy(function(e) { + if (e.isFirst) { + // apply options each + this._subOptions = subOptions; + this._status.curHammer = hammer; + this._panstart(e); + } + }, this)) + .on("panstart panmove", this._panmove) + .on("panend tap", this._panend); + } catch (e) {} + }, + + _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; + }, + + /** + * Unbind element + * @ko movableCoord을 사용하기 위한 엘리먼트를 해제한다. + * @method eg.MovableCoord#unbind + * @param {HTMLElement|String|jQuery} element The target element.movableCoord을 사용하기 위한 설정한 엘리먼트 + * @return {eg.MovableCoord} instance of itself자신의 인스턴스 + */ + unbind: function(el) { + var $el = $(el); + var key = $el.data(MC._KEY); + if (key) { + this._hammers[key].destroy(); + delete this._hammers[key]; + $el.data(MC._KEY, null); + } + return this; + }, + + _grab: function() { + if (this._status.animationParam) { + 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, min, 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(); + /** + * When an area was pressed + * @ko 스크린에서 사용자가 손을 대었을 때 + * @name eg.MovableCoord#hold + * @event + * @param {Object} param + * @param {Array} param.pos coordinate 좌표 정보 + * @param {Number} param.pos.0 x-coordinate x 좌표 + * @param {Number} param.pos.1 y-coordinate y 좌표 + * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event 사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, 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.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); + + // console.log(e.velocityX, e.velocityY, e.deltaX, e.deltaY); + !(direction & MC.DIRECTION_HORIZONTAL) && (vX = 0); + !(direction & MC.DIRECTION_VERTICAL) && (vY = 0); + + this._animateBy( + this._getNextOffsetPos([ + vX * (e.deltaX < 0 ? -1 : 1) * scale[0], + vY * (e.deltaY < 0 ? -1 : 1) * scale[1] + ]), + this._animationEnd, false, null, e); + } + 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; + }, + + _animationEnd: function() { + /** + * When animation was ended. + * @ko 에니메이션이 끝났을 때 발생한다. + * @name eg.MovableCoord#animationEnd + * @event + */ + var pos = this._pos; + var min = this.options.min; + var max = this.options.max; + this._animateTo([ + Math.min(max[0], Math.max(min[0], pos[0])), + Math.min(max[1], Math.max(min[1], pos[1])) + ], $.proxy(this.trigger, this, "animationEnd"), true, null); + }, + + _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; + }, + + _animateBy: function(offset, callback, isBounce, duration, e) { + var pos = this._pos; + return this._animateTo([ + pos[0] + offset[0], + pos[1] + offset[1] + ], callback, isBounce, duration, e); + }, + + _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 destPos; + + }, + + _isCircular: function(circular, destPos, min, 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]); + }, + + _animateTo: function(absPos, callback, isBounce, duration, e) { + var pos = this._pos; + var destPos = this._getPointOfIntersection(pos, absPos); + var param = { + depaPos: pos.concat(), + destPos: destPos, + hammerEvent: e || null + }; + if (!isBounce && e) { // check whether user's action + /** + * When an area was released + * @ko 스크린에서 사용자가 손을 떼었을 때 + * @name eg.MovableCoord#release + * @event + * + * @param {Object} param + * @param {Array} param.depaPos departure coordinate 현재 좌표 + * @param {Number} param.depaPos.0 departure x-coordinate 현재 x 좌표 + * @param {Number} param.depaPos.1 departure y-coordinate 현재 y 좌표 + * @param {Array} param.destPos destination coordinate 애니메이션에 의해 이동할 좌표 + * @param {Number} param.destPos.0 destination x-coordinate x 좌표 + * @param {Number} param.destPos.1 destination y-coordinate y 좌표 + * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event 사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환) + * + */ + this.trigger("release", param); + } + this._afterReleaseProcess(param, callback, isBounce, duration); + }, + + // when user release a finger, pointer or mouse + _afterReleaseProcess: function(param, callback, isBounce, duration) { + // caution: update option values, due to value was changed by "release" event + var pos = this._pos; + var min = this.options.min; + var max = this.options.max; + var circular = this.options.circular; + var isCircular = this._isCircular( + circular, + param.destPos, + min, + max + ); + var destPos = this._isOutToOut(pos, param.destPos, min, max) ? + pos : param.destPos; + var distance = [ + Math.abs(destPos[0] - pos[0]), + Math.abs(destPos[1] - pos[1]) + ]; + var animationParam; + duration = duration === null ? + this._getDurationFromPos(distance) : duration; + duration = this.options.maximumDuration > duration ? + duration : this.options.maximumDuration; + + var done = $.proxy(function(isNext) { + this._status.animationParam = null; + pos[0] = Math.round(destPos[0]); + pos[1] = Math.round(destPos[1]); + pos = this._getCircularPos(pos, min, max, circular); + !isNext && this._setInterrupt(false); + callback(); + }, this); + + if (distance[0] === 0 && distance[1] === 0) { + return done(!isBounce); + } + + // prepare animation parameters + animationParam = { + duration: duration, + depaPos: pos.concat(), + destPos: destPos, + isBounce: isBounce, + isCircular: isCircular, + done: done, + hammerEvent: param.hammerEvent + }; + + /** + * When animation was started. + * @ko 에니메이션이 시작했을 때 발생한다. + * @name eg.MovableCoord#animationStart + * @event + * @param {Object} param + * @param {Number} param.duration + * @param {Array} param.depaPos departure coordinate 현재 좌표 + * @param {Number} param.depaPos.0 departure x-coordinate 현재 x 좌표 + * @param {Number} param.depaPos.1 departure y-coordinate 현재 y 좌표 + * @param {Array} param.destPos destination coordinate 애니메이션에 의해 이동할 좌표 + * @param {Number} param.destPos.0 destination x-coordinate x 좌표 + * @param {Number} param.destPos.1 destination y-coordinate y 좌표 + * @param {Boolean} param.isBounce When an animation is bounced, a value is 'true'. 바운스 되는 애니메이션인 경우 true + * @param {Boolean} param.isCircular When the area is circular type, a value is 'true'. 순환하여 움직여야하는 애니메이션인경우 true + * @param {Function} param.done If user control animation, user must call this function. 애니메이션이 끝났다는 것을 알려주는 함수 + * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event 사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환) + * + */ + var retTrigger = this.trigger("animationStart", animationParam); + + // You can't stop the 'animationStart' event when 'circular' is true. + if (isCircular && !retTrigger) { + throw new Error( + "You can't stop the 'animation' event when 'circular' is true." + ); + } + animationParam.depaPos = pos; + animationParam.startTime = new Date().getTime(); + this._status.animationParam = animationParam; + if (retTrigger) { + if (animationParam.duration) { + // console.error("depaPos", pos, "depaPos",destPos, "duration", duration, "ms"); + var info = this._status.animationParam; + var self = this; + (function loop() { + self._raf = null; + if (self._frame(info) >= 1) { + return done(true); + } // animationEnd + self._raf = ns.requestAnimationFrame(loop); + })(); + } else { + this._triggerChange(animationParam.destPos, false); + done(!isBounce); + } + } + }, + + // 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(options) { + var key; + $.each(["bounce", "margin", "circular"], function(i, v) { + key = options[v]; + if (key != null) { + if ($.isArray(key)) { + options[v] = key.length === 2 ? + key.concat(key) : key.concat(); + } else if (/string|number|boolean/.test(typeof key)) { + options[v] = [ key, key, key, key ]; + } else { + options[v] = null; + } + } + }); + $.extend(this.options, options); + }, + + // trigger 'change' event + _triggerChange: function(pos, holding, e) { + /** + * When coordinate was changed + * @ko 좌표가 변경됐을 때 발생한다. + * @name eg.MovableCoord#change + * @event + * + * @param {Object} param + * @param {Array} param.pos departure coordinate 좌표 + * @param {Number} param.pos.0 departure x-coordinate x 좌표 + * @param {Number} param.pos.1 departure y-coordinate y 좌표 + * @param {Boolean} param.holding If an area was pressed, this value is 'true'. 스크린을 사용자가 누르고 있을 경우 true + * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event 사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환) + * + */ + this._pos = pos.concat(); + this.trigger("change", { + pos: pos.concat(), + holding: holding, + hammerEvent: e || null + }); + }, + + /** + * Get current position + * @ko 현재 위치를 반환한다. + * @method eg.MovableCoord#get + * @return {Array} pos + * @return {Number} pos.0 x position + * @return {Number} pos.1 y position + */ + get: function() { + return this._pos.concat(); + }, + + /** + * Set to absolute position + * + * When duration is greater than zero, 'change' event is triggered + * @ko 위치를 설정한다. 만약, duration이 0보다 크다면 'change' 이벤트가 발생한다. + * @method eg.MovableCoord#setTo + * @param {Number} x x-coordinate 이동할 x좌표 + * @param {Number} y y-coordinate 이동할 y좌표 + * @param {Number} [duration=0] Duration of animation in milliseconds. 애니메이션 진행시간(ms) + * @return {eg.MovableCoord} instance of 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 ], this._animationEnd, false, duration); + } else { + this._pos = this._getCircularPos([ x, y ]); + this._triggerChange(this._pos, false); + this._setInterrupt(false); + } + return this; + }, + /** + * Set to relative position + * + * When duration is greater than zero, 'change' event is triggered + * @ko 현재를 기준으로 위치를 설정한다. 만약, duration이 0보다 크다면 'change' 이벤트가 발생한다. + * @method eg.MovableCoord#setBy + * @param {Number} x x-coordinate 이동할 x좌표 + * @param {Number} y y-coordinate 이동할 y좌표 + * @param {Number} [duration=0] Duration of animation in milliseconds. 애니메이션 진행시간(ms) + * @return {eg.MovableCoord} instance of 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); + }, + + /** + * Release resources and unbind custom events + * @ko 모든 커스텀 이벤트와 자원을 해제한다. + * @method eg.MovableCoord#destroy + */ + destroy: function() { + this.off(); + for (var p in this._hammers) { + this._hammers[p].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 + /** + * To build flickable UI + * @group egjs + * @ko 플리킹 UI를 구성한다. + * @class + * @name eg.Flicking + * @extends eg.Component + * + * @param {HTMLElement|String|jQuery} element wrapper element 기준 요소 + * @param {Object} options + * @param {Boolean} [options.hwAccelerable=eg.isHWAccelerable()] Force to use HW compositing 하드웨어 가속 사용여부 + * @param {String} [options.prefix=eg-flick] Prefix string for flicking elements 요소에 설정될 접두사 + * @param {Number} [options.deceleration=0.0006] Deceleration value can be altered to change the momentum animation duration. higher numbers make the animation shorter 감속계수는 가속도를 조절하여 애니메이션 시간을 변경할 수 있다. 높을수록 애니메이션이 짧아진다. + * @param {Boolean} [options.horizontal=true] For move direction (when horizontal is false, then move direction is vertical) 이동방향 설정 (horizontal == true 가로방향, horizontal == false 세로방향) + * @param {Boolean} [options.circular=false] To make panels rotate infinitely 순환 여부 + * @param {Number|Array} [options.previewPadding=[0,0]] Padding value to display previous and next panels. If set array value the order is left(up) to right(down) 이전과 다음 패널을 출력하는 프리뷰 형태에 사용되는 padding 값. 배열 형태로 지정시 좌측(상단), 우측(하단) 순서로 지정 + * @param {Number} [options.threshold=40] Threshold pixels to move panels in prev/next direction 다음 패널로 이동되기 위한 임계치 픽셀 + * @param {Number} [options.duration=100] Duration time of panel change animation in milliseconds 패널 이동 애니메이션 진행시간(ms) 값 + * @param {Function} [options.panelEffect=easeOutCubic] easing function which is used on panel move animation패널 간의 이동 애니메이션에 사용되는 effect easing 함수 + * @param {Number} [options.defaultIndex=0] Default panel index to show in first time 초기에 출력할 패널 인덱스 + * @param {Array} [options.inputType] inputType you can control input type. a kind of inputs are "touch", "mouse". default value is ["touch", "mouse"] 입력 타입을 지정할수 있다. 입력타입은 "touch", "mouse"가 있으며, 배열로 입력할 수 있다. (기본값은 ["touch", "mouse"] 이다) + * + * @codepen {"id":"rVOpPK", "ko":"플리킹 기본 예제", "en":"Flicking default example", "collectionId":"ArxyLK", "height" : 403} + * + * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"} + * + * @see Easing Functions Cheat Sheet {@link http://easings.net/} + * @see If you want to use another easing function then should be import jQuery easing plugin({@link http://gsgd.co.uk/sandbox/jquery/easing/}) or jQuery UI easing.({@link https://jqueryui.com/easing/})다른 easing 함수를 사용하고 싶다면, jQuery easing plugin({@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 + } + + $.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: [0, 0], // preview padding value in left(up) to right(down) order. In this mode at least 5 panels are required. + 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 padding = this.options.previewPadding; + + if (typeof padding === "number") { + padding = this.options.previewPadding = [ padding, padding ]; + } else if (padding.constructor !== Array) { + padding = this.options.previewPadding = [ 0, 0 ]; + } + + // config value + this._conf = { + panel: { + $list: $children, // panel list + index: 0, // current physical dom index + no: 0, // current logical panel index + 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 + }, + customEvent: { // for custom events value + flick: true, + restore: false, + restoreCall: false + }, + useLayerHack: this.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"]][+!this.options.horizontal]).each( + $.proxy(function (i, v) { + this._conf.dirData.push(MC["DIRECTION_" + v]); + }, this)); + + !ns._hasClickBug() && (this._setPointerEvents = $.noop); + + this._build(); + this._bindEvents(); + + this._applyPanelsCss(); + this._arrangePanels(); + + this.options.hwAccelerable && SUPPORT_WILLCHANGE && this._setHint(); + this._adjustContainerCss("end"); + }, + + /** + * 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; + + this._setPadding(padding, true); + var sizeValue = this._getDataByDirection([ panel.size, "100%" ]); + + // panels' css values + $children.addClass(prefix + "-panel").css({ + position: "absolute", + width: sizeValue[0], + height: sizeValue[1], + top: 0, + left: 0 + }); + + // create container element + cssValue = "position:relative;z-index:2000;width:100%;height:100%;" + + (!horizontal ? "top:" + padding[0] + "px;" : ""); + + this.$container = $children.wrapAll( + "
" + ).parent(); + + 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 + }).bind(this.$wrapper, { + scale: this._getDataByDirection([-1, 0]), + direction: MC["DIRECTION_" + + (horizontal ? "HORIZONTAL" : "VERTICAL")], + interruptable: false, + inputType: options.inputType + }); + + 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; + + panel.size = this.$wrapper[ + horizontal ? "outerWidth" : "height" + ]() - (padding[0] + padding[1]); + + var cssValue = { + padding: (horizontal ? + "0 " + padding.reverse().join("px 0 ") : + padding.join("px 0 ")) + "px" + }; + + if (build) { + cssValue.overflow = "hidden"; + } else if (!horizontal) { + this.$container.css("top", padding[0]); + } + + this.$wrapper.css(cssValue); + }, + + /** + * 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; + + 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 + this._movePanelPosition(this._getBasePositionIndex(), false); + + panel.no = index; + } else { + // if defaultIndex option is given, then move to that index panel + if (index > 0 && index <= lastIndex) { + panel.no = panel.index = 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; + + 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 + panel.index = this._getBasePositionIndex(); + + // 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) { + isDirVal && 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) { + !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 () { + var panel = this._conf.panel; + return panel.index = Math.floor(panel.count / 2 - 0.1); + }, + + /** + * Bind events + */ + _bindEvents: function () { + this._mcInst.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) + }); + }, + + /** + * 'hold' event handler + */ + _holdHandler: function (e) { + this._conf.touch.holdPos = e.pos; + this._conf.panel.changed = false; + + this._adjustContainerCss("start", e.pos); + }, + + /** + * 'change' event handler + */ + _changeHandler: function (e) { + var conf = this._conf; + var touch = conf.touch; + var pos = e.pos; + var direction; + var eventRes = null; + var movedPx; + + this._setPointerEvents(e); // for "click" bug + + /** + * Occurs during the change + * @ko 패널이 이동될 때 발생하는 이벤트 + * @name eg.Flicking#flick + * @event + * @param {Object} param + * @param {String} param.eventType Name of event 이벤트명 + * @param {Number} param.index Current panel physical index 현재 패널 물리적 인덱스 + * @param {Number} param.no Current panel logical position 현재 패널 논리적 인덱스 + * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) 플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인) + * @param {Array} param.pos Departure coordinate 출발점 좌표 + * @param {Number} param.pos.0 Departure x-coordinate x 좌표 + * @param {Boolean} param.holding Holding if an area is pressed, this value is 'true'. 스크린을 사용자가 누르고 있을 경우 true + */ + 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 + })); + + (eventRes || eventRes === null) && this._setTranslate([ + -pos[+!this.options.horizontal], 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"); + + 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, ""); + + /** + * Before panel restores it's last position + * @ko 플리킹 임계치에 도달하지 못하고 사용자의 액션이 끝났을 경우, 원래 패널로 복원되기 전에 발생하는 이벤트 + * @name eg.Flicking#beforeRestore + * @event + * + * @param {Object} param + * @param {String} param.eventType Name of event 이벤트명 + * @param {Number} param.index Current panel physical index 현재 패널 물리적 인덱스 + * @param {Number} param.no Current panel logical position 현재 패널 논리적 인덱스 + * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) 플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인) + * @param {Array} param.depaPos Departure coordinate 출발점 좌표 + * @param {Number} param.depaPos.0 Departure x-coordinate x 좌표 + * @param {Number} param.depaPos.1 Departure y-coordinate y 좌표 + * @param {Array} param.destPos Destination coordinate 도착점 좌표 + * @param {Number} param.destPos.0 Destination x-coordinate x 좌표 + * @param {Number} param.destPos.1 Destination 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; + + /** + * After panel restores it's last position + * @ko 플리킹 임계치에 도달하지 못하고 사용자의 액션이 끝났을 경우, 원래 인덱스로 복원된 후 발생하는 이벤트 + * @name eg.Flicking#restore + * @event + * + * @param {Object} param + * @param {String} param.eventType Name of event 이벤트명 + * @param {Number} param.index Current panel physical index 현재 패널 물리적 인덱스 + * @param {Number} param.no Current panel logical position 현재 패널 논리적 인덱스 + * @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())) { + conf.indexToMove === 0 && this._setPanelNo(); + + /** + * Before panel changes + * @ko 플리킹이 시작되기 전에 발생하는 이벤트 + * @name eg.Flicking#beforeFlickStart + * @event + * + * @param {Object} param + * @param {String} param.eventType Name of event 이벤트명 + * @param {Number} param.index Current panel physical index 현재 패널 물리적 인덱스 + * @param {Number} param.no Current panel logical position 현재 패널 논리적 인덱스 + * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) 플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인) + * @param {Array} param.depaPos Departure coordinate 출발점 좌표 + * @param {Number} param.depaPos.0 Departure x-coordinate x 좌표 + * @param {Number} param.depaPos.1 Departure y-coordinate y 좌표 + * @param {Array} param.destPos Destination coordinate 도착점 좌표 + * @param {Number} param.destPos.0 Destination x-coordinate x 좌표 + * @param {Number} param.destPos.1 Destination y-coordinate y 좌표 + */ + if (!this._triggerEvent(EVENTS.beforeFlickStart, pos)) { + return panel.changed = panel.animating = false; + } + } 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; + + /** + * After panel changes + * @ko 플리킹으로 패널이 이동된 후 발생하는 이벤트 + * @name eg.Flicking#flickEnd + * @event + * + * @param {Object} param + * @param {String} param.eventType Name of event 이벤트명 + * @param {Number} param.index Current panel physical index 현재 패널 물리적 인덱스 + * @param {Number} param.no Current panel logical position 현재 패널 논리적 인덱스 + * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) 플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인) + */ + panel.changed && this._triggerEvent(EVENTS.flickEnd); + } + + !(phase === "start" && pos === undefined) && this._adjustContainerCss(phase); + }, + + /** + * Set the logical panel index number + * @param {Boolean} recover + */ + _setPanelNo: function (recover) { + var panel = this._conf.panel; + var count = panel.origCount - 1; + var num = this._conf.touch.direction === this._conf.dirData[0] ? 1 : -1; + + if (recover) { + panel.index = panel.prevIndex >= 0 ? + panel.prevIndex : panel.index - num; + + panel.no = panel.prevNo >= 0 ? + panel.prevNo : panel.no - num; + + } else { + 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. + 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) { + var options = this.options; + + if (!SUPPORT_TRANSFORM && !options.horizontal) { + coords[0] += options.previewPadding[0]; + } + + 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 () { + return Math.abs(this._conf.touch.distance) >= this.options.threshold; + }, + + /** + * 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; + + return this.trigger(conf.eventPrefix + name, $.extend({ + eventType: name, + index: panel.index, + no: panel.no, + 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.index; + 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.no; + } + + 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; + }, + + /** + * Get current panel position + * @ko 현재 패널의 인덱스 값을 반환한다. + * @method eg.Flicking#getIndex + * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) 물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적) + * @return {Number} Number Current index number 현재 패널 인덱스 번호 + */ + getIndex: function (physical) { + return this._conf.panel[ physical ? "index" : "no" ]; + }, + + /** + * Get current panel element + * @ko 현재 패널 요소의 레퍼런스를 반환한다. + * @method eg.Flicking#getElement + * @return {jQuery} jQuery Current element 현재 요소 + */ + getElement: function () { + var panel = this._conf.panel; + return $(panel.$list[panel.index]); + }, + + /** + * Get next panel element + * @ko 다음 패널 요소의 레퍼런스를 반환한다. + * @method eg.Flicking#getNextElement + * @return {jQuery|null} Next element or null if no more element exist다음 패널 요소. 패널이 없는 경우에는 null + */ + getNextElement: function () { + return this._getElement(this._conf.dirData[0], true); + }, + + /** + * Get next panel index + * @ko 다음 패널의 인덱스 값을 반환한다. + * @method eg.Flicking#getNextIndex + * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) 물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적) + * @return {Number|null} Next element index value or null if no more element exist다음 패널 인덱스 번호. 패널이 없는 경우에는 null + */ + getNextIndex: function (physical) { + return this._getElement(this._conf.dirData[0], false, physical); + }, + + /** + * Get whole panel elements + * @ko 패널을 구성하는 모든 요소들의 레퍼런스를 반환한다. + * @method eg.Flicking#getAllElements + * @return {jQuery} jQuery All panel elements 모든 패널 요소 + */ + getAllElements: function () { + return this._conf.panel.$list; + }, + + /** + * Get previous panel element + * @ko 이전 패널 요소의 레퍼런스를 반환한다. + * @method ns.Flicking#getPrevElement + * @return {jQuery|null} Previous element or null if no more element exist 이전 패널 요소. 패널이 없는 경우에는 null + */ + getPrevElement: function () { + return this._getElement(this._conf.dirData[1], true); + }, + + /** + * Get previous panel index + * @ko 이전 패널의 인덱스 값을 반환한다. + * @method eg.Flicking#getPrevIndex + * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) 물리적/논리적 값 인덱스 불리언(true: 물리적, 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); + }, + + /** + * Get total panel count + * @ko 전체 패널의 개수를 반환한다. + * @method eg.Flicking#getTotalCount + * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) 물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적) + * @return {Number} Number Count of all elements 모든 패널 요소 개수 + */ + getTotalCount: function (physical) { + return this._conf.panel[ physical ? "count" : "origCount" ]; + }, + + /** + * Return either panel is animating or not + * @ko 현재 애니메이션중인지 여부를 리턴한다. + * @method eg.Flicking#isPlaying + * @return {Boolean} + */ + isPlaying: function () { + return this._conf.panel.animating; + }, + + /** + * Move panel to the given direction + * @param {Boolean} next + * @param {Number} duration + */ + _movePanel: function (next, duration) { + var panel = this._conf.panel; + var options = this.options; + + if (panel.animating) { + 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"); + } + }, + + /** + * Move to next panel + * @ko 다음 패널로 이동한다. + * @method eg.Flicking#next + * @param {Number} [duration=options.duration] Duration of animation in milliseconds 애니메이션 진행시간(ms) + * @return {eg.Flicking} instance of itself자신의 인스턴스 + */ + next: function (duration) { + return this._movePanel(true, duration); + }, + + /** + * Move to previous panel + * @ko 이전 패널로 이동한다. + * @method eg.Flicking#prev + * @param {Number} [duration=options.duration] Duration of animation in milliseconds 애니메이션 진행시간(ms) + * @return {eg.Flicking} instance of itself자신의 인스턴스 + */ + prev: function (duration) { + return this._movePanel(false, duration); + }, + + /** + * Move to indicated panel + * @ko 지정한 패널로 이동한다. + * @method eg.Flicking#moveTo + * @param {Number} no logical panel index + * @param {Number} [duration=options.duration] Duration of animation in milliseconds 애니메이션 진행시간(ms) + * @return {eg.Flicking} instance of itself자신의 인스턴스 + */ + moveTo: function (no, duration) { + var panel = this._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) { + return this; + } + + // remember current value in case of restoring + panel.prevIndex = currentIndex; + panel.prevNo = panel.no; + + 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; + } + + panel.no = no; + } else { + indexToMove = no - currentIndex; + panel.no = panel.index = 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); + } + }, + + /** + * Update panel size according current viewport + * @ko 패널 사이즈 정보를 갱신한다. + * @method eg.Flicking#resize + * @return {eg.Flicking} instance of 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; + }, + + /** + * Restore panel in its right position + * @ko 패널의 위치가 올바로 위치하지 않게 되는 경우, 제대로 위치하도록 보정한다. + * @method eg.Flicking#restore + * @param {Number} [duration=options.duration] Duration of animation in milliseconds 애니메이션 진행시간(ms) + * @return {eg.Flicking} instance of 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.size) { + conf.customEvent.restoreCall = true; + duration = this._getNumValue(duration, this.options.duration); + + this._setPanelNo(true); + 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._setPanelNo(true); + + conf.touch.distance = conf.indexToMove = 0; + panel.prevIndex = panel.prevNo = -1; + } + + return this; + } + }); +}); +/** + * Flicking in jQuery plugin + * + * @ko Flicking in jQuery plugin + * @method jQuery.flicking + * @example +
+
+

Layer 0

+
+
+

Layer 1

+
+
+

Layer 2

+
+
+ + * @see eg.Flicking + */ +/** + * flicking:beforeRestore jQuery event plugin + * + * @ko flicking:beforeRestore jQuery event plugin + * @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 + */ +/** + * flicking:beforeFlickStart jQuery event plugin + * + * @ko flicking:beforeFlickStart jQuery event plugin + * @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 + */ +/** + * flicking:flick jQuery event plugin + * + * @ko flicking:flick jQuery event plugin + * @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 + */ +/** + * flicking:flickEnd jQuery event plugin + * + * @ko flicking:flickEnd jQuery event plugin + * @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 + */ +/** + * flicking:restore jQuery event plugin + * + * @ko flicking:restore jQuery event plugin + * @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, "Outlayer"], function($, ns, global, doc, Outlayer) { +// jscs:enable validateLineBreaks, maximumLineLength + if (!Outlayer) { + ns.InfiniteGrid = ns.Class({}); + return; + } + + function clone(target, source, what) { + var s; + $.each(what, function(i, v) { + s = source[v]; + if (s != null) { + if ($.isArray(s)) { + target[v] = $.merge([], s); + } else if ($.isPlainObject(s)) { + target[v] = $.extend(true, {}, s); + } else { + target[v] = s; + } + } + }); + return target; + } + + var InfiniteGridCore = Outlayer.create("InfiniteGrid"); + $.extend(InfiniteGridCore.prototype, { + // @override (from layout) + _resetLayout: function() { + if (!this._isLayoutInited) { + this._registGroupKey(this.options.defaultGroupKey, this.items); + } + this.element.style.width = null; + this.getSize(); // create size property + this._measureColumns(); + }, + + // @override + _getContainerSize: function() { + return { + height: Math.max.apply(Math, this._appendCols), + width: this.size.innerWidth + }; + }, + + // @override + _getItemLayoutPosition: function(item) { + if (this._equalItemSize) { + item.size = this._equalItemSize; + } else { + item.getSize(); + } + (item.isAppend == null) && (item.isAppend = true); + var outerHeight = parseInt(item.size.outerHeight, 10); + var shortColIndex; + var isAppend = item.isAppend; + var cols = isAppend ? this._appendCols : this._prependCols; + var y = Math[isAppend ? "min" : "max"].apply(Math, cols); + 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 ? outerHeight : -outerHeight); + + return { + x: this.columnWidth * shortColIndex, + y: isAppend ? y : y - outerHeight + }; + }, + resetLayout: function() { + this._resetLayout(); + this._isLayoutInited = true; + }, + 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.outerHeight : -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; + })); + }, + _measureColumns: function() { + var containerWidth = this.size.innerWidth; + var columnWidth = this._getColumnWidth(); + var cols = containerWidth / columnWidth; + var excess = columnWidth - containerWidth % 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._appendCols = []; + this._prependCols = []; + while (cols--) { + this._appendCols.push(0); + this._prependCols.push(0); + } + }, + _getColumnWidth: function() { + var el = this.items[0] && this.items[0].element; + var size; + if (el) { + /* jshint ignore:start */ + size = getSize(el); + /* jshint ignore:end */ + } else { + size = { + outerWidth: 0, + outerHeight: 0 + }; + } + this.options.isEqualSize && (this._equalItemSize = size); + this.columnWidth = size.outerWidth || this.size.outerWidth; + return this.columnWidth; + }, + _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; + }, + clone: function(target, source) { + clone(target, source, [ + "_isLayoutInited", + "_equalItemSize", + "_appendCols", + "_prependCols", + "columnWidth", + "size", + "options" + ]); + target.items = target.items || []; + target.items.length = source.items.length; + $.each(source.items, function(i) { + target.items[i] = clone(target.items[i] || {}, source.items[i], + ["position", "size", "isAppend", "groupKey"]); + }); + return target; + }, + itemize: function(elements, groupKey) { + var items = this._itemize(elements); + this._registGroupKey(groupKey, items); + return items; + }, + _registGroupKey: function(groupKey, array) { + if (groupKey != null) { + var i = 0; + var v; + while (v = array[i++]) { + v.groupKey = groupKey; + } + } + }, + + // @override + destroy: function() { + this.off(); + Outlayer.prototype.destroy.apply(this); + } + }); + + /** + * To build Grid layout UI + * InfiniteGrid is composed using Outlayer and supports recycle-dom. + * DOM elements are fixed even contents are added infinitely. + * @group egjs + * @ko 그리드 레이아웃을 구성하는 UI 컴포넌트. InfiniteGrid는 Outlayer로 구성되어 있다. 하지만, 이 컴포넌트는 recycle-dom을 지원한다. + * 컨텐츠를 계속 증가하면 할수록 일정한 DOM 개수를 유지할수 있다. + * @class + * @name eg.InfiniteGrid + * @extends eg.Component + * + * @param {HTMLElement|String|jQuery} element wrapper element 기준 요소 + * @param {Object} [options] + * @param {String} [options.itemSelector] selector string for layout item elements 레이아웃의 아이템으로 사용될 엘리먼트들의 셀렉터 + * @param {Boolean} [options.isEqualSize=false] determine if all item's size are same 모든 아이템의 사이즈가 동일한지를 지정한다 + * @param {String} [options.defaultGroupKey=null] when encounter item markup during the initialization, then set `defaultGroupKey` as groupKey 초기화할때 마크업에 아이템이 있다면, defalutGroupKey를 groupKey로 지정한다 + * @param {Number} [options.count=30] when count value is greater than 0, grid will maintain same DOM length recycling count값이 0보다 클 경우, 그리드는 일정한 dom 개수를 유지한다 + * @param {Number} [options.threshold=300] Threshold pixels to determine if grid needs to append or prepend elements엘리먼트가 append 또는 prepend될지를 결정하는 임계치 픽셀 + * + * @codepen {"id":"zvrbap", "ko":"InfiniteGrid 데모", "en":"InfiniteGrid example", "collectionId":"DPYEww", "height": 403} + * @support {"ie": "8+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"} + * + * @see Outlayer {@link https://github.com/metafizzy/outlayer} + * + * @example + +
    +
  • +
    테스트1
    +
  • +
  • +
    테스트2
    +
  • +
  • +
    테스트3
    +
  • +
  • +
    테스트4
    +
  • +
  • +
    테스트5
    +
  • +
  • +
    테스트6
    +
  • +
+ + */ + 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); + this.options.transitionDuration = 0; // don't use this option. + this.options.isInitLayout = false; // isInitLayout is always 'false' in order to controll layout. + this.options.isResizeBound = false; // isResizeBound is always 'false' in order to controll layout. + + // if el is jQuery instance, el should change to HTMLElement. + if (el instanceof $) { + el = el.get(0); + } + this._prefix = _prefix || ""; + this.core = new InfiniteGridCore(el, this.options) + .on(EVENTS.layoutComplete, $.proxy(this._onlayoutComplete, this)); + this.$view = $(global); + this._reset(); + this.core.$element.children().length > 0 && this.layout(); + this._onResize = $.proxy(this._onResize, this); + this._onScroll = $.proxy(this._onScroll, this); + this._isIos = ns.agent().os.name === "ios"; + this._prevScrollTop = 0; + this._topElement = null; + this._bottomElement = null; + this._refreshViewport(); + this.$view.on("resize", this._onResize); + this.$view.on("scroll", this._onScroll); + }, + _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) { + ele = this._bottomElement || this.getBottomElement(); + rect = ele.getBoundingClientRect(); + if (rect.top <= this._clientHeight + this.options.threshold) { + /** + * Occurs when grid needs to append elements. + * in order words, when scroll reaches end of page + * + * @ko 엘리먼트가 append 될 필요가 있을 때 발생하는 이벤트. + * 즉, 스크롤이 페이지 하단에 도달했을 때 발생한다. + * @name eg.InfiniteGrid#append + * @event + * + * @param {Object} param + * @param {Number} param.scrollTop scrollTop scroll-y position of window윈도우 y 스크롤의 값 + */ + this.trigger(this._prefix + EVENTS.append, { + scrollTop: scrollTop + }); + } + } else { + if (this.isRecycling() && this._removedContent > 0 && + (ele = this._topElement || this.getTopElement())) { + rect = ele.getBoundingClientRect(); + if (rect.bottom >= -this.options.threshold) { + /** + * Occurs when grid needs to prepend elements + * in order words, when scroll reaches top of page and a count of cropped element is more than zero. + * + * @ko 엘리먼트가 prepend 될 필요가 있을 때 발생하는 이벤트. + * 즉, 스크롤이 페이지 상단에 도달하고, 순환에 의해 잘려진 엘리먼트가 존재할때 발생한다. + * @name eg.InfiniteGrid#prepend + * @event + * + * @param {Object} param + * @param {Number} param.scrollTop scrollTop scroll-y position of window윈도우 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; + function delayed() { + self._refreshViewport(); + self.core.element.style.width = null; + self.core.needsResizeLayout() && self.layout(); + delete self.resizeTimeout; + } + this.resizeTimeout = setTimeout(delayed, 100); + }, + _refreshViewport: function() { + this._clientHeight = this.$view.height(); + }, + /** + * Get current status + * @ko infiniteGrid의 현재상태를 반환한다. + * @method eg.InfiniteGrid#getStatue + * @return {Object} infiniteGrid status ObjectinfiniteGrid 상태 오브젝트 + */ + getStatus: function() { + var data = []; + var p; + for (p in this) { + if (this.hasOwnProperty(p) && /^_/.test(p)) { + data.push(p); + } + } + return { + core: this.core.clone({}, this.core), + data: clone({}, this, data), + html: this.core.$element.html(), + cssText: this.core.element.style.cssText + }; + }, + /** + * Set current status + * @ko infiniteGrid의 현재상태를 설정한다. + * @method eg.InfiniteGrid#setStatus + * @param {Object} status Object + * @return {eg.InfiniteGrid} instance of itself자신의 인스턴스 + */ + setStatus: function(status) { + this.core.element.style.cssText = status.cssText; + this.core.$element.html(status.html); + this.core.items = this.core.itemize(this.core.$element.children().toArray()); + this.core.clone(this.core, status.core); + $.extend(this, status.data); + return this; + }, + /** + * Check if element is appending or prepending + * @ko append나 prepend가 진행중일 경우 true를 반환한다. + * @method eg.InfiniteGrid#isProcessing + * @return {Boolean} + */ + isProcessing: function() { + return this._isProcessing; + }, + /** + * Check if elements are in recycling mode + * @ko recycle 모드 여부를 반환한다. + * @method eg.InfiniteGrid#isRecycling + * @return {Boolean} + */ + isRecycling: function() { + return this.core.options.count > 0 && this._isRecycling; + }, + /** + * Get group keys + * @ko 그룹키들을 반환한다. + * @method eg.InfiniteGrid#getGroupKeys + * @return {Array} groupKeys + */ + getGroupKeys: function() { + var result = []; + if (this.core._isLayoutInited) { + var i = 0; + var item; + while (item = this.core.items[i++]) { + result.push(item.groupKey); + } + } + return result; + }, + /** + * Rearrange layout + * @ko 레이아웃을 재배치한다. + * @method eg.InfiniteGrid#layout + * @return {eg.InfiniteGrid} instance of itself자신의 인스턴스 + */ + layout: function() { + this._isProcessing = true; + this._isAppendType = true; + var i = 0; + var v; + while (v = this.core.items[i++]) { + v.isAppend = true; + } + this.core.layout(); + return this; + }, + /** + * Append elements + * @ko 엘리먼트를 append 한다. + * @method eg.InfiniteGrid#append + * @param {Array|String|jQuery} elements to be appended elements append될 엘리먼트 배열 + * @param {Number|String} [groupKey] to be appended groupkey of elementsappend될 엘리먼트의 그룹키 + * @return {Number} length a number of 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.core.items.length + $elements.length) >= this.core.options.count; + } + this._insert($elements, groupKey, true); + return $elements.length; + }, + /** + * Prepend elements + * @ko 엘리먼트를 prepend 한다. + * @method eg.InfiniteGrid#prepend + * @param {Array|String|jQuery} elements to be prepended elements prepend될 엘리먼트 배열 + * @param {Number|String} [groupKey] to be prepended groupkey of elementsprepend될 엘리먼트의 그룹키 + * @return {Number} length a number of 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; + }, + /** + * Clear elements and data + * @ko 엘리먼트와 데이터를 지운다. + * @method eg.InfiniteGrid#clear + * @return {eg.InfiniteGrid} instance of itself자신의 인스턴스 + */ + clear: function() { + this.core.$element.empty(); + this.core.items.length = 0; + this._reset(); + this.layout(); + return this; + + }, + + _getTopItem: function() { + var item = null; + var min = Infinity; + $.each(this.core.getColItems(false), function(i, v) { + if (v && v.position.y < min) { + min = v.position.y; + item = v; + } + }); + return item; + }, + + /** + * Get the first element at the top + * @ko 가장 위에 있는 엘리먼트를 반환한다. + * @method eg.InfiniteGrid#getTopElement + * + * @return {HTMLElement} element + */ + getTopElement: function() { + var item = this._getTopItem(); + return item && item.element; + }, + + _getBottomItem: function() { + var item = null; + var max = -Infinity; + $.each(this.core.getColItems(true), function(i, v) { + if (v && v.position.y + v.size.outerHeight > max) { + max = v.position.y + v.size.outerHeight; + item = v; + } + }); + return item; + }, + + /** + * Get the last element at the bottom + * @ko 가장 아래에 있는 엘리먼트를 반환한다. + * @method eg.InfiniteGrid#getBottomElement + * + * @return {HTMLElement} element + */ + getBottomElement: function() { + var item = this._getBottomItem(); + return item && item.element; + }, + + _onlayoutComplete: function(e) { + var distance = 0; + var isAppend = this._isAppendType; + var item; + var i = 0; + while (item = e[i++]) { + if (typeof item.oldVisibility !== "undefined") { + item.element.style.visibility = item.oldVisibility; + delete item.oldVisibility; + } + } + + // refresh element + this._topElement = this.getTopElement(); + this._bottomElement = this.getBottomElement(); + + if (isAppend === false) { + this._isFitted = false; + this._fit(true); + distance = e.length >= this.core.items.length ? + 0 : this.core.items[e.length].position.y; + if (distance > 0) { + this._prevScrollTop = this._getScrollTop() + distance; + this.$view.scrollTop(this._prevScrollTop); + } + } + + // reset flags + this._reset(true); + + /** + * Occurs when layout is completed (after append / after prepend / after layout) + * @ko 레이아웃이 완료 되었을 때 발생하는 이벤트 (append/prepend/layout 메소드 호출 후, 아이템의 배치가 완료되었을때 발생) + * @name eg.InfiniteGrid#layoutComplete + * @event + * + * @param {Object} param + * @param {Array} param.target target rearranged elements재배치된 엘리먼트들 + * @param {Boolean} param.isAppend isAppend determine if append or prepend (value is true when call layout method)아이템이 append로 추가되었는지, prepend로 추가되었는지를 반한환다. (layout호출시에는 true) + * @param {Number} param.distance the distance of moved top-element after layoutComplete event is triggered. in order words, prepended distance or height 최상단 엘리먼트가 layoutComplete 이벤트 발생 후,이동되어진 거리. 즉, prepend 되어 늘어난 거리(높이) + * @param {Number} param.croppedCount the count of removed elements for recycle-dom. 순환 구조에 의해, 삭제된 엘리먼트 개수 + */ + this.trigger(this._prefix + EVENTS.layoutComplete, { + target: e.concat(), + isAppend: isAppend, + distance: distance, + croppedCount: this._removedContent + }); + }, + + // $elements => $([HTMLElement, HTMLElement, ...]) + _insert: function($elements, groupKey, isAppend) { + if ($elements.length === 0) { + return; + } + this._isAppendType = isAppend; + var elements = $elements.toArray(); + var $cloneElements = $(elements); + var i = 0; + var item; + var items = this.core.itemize(elements, groupKey); + while (item = items[i++]) { + item.isAppend = isAppend; + item.oldVisibility = item.element.style.visibility; + item.element.style.visibility = "hidden"; + } + if (isAppend) { + this.core.items = this.core.items.concat(items); + } else { + this.core.items = items.concat(this.core.items.slice(0)); + items = items.reverse(); + } + if (this.isRecycling()) { + this._adjustRange(isAppend, $cloneElements); + } + var noChild = this.core.$element.children().length === 0; + this.core.$element[isAppend ? "append" : "prepend"]($cloneElements); + noChild && this.core.resetLayout(); // for init-items + + var needCheck = this._checkImageLoaded($cloneElements); + if (needCheck.length > 0) { + this._waitImageLoaded(items, needCheck); + } else { + // convert to async + var self = this; + setTimeout(function() { + self.core.layoutItems(items, true); + }, 0); + } + }, + _adjustRange: function (isTop, $elements) { + var diff = this.core.items.length - this.core.options.count; + var targets; + var idx; + if (diff <= 0 || (idx = this._getDelimiterIndex(isTop, diff)) < 0) { + return; + } + if (isTop) { + targets = this.core.items.slice(0, idx); + this.core.items = this.core.items.slice(idx); + this._isFitted = false; + } else { + targets = this.core.items.slice(idx); + this.core.items = this.core.items.slice(0, idx); + } + + // @todo improve performance + var i = 0; + var item; + var el; + while (item = targets[i++]) { + el = item.element; + idx = $elements.index(el); + if (idx !== -1) { + $elements.splice(idx, 1); + } else { + el.parentNode.removeChild(el); + } + } + this._removedContent += isTop ? targets.length : -targets.length; + + }, + _getDelimiterIndex: function(isTop, removeCount) { + var len = this.core.items.length; + var i; + var idx = 0; + var baseIdx = isTop ? removeCount - 1 : len - removeCount; + var targetIdx = baseIdx + (isTop ? 1 : -1); + var groupKey = this.core.items[baseIdx].groupKey; + if (groupKey != null && groupKey === this.core.items[targetIdx].groupKey) { + if (isTop) { + for (i = baseIdx; i > 0; i--) { + if (groupKey !== this.core.items[i].groupKey) { + break; + } + } + idx = i === 0 ? -1 : i + 1; + } else { + for (i = baseIdx; i < len; i++) { + if (groupKey !== this.core.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.core.options.count <= 0) { + this._fit = function() { + return false; + }; + this._isFitted = true; + return false; + } + + if (this._isFitted) { + return false; + } + + var item; + var height; + var i = 0; + var y = this.core.updateCols(); // for prepend + while (item = this.core.items[i++]) { + item.position.y -= y; + applyDom && item.css({ + "top": item.position.y + "px" + }); + } + this.core.updateCols(true); // for append + height = this.core._getContainerSize().height; + applyDom && this.core._setContainerMeasure(height, false); + this._isFitted = true; + return true; + }, + + /** + * Remove white space which was removed by append action. + * @ko append에 의해 제거된 빈공간을 제거한다. + * @method eg.InfiniteGrid#fit + * @return {Number} distance if empty space is removed, value is not zero. 빈공간이 제거되면 0이 아닌 값을 반환 + */ + fit: function() { + var item = this._getTopItem(); + var distance = item ? item.position.y : 0; + this._fit(true); + return distance; + }, + _reset: function(isLayoutComplete) { + if (!isLayoutComplete) { + this._isFitted = true; + this._isRecycling = false; + this._removedContent = 0; + } + this._isAppendType = null; + this._isProcessing = false; + }, + _checkImageLoaded: function($elements) { + var needCheck = []; + $elements.each(function(k, v) { + if (v.nodeName === "IMG") { + !v.complete && needCheck.push(v); + } else if (v.nodeType && + (v.nodeType === 1 || v.nodeType === 9 || v.nodeType === 11)) { // ELEMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE + needCheck = needCheck.concat($(v).find("img").filter(function(fk, fv) { + return !fv.complete; + }).toArray()); + } + }); + return needCheck; + }, + _waitImageLoaded: function(items, needCheck) { + var core = this.core; + var checkCount = needCheck.length; + var onCheck = function(e) { + checkCount--; + $(e.target).off("load error"); + checkCount <= 0 && core.layoutItems(items, true); + }; + $.each(needCheck, function(k, v) { + $(v).on("load error", onCheck); + }); + }, + /** + * Release resources and unbind custom events + * @ko 모든 커스텀 이벤트와 자원을 해제한다. + * @method eg.InfiniteGrid#destroy + */ + destroy: function() { + if (this.core) { + this.core.destroy(); + this.core = null; + } + this.$view.off("resize", this._onResize) + .off("scroll", this._onScroll); + this.off(); + } + }); +}); +/** + * InfiniteGrid in jQuery plugin + * @ko InfiniteGrid in jQuery plugin + * @method jQuery.infiniteGrid + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid + */ + /** + * infiniteGrid:layoutComplete jQuery event plugin + * + * @ko infiniteGrid:layoutComplete jQuery event plugin + * @name jQuery#infiniteGrid:layoutComplete + * @event + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid#event:layoutComplete + */ +/** + * infiniteGrid:append jQuery event plugin + * + * @ko infiniteGrid:append jQuery event plugin + * @name jQuery#infiniteGrid:append + * @event + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid#event:append + */ +/** + * infiniteGrid:prepend jQuery event plugin + * + * @ko infiniteGrid:prepend jQuery event plugin + * @name jQuery#infiniteGrid:prepend + * @event + * @example +
    +
  • +
    test1
    +
  • +
  • +
    test3
    +
  • +
+ + * @see eg.InfiniteGrid#event:prepend + */ \ No newline at end of file diff --git a/dist/eg.min.js b/dist/eg.min.js new file mode 100644 index 0000000..1c1413e --- /dev/null +++ b/dist/eg.min.js @@ -0,0 +1,16 @@ +/** +* 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.1.0 +* @SHA-1 fb4a69e (1.1.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._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/"},Outlayer:{url:"https://github.com/metafizzy/outlayer/"}},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],function(a,b,c){function d(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 e=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,f=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(e&&!f){var g={},h=e;e=function(a){function b(){g[c]&&a()}var c=h(b);return g[c]=!0,c},f=function(a){delete g[a]}}else e&&f||(e=function(a){return c.setTimeout(a,16)},f=c.clearTimeout);b.VERSION="1.1.0",b.hook={};var i={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"}}},j={getBrowserName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.browser)},getBrowserVersion:function(a){var b,c;return a?(c=this.getBrowserRule(a).versionSearch||a,b=this.extractBrowserVersion(c,this.ua)):void 0},extractBrowserVersion:function(a,b){var c,d,e=i.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},getOSName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.os)},getOSVersion:function(a){var b,c,d,e,f=this.ua,g=this.getOSRule(a)||{},h=i.defaultString.os.version;return a?g.versionAlias?g.versionAlias:(c=g.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||h):void 0},getOSRule:function(a){return this.getRule(i.os,a)},getBrowserRule:function(a){return this.getRule(i.browser,a)},getRule:function(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&&this.isMatched(this.ua,c):d)return e},getIdentityStringFromArray:function(a,b){for(var c,d=0;c=a[d];d++)if(this.isMatched(this.ua,c.criteria))return c.identity||b.name;return b.name},isMatched:function(a,b){return b&&b.test?!!b.test(a):a.indexOf(b)>-1},isWebview:function(){for(var a,b,c=this.ua,d=i.webview,e=!1,f=0;b=d[f];f++)if(this.isMatched(c,b.criteria)&&(a=this.extractBrowserVersion(b.browserVersionSearch,c),this.isMatched(c,b.webviewToken)||this.isMatched(a,b.webviewBrowserVersion))){e=!0;break}return e}};j.create=function(a){j.ua=a;var b={os:{},browser:{}};return b.browser.name=j.getBrowserName(i.browser),b.browser.version=j.getBrowserVersion(b.browser.name),b.os.name=j.getOSName(i.os),b.os.version=j.getOSVersion(b.os.name),b.browser.webview=j.isWebview(),b.browser.name=b.browser.name.toLowerCase(),b.os.name=b.os.name.toLowerCase(),b},b.agent=function(){var a=j.create(c.navigator.userAgent);return d(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,e=b.agent(),f=e.os.version,g=e.browser.name,h=e.browser.version;return-1!==g.indexOf("chrome")?c=h>="25":/ie|edge|firefox|safari|inapp/.test(g)?c=!0:-1!==e.os.name.indexOf("android")&&(a=(j.ua.match(/\(.*\)/)||[null])[0],c=f>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||f>="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)),d(this,"isHWAccelerable",[c,e],c)},b.isTransitional=function(){var a=!1,c=b.agent(),e=c.browser.name;if(/chrome|firefox/.test(e))a=!0;else switch(c.os.name){case"ios":a=/safari|inapp/.test(e)&&parseInt(c.os.version,10)<6;break;case"window":a=-1!==e.indexOf("safari")||-1!==e.indexOf("ie")&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/chrome|firefox|safari/.test(e)}return d(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return d(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return e(a)},b.cancelAnimationFrame=function(a){f(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,h=a):(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,a(c).trigger("rotate"))}function g(a){var b,e,i=m();if("resize"===i)c.setTimeout(function(){f()},0);else{if(b=300,"android"===k.os.name){if(e=d.documentElement.clientWidth,"orientationchange"===a.type&&e===h)return c.setTimeout(function(){g(a)},500),!1;h=e}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),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"ios"===d.name?f.webview===!0?a=n: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("animate",["jQuery",window],function(a,b){function c(b){b=b.split(")");var c,e,f,g=a.trim,h=-1,i=b.length-1,j=o?new Float32Array(6):[],k=o?new Float32Array(6):[],l=o?new Float32Array(6):[1,0,0,1,0,0];for(j[0]=j[3]=l[0]=l[3]=1,j[1]=j[2]=j[4]=j[5]=0;++h1?f[1]:f[0];break;case"skewX":k[2]=Math.tan(d(f));break;case"skewY":k[1]=Math.tan(d(f));break;case"matrix":f=f.split(","),k[0]=f[0],k[1]=f[1],k[2]=f[2],k[3]=f[3],k[4]=parseInt(f[4],10),k[5]=parseInt(f[5],10)}l[0]=j[0]*k[0]+j[2]*k[1],l[1]=j[1]*k[0]+j[3]*k[1],l[2]=j[0]*k[2]+j[2]*k[3],l[3]=j[1]*k[2]+j[3]*k[3],l[4]=j[0]*k[4]+j[2]*k[5]+j[4],l[5]=j[1]*k[4]+j[3]*k[5]+j[5],j=[l[0],l[1],l[2],l[3],l[4],l[5]]}return l}function d(a){return~a.indexOf("deg")?parseInt(a,10)*(2*Math.PI/360):~a.indexOf("grad")?parseInt(a,10)*(Math.PI/200):parseFloat(a)}function e(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 f(a,b,c){for(var d,f="",g=a.split(")"),h=0,i=g.length-1;i>h;h++){var j=g[h];if((d=j.match(/(translate([XYZ]|3d)?|rotate)\(([^)]*)/))&&d.length>1)if("rotate"===d[1])-1===d[3].indexOf("deg")&&(j=d[1]+"("+d[3]+"deg");else switch(d[2]){case"X":j=d[1]+"("+e(d[3],b);break;case"Y":j=d[1]+"("+e(d[3],c);break;case"Z":break;default:for(var k=d[3].split(","),l=[b,c,100],m=0,n=k.length;n>m;m++)k[m]=e(k[m],l[m]);j=d[1]+"("+k.join(",")}j=" "+j+")",f+=j}return f=f.replace("%","").replace("+=","")}function g(a){var b=a.match(/(-*[\d|\.]+)(px|deg|rad)*/);return b&&b.length>=1?{num:parseFloat(b[1]),unit:b[2]}:void 0}function h(b){for(var c=b.split(")"),d=[],e=0,f=c.length-1;f>e;e++){var h=l(c[e]);h[1]=a.map(h[1],g),d.push(h)}return function(b){var c="",e=0;return a.each(d,function(f){"scale"===d[f][0]&&(e=1);var g=a.map(d[f][1],function(a){var c=a.num;return 1===e&&(c-=1),e+c*b+(a.unit||"")}).join(",");c+=d[f][0]+"("+g+") "}),c}}function i(b,c,d){var e,g,i=d.indexOf("+=")>=0;return d=f(d,parseFloat(a.css(b,"width"))||0,parseFloat(a.css(b,"height"))||0),i?(e=c&&"none"!==c?c:"matrix(1, 0, 0, 1, 0, 0)",g=h(d)):(e=m(c),g=m(d),e[1].lengthg[1].length&&(g=n(g))),function(a){var b=[],c="";if(i)return c=e+g(a);if(1===a)c=j(g);else{for(var d,f,h=0,k=e[1].length;k>h;h++)d=parseFloat(e[1][h]),f=parseFloat(g[1][h]),b.push(d+(f-d)*a);c=j([e[0],b])}return c}}function j(b){var c,d=[];if(a.isArray(b))return c=b[0],c+"("+b[1].join(k(c)+",")+k(c)+")";for(c in b)d.push(c);return a.map(d,function(a){return a+"("+b[a]+k(a)+")"}).join(" ")}function k(a){return a.indexOf("translate")>=0?"px":a.indexOf("rotate")>=0?"deg":""}function l(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 m(a){var b=[];return a&&"none"!==a?(b=p?l(new p(a).toString()):["matrix",c(a)],a.indexOf("3d")>=0&&b[0].indexOf("3d")<0&&(b=n(b)),b):["matrix",["1","0","0","1","0","0"]]}function n(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"]]}var o="Float32Array"in window,p=b.WebKitCSSMatrix||b.MSCSSMatrix||b.OCSSMatrix||b.MozMatrix||b.CSSMatrix;return a.fx.step.transform=function(b){b.rateFn=b.rateFn||i(b.elem,b.start,b.end),a.style(b.elem,"transform",b.rateFn(b.pos))},{toMatrix:m,toMatrix3d:n}}),eg.module("css",["jQuery",document],function(a,b){if(!a.cssHooks)throw new Error("jQuery 1.4.3+ is needed for this plugin to work");if(!(a.fn&&a.fn.jquery&&a.fn.jquery.replace(/\./,"")>="18")){var c=["Webkit","Moz","O","ms"],d=["transitionProperty","transitionDuration","transition","transform","transitionTimingFunction"],e=function(){for(var a=(b.head||b.getElementsByTagName("head")[0]).style,d=0,e=c.length;e>d;d++)if(c[d]+"Transition"in a)return c[d]}();if(e){for(var f=function(b){var c=b.charAt(0).toUpperCase()+b.slice(1),d=e+c,f="ms"===e?"Ms"+c:d;a.cssHooks[c]=a.cssHooks[e.toLowerCase()+c]=a.cssHooks[b]={get:function(b,c){return c?a.css(b,f):b.style[d]},set:function(a,b){a.style[d]=b}}},g=0,h=d.length;h>g;g++)f(d[g]);return{vendorPrefix:e,setCssHooks:f}}}}),eg.module("persist",["jQuery",eg,window,document],function(a,b,c,d){function e(a){s=s||a.originalEvent&&a.originalEvent.persisted,!s&&t?r.trigger("persist"):f()}function f(){i(null)}function g(){var a,b={},c=!1;if(u?(a=l.state,c="string"==typeof a&&"null"!==a):(a=v.getItem(m.href+p),c=a&&a.length>0),c)try{if(b=o.parse(a),"object"!==jQuery.type(b)||b instanceof Array)throw new Error}catch(d){console.warn("window.history or session/localStorage has no valid format data to be handled in persist.")}return b}function h(a){var b=g()[a];return("null"===b||"undefined"==typeof b)&&(b=null),b}function i(a){if(u)try{l.replaceState(null===a?null:o.stringify(a),d.title,m.href)}catch(b){console.warn(b.message)}else a?v.setItem(m.href+p,o.stringify(a)):v.removeItem(m.href+p);a?r.attr(p,!0):r.attr(p,null)}function j(a,b){var c=g();c[a]=b,i(c)}var k=c.performance,l=c.history,m=c.location,n=c.navigator.userAgent,o=c.JSON,p="___persist___",q="KEY"+p,r=a(c),s=r.attr(p)===!0,t=k&&k.navigation&&k.navigation.type===(k.navigation.TYPE_BACK_FORWARD||2),u="replaceState"in l&&"state"in l,v=function(){if(!u){if("sessionStorage"in c){var a="__tmp__"+p;return sessionStorage.setItem(a,p),sessionStorage.getItem(a)===p?sessionStorage:localStorage}return c.localStorage}}();return(u||v)&&(o||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"))?(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&&j(b,c),h(b)},a.persist.isNeeded=function(){var c=b.agent(n).os,d=!0;return("ios"===c.name||"android"===c.name&&parseFloat(c.version)<4.4)&&(d=!1),a.persist.isNeeded=function(){return d},d},!t&&f(),a.event.special.persist={setup:function(){r.on("pageshow",e)},teardown:function(){r.off("pageshow",e)},trigger:function(a){a.state=h(q)}},{isBackForwardNavigated:t,onPageshow:e,reset:f,getState:g,setState:i,persist:a.persist,isNeeded:a.persist.isNeeded,GLOBALKEY:q}):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,c,d){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("tap"===a.type)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),this._animateBy(this._getNextOffsetPos([e*(a.deltaX<0?-1:1)*d[0],g*(a.deltaY<0?-1:1)*d[1]]),this._animationEnd,!1,null,a)}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)},_animationEnd:function(){var b=this._pos,c=this.options.min,d=this.options.max;this._animateTo([Math.min(d[0],Math.max(c[0],b[0])),Math.min(d[1],Math.max(c[1],b[1]))],a.proxy(this.trigger,this,"animationEnd"),!0,null)},_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},_animateBy:function(a,b,c,d,e){var f=this._pos;return this._animateTo([f[0]+a[0],f[1]+a[1]],b,c,d,e)},_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],b},_isCircular:function(a,b,c,d){return a[0]&&b[1]d[0]||a[2]&&b[1]>d[1]||a[3]&&b[0]f?f:this.options.maximumDuration;var o=a.proxy(function(a){this._status.animationParam=null,h[0]=Math.round(m[0]),h[1]=Math.round(m[1]),h=this._getCircularPos(h,i,j,k),!a&&this._setInterrupt(!1),d()},this);if(0===n[0]&&0===n[1])return o(!e);g={duration:f,depaPos:h.concat(),destPos:m,isBounce:e,isCircular:l,done:o,hammerEvent:c.hammerEvent};var p=this.trigger("animationStart",g);if(l&&!p)throw new Error("You can't stop the 'animation' event when 'circular' is true.");if(g.depaPos=h,g.startTime=(new Date).getTime(),this._status.animationParam=g,p)if(g.duration){var q=this._status.animationParam,r=this;!function s(){return r._raf=null,r._frame(q)>=1?o(!0):void(r._raf=b.requestAnimationFrame(s))}()}else this._triggerChange(g.destPos,!1),o(!e)},_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(b){var c;a.each(["bounce","margin","circular"],function(d,e){c=b[e],null!=c&&(b[e]=a.isArray(c)?2===c.length?c.concat(c):c.concat():/string|number|boolean/.test(typeof c)?[c,c,c,c]:null)}),a.extend(this.options,b)},_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],this._animationEnd,!1,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].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,f){this.$wrapper=a(c);var g=this.$wrapper.children();if(!g.length)throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized.");a.extend(this.options={hwAccelerable:b.isHWAccelerable(),prefix:"eg-flick",deceleration:6e-4,horizontal:!0,circular:!1,previewPadding:[0,0],threshold:40,duration:100,panelEffect:a.easing.easeOutCubic,defaultIndex:0,inputType:["touch","mouse"]},d);var i=this.options.previewPadding;"number"==typeof i?i=this.options.previewPadding=[i,i]:i.constructor!==Array&&(i=this.options.previewPadding=[0,0]),this._conf={panel:{$list:g,index:0,no:0,size:0,count:0,origCount:0,changed:!1,animating:!1,minCount:i[0]+i[1]>0?5:3},touch:{holdPos:[0,0],destPos:[0,0],distance:0,direction:null,lastPos:0},customEvent:{flick:!0,restore:!1,restoreCall:!1},useLayerHack:this.options.hwAccelerable&&!h,dirData:[],indexToMove:0,eventPrefix:f||"",$dummyAnchor:null},a([["LEFT","RIGHT"],["UP","DOWN"]][+!this.options.horizontal]).each(a.proxy(function(a,b){this._conf.dirData.push(e["DIRECTION_"+b])},this)),!b._hasClickBug()&&(this._setPointerEvents=a.noop),this._build(),this._bindEvents(),this._applyPanelsCss(),this._arrangePanels(),this.options.hwAccelerable&&h&&this._setHint(),this._adjustContainerCss("end")},_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;this._setPadding(f,!0);var j=this._getDataByDirection([b.size,"100%"]);d.addClass(g+"-panel").css({position:"absolute",width:j[0],height:j[1],top:0,left:0}),a="position:relative;z-index:2000;width:100%;height:100%;"+(h?"":"top:"+f[0]+"px;"),this.$container=d.wrapAll("
").parent(),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}).bind(this.$wrapper,{scale:this._getDataByDirection([-1,0]), +direction:e["DIRECTION_"+(h?"HORIZONTAL":"VERTICAL")],interruptable:!1,inputType:c.inputType}),this._setDefaultPanel(c.defaultIndex)},_setPadding:function(a,b){var c=this.options.horizontal,d=this._conf.panel;d.size=this.$wrapper[c?"outerWidth":"height"]()-(a[0]+a[1]);var e={padding:(c?"0 "+a.reverse().join("px 0 "):a.join("px 0 "))+"px"};b?e.overflow="hidden":c||this.$container.css("top",a[0]),this.$wrapper.css(e)},_addClonePanels:function(){var a,b=this._conf.panel,c=b.origCount,d=b.minCount-c,e=b.$list;if(this.options.circular&&c0&&d>=a&&this._movePanelPosition(a,!0),this._movePanelPosition(this._getBasePositionIndex(),!1),c.no=a):a>0&&d>=a&&(c.no=c.index=a,b=[-(c.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=this._conf,d=c.panel,e=c.touch,f=c.dirData;this.options.circular&&(c.customEvent.flick=!1,a&&(b&&(e.direction=f[+!Boolean(b>0)]),this._arrangePanelPosition(e.direction,b)),d.index=this._getBasePositionIndex(),c.customEvent.flick=!!this._setMovableCoord("setTo",[d.size*d.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&&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!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(){var a=this._conf.panel;return a.index=Math.floor(a.count/2-.1)},_bindEvents:function(){this._mcInst.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)})},_holdHandler:function(a){this._conf.touch.holdPos=a.pos,this._conf.panel.changed=!1,this._adjustContainerCss("start",a.pos)},_changeHandler:function(b){var c,d,e=this._conf,g=e.touch,h=b.pos,i=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&&(i=this._triggerEvent(f.flick,{pos:b.pos,holding:b.holding,direction:c||g.direction})),(i||null===i)&&this._setTranslate([-h[+!this.options.horizontal],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?b.prevIndex:b.index-d,b.no=b.prevNo>=0?b.prevNo:b.no-d):(b.index+=d,b.no+=d),b.no>c?b.no=0:b.no<0&&(b.no=c)},_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 this._getDataByDirection(a),{x:this._getUnitValue(a[0]),y:this._getUnitValue(a[1])}},_setTranslate:function(a){var b=this.options;g||b.horizontal||(a[0]+=b.previewPadding[0]),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(){return Math.abs(this._conf.touch.distance)>=this.options.threshold},_triggerEvent:function(b,c){var d=this._conf,e=d.panel;return this.trigger(d.eventPrefix+b,a.extend({eventType:b,index:e.index,no:e.no,direction:d.touch.direction},c))},_getElement:function(b,c,d){var e,f,g,h=this._conf.panel,i=this.options.circular,j=h.index,k=b===this._conf.dirData[0],l=null;return d?(e=h.count,f=j):(e=h.origCount,f=h.no),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?"index":"no"]},getElement:function(){var b=this._conf.panel;return a(b.$list[b.index])},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.panel,d=this.options;return c.animating?void 0:(this._setValueToMove(a),(d.circular||null!=this[a?"getNextIndex":"getPrevIndex"]())&&this._movePanelByPhase("setBy",[c.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.panel,f=this.options.circular,g=e.index;return a=this._getNumValue(a,-1),0>a||a>=e.origCount||a===e.no||e.animating?this:(e.prevIndex=g,e.prevNo=e.no,f?(c=a-e.no,d=c>0,Math.abs(c)>(d?e.count-(g+1):g)&&(c+=(d?-1:1)*e.count),e.no=a):(c=a-g,e.no=e.index=a),this._conf.indexToMove=c,this._setValueToMove(d),this._movePanelByPhase(f?"setBy":"setTo",[e.size*(f?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.size?(c.customEvent.restoreCall=!0,a=this._getNumValue(a,this.options.duration),this._setPanelNo(!0),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._setPanelNo(!0),c.touch.distance=c.indexToMove=0,d.prevIndex=d.prevNo=-1),this}})}),eg.module("infiniteGrid",["jQuery",eg,window,document,"Outlayer"],function(a,b,c,d,e){function f(b,c,d){var e;return a.each(d,function(d,f){e=c[f],null!=e&&(b[f]=a.isArray(e)?a.merge([],e):a.isPlainObject(e)?a.extend(!0,{},e):e)}),b}if(!e)return void(b.InfiniteGrid=b.Class({}));var g=e.create("InfiniteGrid");a.extend(g.prototype,{_resetLayout:function(){this._isLayoutInited||this._registGroupKey(this.options.defaultGroupKey,this.items),this.element.style.width=null,this.getSize(),this._measureColumns()},_getContainerSize:function(){return{height:Math.max.apply(Math,this._appendCols),width:this.size.innerWidth}},_getItemLayoutPosition:function(b){this._equalItemSize?b.size=this._equalItemSize:b.getSize(),null==b.isAppend&&(b.isAppend=!0);var c,d=parseInt(b.size.outerHeight,10),e=b.isAppend,f=e?this._appendCols:this._prependCols,g=Math[e?"min":"max"].apply(Math,f);if(e)c=a.inArray(g,f);else for(var h=f.length;h-->=0;)if(f[h]===g){c=h;break}return f[c]=g+(e?d:-d),{x:this.columnWidth*c,y:e?g:g-d}},resetLayout:function(){this._resetLayout(),this._isLayoutInited=!0},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.outerHeight:-e):0;return e},_getMinY:function(b){return Math.min.apply(Math,a.map(b,function(a){return a?a.position.y:0}))},_measureColumns:function(){var a=this.size.innerWidth,b=this._getColumnWidth(),c=a/b,d=b-a%b;for(c=Math.max(Math[d&&1>=d?"round":"floor"](c),1),this._appendCols=[],this._prependCols=[];c--;)this._appendCols.push(0),this._prependCols.push(0)},_getColumnWidth:function(){var a,b=this.items[0]&&this.items[0].element;return a=b?getSize(b):{outerWidth:0,outerHeight:0},this.options.isEqualSize&&(this._equalItemSize=a),this.columnWidth=a.outerWidth||this.size.outerWidth,this.columnWidth},_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},clone:function(b,c){return f(b,c,["_isLayoutInited","_equalItemSize","_appendCols","_prependCols","columnWidth","size","options"]),b.items=b.items||[],b.items.length=c.items.length,a.each(c.items,function(a){b.items[a]=f(b.items[a]||{},c.items[a],["position","size","isAppend","groupKey"])}),b},itemize:function(a,b){var c=this._itemize(a);return this._registGroupKey(b,c),c},_registGroupKey:function(a,b){if(null!=a)for(var c,d=0;c=b[d++];)c.groupKey=a},destroy:function(){this.off(),e.prototype.destroy.apply(this)}});var h={layoutComplete:"layoutComplete",append:"append",prepend:"prepend"};b.InfiniteGrid=b.Class.extend(b.Component,{_events:function(){return h},construct:function(d,e,f){this.options=a.extend({isEqualSize:!1,defaultGroupKey:null,count:30,threshold:300},e),this.options.transitionDuration=0,this.options.isInitLayout=!1,this.options.isResizeBound=!1,d instanceof a&&(d=d.get(0)),this._prefix=f||"",this.core=new g(d,this.options).on(h.layoutComplete,a.proxy(this._onlayoutComplete,this)),this.$view=a(c),this._reset(),this.core.$element.children().length>0&&this.layout(),this._onResize=a.proxy(this._onResize,this),this._onScroll=a.proxy(this._onScroll,this),this._isIos="ios"===b.agent().os.name,this._prevScrollTop=0,this._topElement=null,this._bottomElement=null,this._refreshViewport(),this.$view.on("resize",this._onResize),this.$view.on("scroll",this._onScroll)},_getScrollTop:function(){return d.body.scrollTop||d.documentElement.scrollTop},_onScroll:function(){if(!this.isProcessing()){var a=this._getScrollTop(),b=this._prevScrollTop;if(!(this._isIos&&0===a||b===a)){var c,d;if(a>b)c=this._bottomElement||this.getBottomElement(),d=c.getBoundingClientRect(),d.top<=this._clientHeight+this.options.threshold&&this.trigger(this._prefix+h.append,{scrollTop:a});else if(this.isRecycling()&&this._removedContent>0&&(c=this._topElement||this.getTopElement())&&(d=c.getBoundingClientRect(),d.bottom>=-this.options.threshold)){var e=this.fit();e>0&&(a-=e,this.$view.scrollTop(a)),this.trigger(this._prefix+h.prepend,{scrollTop:a})}this._prevScrollTop=a}}},_onResize:function(){function a(){b._refreshViewport(),b.core.element.style.width=null,b.core.needsResizeLayout()&&b.layout(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},_refreshViewport:function(){this._clientHeight=this.$view.height()},getStatus:function(){var a,b=[];for(a in this)this.hasOwnProperty(a)&&/^_/.test(a)&&b.push(a);return{core:this.core.clone({},this.core),data:f({},this,b),html:this.core.$element.html(),cssText:this.core.element.style.cssText}},setStatus:function(b){return this.core.element.style.cssText=b.cssText,this.core.$element.html(b.html),this.core.items=this.core.itemize(this.core.$element.children().toArray()),this.core.clone(this.core,b.core),a.extend(this,b.data),this},isProcessing:function(){return this._isProcessing},isRecycling:function(){return this.core.options.count>0&&this._isRecycling},getGroupKeys:function(){var a=[];if(this.core._isLayoutInited)for(var b,c=0;b=this.core.items[c++];)a.push(b.groupKey);return a},layout:function(){this._isProcessing=!0,this._isAppendType=!0;for(var a,b=0;a=this.core.items[b++];)a.isAppend=!0;return this.core.layout(),this},append:function(b,c){return this._isProcessing||0===b.length?void 0:(b=a(b),this._isProcessing=!0,this._isRecycling||(this._isRecycling=this.core.items.length+b.length>=this.core.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.core.$element.empty(),this.core.items.length=0,this._reset(),this.layout(),this},_getTopItem:function(){var b=null,c=1/0;return a.each(this.core.getColItems(!1),function(a,d){d&&d.position.yc&&(c=d.position.y+d.size.outerHeight,b=d)}),b},getBottomElement:function(){var a=this._getBottomItem();return a&&a.element},_onlayoutComplete:function(a){for(var b,c=0,d=this._isAppendType,e=0;b=a[e++];)"undefined"!=typeof b.oldVisibility&&(b.element.style.visibility=b.oldVisibility,delete b.oldVisibility);this._topElement=this.getTopElement(),this._bottomElement=this.getBottomElement(),d===!1&&(this._isFitted=!1,this._fit(!0),c=a.length>=this.core.items.length?0:this.core.items[a.length].position.y,c>0&&(this._prevScrollTop=this._getScrollTop()+c,this.$view.scrollTop(this._prevScrollTop))),this._reset(!0),this.trigger(this._prefix+h.layoutComplete,{target:a.concat(),isAppend:d,distance:c,croppedCount:this._removedContent})},_insert:function(b,c,d){if(0!==b.length){this._isAppendType=d;for(var e,f=b.toArray(),g=a(f),h=0,i=this.core.itemize(f,c);e=i[h++];)e.isAppend=d,e.oldVisibility=e.element.style.visibility,e.element.style.visibility="hidden";d?this.core.items=this.core.items.concat(i):(this.core.items=i.concat(this.core.items.slice(0)),i=i.reverse()),this.isRecycling()&&this._adjustRange(d,g);var j=0===this.core.$element.children().length;this.core.$element[d?"append":"prepend"](g),j&&this.core.resetLayout();var k=this._checkImageLoaded(g);if(k.length>0)this._waitImageLoaded(i,k);else{var l=this;setTimeout(function(){l.core.layoutItems(i,!0)},0)}}},_adjustRange:function(a,b){var c,d,e=this.core.items.length-this.core.options.count;if(!(0>=e||(d=this._getDelimiterIndex(a,e))<0)){a?(c=this.core.items.slice(0,d),this.core.items=this.core.items.slice(d),this._isFitted=!1):(c=this.core.items.slice(d),this.core.items=this.core.items.slice(0,d));for(var f,g,h=0;f=c[h++];)g=f.element,d=b.index(g),-1!==d?b.splice(d,1):g.parentNode.removeChild(g);this._removedContent+=a?c.length:-c.length}},_getDelimiterIndex:function(a,b){var c,d=this.core.items.length,e=0,f=a?b-1:d-b,g=f+(a?1:-1),h=this.core.items[f].groupKey;if(null!=h&&h===this.core.items[g].groupKey)if(a){for(c=f;c>0&&h===this.core.items[c].groupKey;c--);e=0===c?-1:c+1}else{for(c=f;d>c&&h===this.core.items[c].groupKey;c++);e=c===d?-1:c}else e=a?g:f;return e},_fit:function(a){if(this.core.options.count<=0)return this._fit=function(){return!1},this._isFitted=!0,!1;if(this._isFitted)return!1;for(var b,c,d=0,e=this.core.updateCols();b=this.core.items[d++];)b.position.y-=e,a&&b.css({top:b.position.y+"px"});return this.core.updateCols(!0),c=this.core._getContainerSize().height,a&&this.core._setContainerMeasure(c,!1),this._isFitted=!0,!0},fit:function(){var a=this._getTopItem(),b=a?a.position.y:0;return this._fit(!0),b},_reset:function(a){a||(this._isFitted=!0,this._isRecycling=!1,this._removedContent=0),this._isAppendType=null,this._isProcessing=!1},_checkImageLoaded:function(b){var c=[];return b.each(function(b,d){"IMG"===d.nodeName?!d.complete&&c.push(d):!d.nodeType||1!==d.nodeType&&9!==d.nodeType&&11!==d.nodeType||(c=c.concat(a(d).find("img").filter(function(a,b){return!b.complete}).toArray()))}),c},_waitImageLoaded:function(b,c){var d=this.core,e=c.length,f=function(c){e--,a(c.target).off("load error"),0>=e&&d.layoutItems(b,!0)};a.each(c,function(b,c){a(c).on("load error",f)})},destroy:function(){this.core&&(this.core.destroy(),this.core=null),this.$view.off("resize",this._onResize).off("scroll",this._onScroll),this.off()}})}); \ 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 0000000..9c2995e --- /dev/null +++ b/dist/pkgd/eg.pkgd.min.js @@ -0,0 +1,48 @@ +/** +* 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.1.0 +* @SHA-1 fb4a69e (1.1.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 +* bower_components/get-style-property/get-style-property.js +* bower_components/get-size/get-size.js +* bower_components/matches-selector/matches-selector.js +* bower_components/eventEmitter/EventEmitter.js +* bower_components/eventie/eventie.js +* bower_components/doc-ready/doc-ready.js +* bower_components/fizzy-ui-utils/utils.js +* bower_components/outlayer/item.js +* bower_components/outlayer/outlayer.js +* src/module.js +* src/eg.js +* src/class.js +* src/component.js +* src/customEvent/rotate.js +* src/customEvent/scrollEnd.js +* src/hook/animate.js +* src/hook/css.js +* src/plugin/apply.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.distancee;e++)if(b=c[e]+a,"string"==typeof d[b])return b}}var c="Webkit Moz ms Ms O".split(" "),d=document.documentElement.style;"function"==typeof define&&define.amd?define(function(){return b}):"object"==typeof exports?module.exports=b:a.getStyleProperty=b}(window),function(a){function b(a){var b=parseFloat(a),c=-1===a.indexOf("%")&&!isNaN(b);return c&&b}function c(){}function d(){for(var a={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},b=0,c=g.length;c>b;b++){var d=g[b];a[d]=0}return a}function e(c){function e(){if(!m){m=!0;var d=a.getComputedStyle;if(j=function(){var a=d?function(a){return d(a,null)}:function(a){return a.currentStyle};return function(b){var c=a(b);return c||f("Style returned "+c+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),c}}(),k=c("boxSizing")){var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style[k]="border-box";var g=document.body||document.documentElement;g.appendChild(e);var h=j(e);l=200===b(h.width),g.removeChild(e)}}}function h(a){if(e(),"string"==typeof a&&(a=document.querySelector(a)),a&&"object"==typeof a&&a.nodeType){var c=j(a);if("none"===c.display)return d();var f={};f.width=a.offsetWidth,f.height=a.offsetHeight;for(var h=f.isBorderBox=!(!k||!c[k]||"border-box"!==c[k]),m=0,n=g.length;n>m;m++){var o=g[m],p=c[o];p=i(a,p);var q=parseFloat(p);f[o]=isNaN(q)?0:q}var r=f.paddingLeft+f.paddingRight,s=f.paddingTop+f.paddingBottom,t=f.marginLeft+f.marginRight,u=f.marginTop+f.marginBottom,v=f.borderLeftWidth+f.borderRightWidth,w=f.borderTopWidth+f.borderBottomWidth,x=h&&l,y=b(c.width);y!==!1&&(f.width=y+(x?0:r+v));var z=b(c.height);return z!==!1&&(f.height=z+(x?0:s+w)),f.innerWidth=f.width-(r+v),f.innerHeight=f.height-(s+w),f.outerWidth=f.width+t,f.outerHeight=f.height+u,f}}function i(b,c){if(a.getComputedStyle||-1===c.indexOf("%"))return c;var d=b.style,e=d.left,f=b.runtimeStyle,g=f&&f.left;return g&&(f.left=b.currentStyle.left),d.left=c,c=d.pixelLeft,d.left=e,g&&(f.left=g),c}var j,k,l,m=!1;return h}var f="undefined"==typeof console?c:function(a){console.error(a)},g=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"];"function"==typeof define&&define.amd?define(["get-style-property/get-style-property"],e):"object"==typeof exports?module.exports=e(require("desandro-get-style-property")):a.getSize=e(a.getStyleProperty)}(window),function(a){function b(a,b){return a[g](b)}function c(a){if(!a.parentNode){var b=document.createDocumentFragment();b.appendChild(a)}}function d(a,b){c(a);for(var d=a.parentNode.querySelectorAll(b),e=0,f=d.length;f>e;e++)if(d[e]===a)return!0;return!1}function e(a,d){return c(a),b(a,d)}var f,g=function(){if(a.matches)return"matches";if(a.matchesSelector)return"matchesSelector";for(var b=["webkit","moz","ms","o"],c=0,d=b.length;d>c;c++){var e=b[c],f=e+"MatchesSelector";if(a[f])return f}}();if(g){var h=document.createElement("div"),i=b(h,"div");f=i?b:e}else f=d;"function"==typeof define&&define.amd?define(function(){return f}):"object"==typeof exports?module.exports=f:window.matchesSelector=f}(Element.prototype),function(){function a(){}function b(a,b){for(var c=a.length;c--;)if(a[c].listener===b)return c;return-1}function c(a){return function(){return this[a].apply(this,arguments)}}var d=a.prototype,e=this,f=e.EventEmitter;d.getListeners=function(a){var b,c,d=this._getEvents();if(a instanceof RegExp){b={};for(c in d)d.hasOwnProperty(c)&&a.test(c)&&(b[c]=d[c])}else b=d[a]||(d[a]=[]);return b},d.flattenListeners=function(a){var b,c=[];for(b=0;ba;a++){var d=g[a];d()}}function e(e){return"complete"===f.readyState?d():(e.bind(f,"DOMContentLoaded",c),e.bind(f,"readystatechange",c),e.bind(a,"load",c)),b}var f=a.document,g=[];b.isReady=!1,"function"==typeof define&&define.amd?define(["eventie/eventie"],e):"object"==typeof exports?module.exports=e(require("eventie")):a.docReady=e(a.eventie)}(window),function(a,b){"function"==typeof define&&define.amd?define(["doc-ready/doc-ready","matches-selector/matches-selector"],function(c,d){return b(a,c,d)}):"object"==typeof exports?module.exports=b(a,require("doc-ready"),require("desandro-matches-selector")):a.fizzyUIUtils=b(a,a.docReady,a.matchesSelector)}(window,function(a,b,c){var d={};d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.modulo=function(a,b){return(a%b+b)%b};var e=Object.prototype.toString;d.isArray=function(a){return"[object Array]"==e.call(a)},d.makeArray=function(a){var b=[];if(d.isArray(a))b=a;else if(a&&"number"==typeof a.length)for(var c=0,e=a.length;e>c;c++)b.push(a[c]);else b.push(a);return b},d.indexOf=Array.prototype.indexOf?function(a,b){return a.indexOf(b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},d.removeFrom=function(a,b){var c=d.indexOf(a,b);-1!=c&&a.splice(c,1)},d.isElement="function"==typeof HTMLElement||"object"==typeof HTMLElement?function(a){return a instanceof HTMLElement}:function(a){return a&&"object"==typeof a&&1==a.nodeType&&"string"==typeof a.nodeName},d.setText=function(){function a(a,c){b=b||(void 0!==document.documentElement.textContent?"textContent":"innerText"),a[b]=c}var b;return a}(),d.getParent=function(a,b){for(;a!=document.body;)if(a=a.parentNode,c(a,b))return a},d.getQueryElement=function(a){return"string"==typeof a?document.querySelector(a):a},d.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},d.filterFindElements=function(a,b){a=d.makeArray(a);for(var e=[],f=0,g=a.length;g>f;f++){var h=a[f];if(d.isElement(h))if(b){c(h,b)&&e.push(h);for(var i=h.querySelectorAll(b),j=0,k=i.length;k>j;j++)e.push(i[j])}else e.push(h)}return e},d.debounceMethod=function(a,b,c){var d=a.prototype[b],e=b+"Timeout";a.prototype[b]=function(){var a=this[e];a&&clearTimeout(a);var b=arguments,f=this;this[e]=setTimeout(function(){d.apply(f,b),delete f[e]},c||100)}},d.toDashed=function(a){return a.replace(/(.)([A-Z])/g,function(a,b,c){return b+"-"+c}).toLowerCase()};var f=a.console;return d.htmlInit=function(c,e){b(function(){for(var b=d.toDashed(e),g=document.querySelectorAll(".js-"+b),h="data-"+b+"-options",i=0,j=g.length;j>i;i++){var k,l=g[i],m=l.getAttribute(h);try{k=m&&JSON.parse(m)}catch(n){f&&f.error("Error parsing "+h+" on "+l.nodeName.toLowerCase()+(l.id?"#"+l.id:"")+": "+n);continue}var o=new c(l,k),p=a.jQuery;p&&p.data(l,e,o)}})},d}),function(a,b){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","get-size/get-size","get-style-property/get-style-property","fizzy-ui-utils/utils"],function(c,d,e,f){return b(a,c,d,e,f)}):"object"==typeof exports?module.exports=b(a,require("wolfy87-eventemitter"),require("get-size"),require("desandro-get-style-property"),require("fizzy-ui-utils")):(a.Outlayer={},a.Outlayer.Item=b(a,a.EventEmitter,a.getSize,a.getStyleProperty,a.fizzyUIUtils))}(window,function(a,b,c,d,e){function f(a){for(var b in a)return!1;return b=null,!0}function g(a,b){a&&(this.element=a,this.layout=b,this.position={x:0,y:0},this._create())}function h(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}var i=a.getComputedStyle,j=i?function(a){return i(a,null)}:function(a){return a.currentStyle},k=d("transition"),l=d("transform"),m=k&&l,n=!!d("perspective"),o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend",transition:"transitionend"}[k],p=["transform","transition","transitionDuration","transitionProperty"],q=function(){for(var a={},b=0,c=p.length;c>b;b++){var e=p[b],f=d(e);f&&f!==e&&(a[e]=f)}return a}();e.extend(g.prototype,b.prototype),g.prototype._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.getSize=function(){this.size=c(this.element)}, +g.prototype.css=function(a){var b=this.element.style;for(var c in a){var d=q[c]||c;b[d]=a[c]}},g.prototype.getPosition=function(){var a=j(this.element),b=this.layout.options,c=b.isOriginLeft,d=b.isOriginTop,e=a[c?"left":"right"],f=a[d?"top":"bottom"],g=this.layout.size,h=-1!=e.indexOf("%")?parseFloat(e)/100*g.width:parseInt(e,10),i=-1!=f.indexOf("%")?parseFloat(f)/100*g.height:parseInt(f,10);h=isNaN(h)?0:h,i=isNaN(i)?0:i,h-=c?g.paddingLeft:g.paddingRight,i-=d?g.paddingTop:g.paddingBottom,this.position.x=h,this.position.y=i},g.prototype.layoutPosition=function(){var a=this.layout.size,b=this.layout.options,c={},d=b.isOriginLeft?"paddingLeft":"paddingRight",e=b.isOriginLeft?"left":"right",f=b.isOriginLeft?"right":"left",g=this.position.x+a[d];c[e]=this.getXValue(g),c[f]="";var h=b.isOriginTop?"paddingTop":"paddingBottom",i=b.isOriginTop?"top":"bottom",j=b.isOriginTop?"bottom":"top",k=this.position.y+a[h];c[i]=this.getYValue(k),c[j]="",this.css(c),this.emitEvent("layout",[this])},g.prototype.getXValue=function(a){var b=this.layout.options;return b.percentPosition&&!b.isHorizontal?a/this.layout.size.width*100+"%":a+"px"},g.prototype.getYValue=function(a){var b=this.layout.options;return b.percentPosition&&b.isHorizontal?a/this.layout.size.height*100+"%":a+"px"},g.prototype._transitionTo=function(a,b){this.getPosition();var c=this.position.x,d=this.position.y,e=parseInt(a,10),f=parseInt(b,10),g=e===this.position.x&&f===this.position.y;if(this.setPosition(a,b),g&&!this.isTransitioning)return void this.layoutPosition();var h=a-c,i=b-d,j={};j.transform=this.getTranslate(h,i),this.transition({to:j,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},g.prototype.getTranslate=function(a,b){var c=this.layout.options;return a=c.isOriginLeft?a:-a,b=c.isOriginTop?b:-b,n?"translate3d("+a+"px, "+b+"px, 0)":"translate("+a+"px, "+b+"px)"},g.prototype.goTo=function(a,b){this.setPosition(a,b),this.layoutPosition()},g.prototype.moveTo=m?g.prototype._transitionTo:g.prototype.goTo,g.prototype.setPosition=function(a,b){this.position.x=parseInt(a,10),this.position.y=parseInt(b,10)},g.prototype._nonTransition=function(a){this.css(a.to),a.isCleaning&&this._removeStyles(a.to);for(var b in a.onTransitionEnd)a.onTransitionEnd[b].call(this)},g.prototype._transition=function(a){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(a);var b=this._transn;for(var c in a.onTransitionEnd)b.onEnd[c]=a.onTransitionEnd[c];for(c in a.to)b.ingProperties[c]=!0,a.isCleaning&&(b.clean[c]=!0);if(a.from){this.css(a.from);var d=this.element.offsetHeight;d=null}this.enableTransition(a.to),this.css(a.to),this.isTransitioning=!0};var r="opacity,"+h(q.transform||"transform");g.prototype.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:r,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(o,this,!1))},g.prototype.transition=g.prototype[k?"_transition":"_nonTransition"],g.prototype.onwebkitTransitionEnd=function(a){this.ontransitionend(a)},g.prototype.onotransitionend=function(a){this.ontransitionend(a)};var s={"-webkit-transform":"transform","-moz-transform":"transform","-o-transform":"transform"};g.prototype.ontransitionend=function(a){if(a.target===this.element){var b=this._transn,c=s[a.propertyName]||a.propertyName;if(delete b.ingProperties[c],f(b.ingProperties)&&this.disableTransition(),c in b.clean&&(this.element.style[a.propertyName]="",delete b.clean[c]),c in b.onEnd){var d=b.onEnd[c];d.call(this),delete b.onEnd[c]}this.emitEvent("transitionEnd",[this])}},g.prototype.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(o,this,!1),this.isTransitioning=!1},g.prototype._removeStyles=function(a){var b={};for(var c in a)b[c]="";this.css(b)};var t={transitionProperty:"",transitionDuration:""};return g.prototype.removeTransitionStyles=function(){this.css(t)},g.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},g.prototype.remove=function(){if(!k||!parseFloat(this.layout.options.transitionDuration))return void this.removeElem();var a=this;this.once("transitionEnd",function(){a.removeElem()}),this.hide()},g.prototype.reveal=function(){delete this.isHidden,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("visibleStyle");b[c]=this.onRevealTransitionEnd,this.transition({from:a.hiddenStyle,to:a.visibleStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},g.prototype.getHideRevealTransitionEndProperty=function(a){var b=this.layout.options[a];if(b.opacity)return"opacity";for(var c in b)return c},g.prototype.hide=function(){this.isHidden=!0,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("hiddenStyle");b[c]=this.onHideTransitionEnd,this.transition({from:a.visibleStyle,to:a.hiddenStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},g.prototype.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},g}),function(a,b){"function"==typeof define&&define.amd?define(["eventie/eventie","eventEmitter/EventEmitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(c,d,e,f,g){return b(a,c,d,e,f,g)}):"object"==typeof exports?module.exports=b(a,require("eventie"),require("wolfy87-eventemitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):a.Outlayer=b(a,a.eventie,a.EventEmitter,a.getSize,a.fizzyUIUtils,a.Outlayer.Item)}(window,function(a,b,c,d,e,f){function g(a,b){var c=e.getQueryElement(a);if(!c)return void(h&&h.error("Bad element for "+this.constructor.namespace+": "+(c||a)));this.element=c,i&&(this.$element=i(this.element)),this.options=e.extend({},this.constructor.defaults),this.option(b);var d=++k;this.element.outlayerGUID=d,l[d]=this,this._create(),this.options.isInitLayout&&this.layout()}var h=a.console,i=a.jQuery,j=function(){},k=0,l={};return g.namespace="outlayer",g.Item=f,g.defaults={containerStyle:{position:"relative"},isInitLayout:!0,isOriginLeft:!0,isOriginTop:!0,isResizeBound:!0,isResizingContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}},e.extend(g.prototype,c.prototype),g.prototype.option=function(a){e.extend(this.options,a)},g.prototype._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),e.extend(this.element.style,this.options.containerStyle),this.options.isResizeBound&&this.bindResize()},g.prototype.reloadItems=function(){this.items=this._itemize(this.element.children)},g.prototype._itemize=function(a){for(var b=this._filterFindItemElements(a),c=this.constructor.Item,d=[],e=0,f=b.length;f>e;e++){var g=b[e],h=new c(g,this);d.push(h)}return d},g.prototype._filterFindItemElements=function(a){return e.filterFindElements(a,this.options.itemSelector)},g.prototype.getItemElements=function(){for(var a=[],b=0,c=this.items.length;c>b;b++)a.push(this.items[b].element);return a},g.prototype.layout=function(){this._resetLayout(),this._manageStamps();var a=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;this.layoutItems(this.items,a),this._isLayoutInited=!0},g.prototype._init=g.prototype.layout,g.prototype._resetLayout=function(){this.getSize()},g.prototype.getSize=function(){this.size=d(this.element)},g.prototype._getMeasurement=function(a,b){var c,f=this.options[a];f?("string"==typeof f?c=this.element.querySelector(f):e.isElement(f)&&(c=f),this[a]=c?d(c)[b]:f):this[a]=0},g.prototype.layoutItems=function(a,b){a=this._getItemsForLayout(a),this._layoutItems(a,b),this._postLayout()},g.prototype._getItemsForLayout=function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];e.isIgnored||b.push(e)}return b},g.prototype._layoutItems=function(a,b){if(this._emitCompleteOnItems("layout",a),a&&a.length){for(var c=[],d=0,e=a.length;e>d;d++){var f=a[d],g=this._getItemLayoutPosition(f);g.item=f,g.isInstant=b||f.isLayoutInstant,c.push(g)}this._processLayoutQueue(c)}},g.prototype._getItemLayoutPosition=function(){return{x:0,y:0}},g.prototype._processLayoutQueue=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];this._positionItem(d.item,d.x,d.y,d.isInstant)}},g.prototype._positionItem=function(a,b,c,d){d?a.goTo(b,c):a.moveTo(b,c)},g.prototype._postLayout=function(){this.resizeContainer()},g.prototype.resizeContainer=function(){if(this.options.isResizingContainer){var a=this._getContainerSize();a&&(this._setContainerMeasure(a.width,!0),this._setContainerMeasure(a.height,!1))}},g.prototype._getContainerSize=j,g.prototype._setContainerMeasure=function(a,b){if(void 0!==a){var c=this.size;c.isBorderBox&&(a+=b?c.paddingLeft+c.paddingRight+c.borderLeftWidth+c.borderRightWidth:c.paddingBottom+c.paddingTop+c.borderTopWidth+c.borderBottomWidth),a=Math.max(a,0),this.element.style[b?"width":"height"]=a+"px"}},g.prototype._emitCompleteOnItems=function(a,b){function c(){e.dispatchEvent(a+"Complete",null,[b])}function d(){g++,g===f&&c()}var e=this,f=b.length;if(!b||!f)return void c();for(var g=0,h=0,i=b.length;i>h;h++){var j=b[h];j.once(a,d)}},g.prototype.dispatchEvent=function(a,b,c){var d=b?[b].concat(c):c;if(this.emitEvent(a,d),i)if(this.$element=this.$element||i(this.element),b){var e=i.Event(b);e.type=a,this.$element.trigger(e,c)}else this.$element.trigger(a,c)},g.prototype.ignore=function(a){var b=this.getItem(a);b&&(b.isIgnored=!0)},g.prototype.unignore=function(a){var b=this.getItem(a);b&&delete b.isIgnored},g.prototype.stamp=function(a){if(a=this._find(a)){this.stamps=this.stamps.concat(a);for(var b=0,c=a.length;c>b;b++){var d=a[b];this.ignore(d)}}},g.prototype.unstamp=function(a){if(a=this._find(a))for(var b=0,c=a.length;c>b;b++){var d=a[b];e.removeFrom(this.stamps,d),this.unignore(d)}},g.prototype._find=function(a){return a?("string"==typeof a&&(a=this.element.querySelectorAll(a)),a=e.makeArray(a)):void 0},g.prototype._manageStamps=function(){if(this.stamps&&this.stamps.length){this._getBoundingRect();for(var a=0,b=this.stamps.length;b>a;a++){var c=this.stamps[a];this._manageStamp(c)}}},g.prototype._getBoundingRect=function(){var a=this.element.getBoundingClientRect(),b=this.size;this._boundingRect={left:a.left+b.paddingLeft+b.borderLeftWidth,top:a.top+b.paddingTop+b.borderTopWidth,right:a.right-(b.paddingRight+b.borderRightWidth),bottom:a.bottom-(b.paddingBottom+b.borderBottomWidth)}},g.prototype._manageStamp=j,g.prototype._getElementOffset=function(a){var b=a.getBoundingClientRect(),c=this._boundingRect,e=d(a),f={left:b.left-c.left-e.marginLeft,top:b.top-c.top-e.marginTop,right:c.right-b.right-e.marginRight,bottom:c.bottom-b.bottom-e.marginBottom};return f},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.bindResize=function(){this.isResizeBound||(b.bind(a,"resize",this),this.isResizeBound=!0)},g.prototype.unbindResize=function(){this.isResizeBound&&b.unbind(a,"resize",this),this.isResizeBound=!1},g.prototype.onresize=function(){function a(){b.resize(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},g.prototype.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},g.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a;return b&&a.innerWidth!==this.size.innerWidth},g.prototype.addItems=function(a){var b=this._itemize(a);return b.length&&(this.items=this.items.concat(b)),b},g.prototype.appended=function(a){var b=this.addItems(a);b.length&&(this.layoutItems(b,!0),this.reveal(b))},g.prototype.prepended=function(a){var b=this._itemize(a);if(b.length){var c=this.items.slice(0);this.items=b.concat(c),this._resetLayout(),this._manageStamps(),this.layoutItems(b,!0),this.reveal(b),this.layoutItems(c)}},g.prototype.reveal=function(a){this._emitCompleteOnItems("reveal",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.reveal()}},g.prototype.hide=function(a){this._emitCompleteOnItems("hide",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.hide()}},g.prototype.revealItemElements=function(a){var b=this.getItems(a);this.reveal(b)},g.prototype.hideItemElements=function(a){var b=this.getItems(a);this.hide(b)},g.prototype.getItem=function(a){for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];if(d.element===a)return d}},g.prototype.getItems=function(a){a=e.makeArray(a);for(var b=[],c=0,d=a.length;d>c;c++){var f=a[c],g=this.getItem(f);g&&b.push(g)}return b},g.prototype.remove=function(a){var b=this.getItems(a);if(this._emitCompleteOnItems("remove",b),b&&b.length)for(var c=0,d=b.length;d>c;c++){var f=b[c];f.remove(),e.removeFrom(this.items,f)}},g.prototype.destroy=function(){var a=this.element.style;a.height="",a.position="",a.width="";for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];d.destroy()}this.unbindResize();var e=this.element.outlayerGUID;delete l[e],delete this.element.outlayerGUID,i&&i.removeData(this.element,this.constructor.namespace)},g.data=function(a){a=e.getQueryElement(a);var b=a&&a.outlayerGUID;return b&&l[b]},g.create=function(a,b){function c(){g.apply(this,arguments)}return Object.create?c.prototype=Object.create(g.prototype):e.extend(c.prototype,g.prototype),c.prototype.constructor=c,c.defaults=e.extend({},g.defaults),e.extend(c.defaults,b),c.prototype.settings={},c.namespace=a,c.data=g.data,c.Item=function(){f.apply(this,arguments)},c.Item.prototype=new f,e.htmlInit(c,a),i&&i.bridget&&i.bridget(a,c),c},g.Item=f,g}),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._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/"},Outlayer:{url:"https://github.com/metafizzy/outlayer/"}},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],function(a,b,c){function d(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 e=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,f=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(e&&!f){var g={},h=e;e=function(a){function b(){g[c]&&a()}var c=h(b);return g[c]=!0,c},f=function(a){delete g[a]}}else e&&f||(e=function(a){return c.setTimeout(a,16)},f=c.clearTimeout);b.VERSION="1.1.0",b.hook={};var i={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"}}},j={getBrowserName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.browser)},getBrowserVersion:function(a){var b,c;return a?(c=this.getBrowserRule(a).versionSearch||a,b=this.extractBrowserVersion(c,this.ua)):void 0},extractBrowserVersion:function(a,b){var c,d,e=i.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},getOSName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.os)},getOSVersion:function(a){var b,c,d,e,f=this.ua,g=this.getOSRule(a)||{},h=i.defaultString.os.version;return a?g.versionAlias?g.versionAlias:(c=g.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||h):void 0},getOSRule:function(a){return this.getRule(i.os,a)},getBrowserRule:function(a){return this.getRule(i.browser,a)},getRule:function(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&&this.isMatched(this.ua,c):d)return e},getIdentityStringFromArray:function(a,b){for(var c,d=0;c=a[d];d++)if(this.isMatched(this.ua,c.criteria))return c.identity||b.name;return b.name},isMatched:function(a,b){return b&&b.test?!!b.test(a):a.indexOf(b)>-1},isWebview:function(){for(var a,b,c=this.ua,d=i.webview,e=!1,f=0;b=d[f];f++)if(this.isMatched(c,b.criteria)&&(a=this.extractBrowserVersion(b.browserVersionSearch,c),this.isMatched(c,b.webviewToken)||this.isMatched(a,b.webviewBrowserVersion))){e=!0;break}return e}};j.create=function(a){j.ua=a;var b={os:{},browser:{}};return b.browser.name=j.getBrowserName(i.browser),b.browser.version=j.getBrowserVersion(b.browser.name),b.os.name=j.getOSName(i.os),b.os.version=j.getOSVersion(b.os.name),b.browser.webview=j.isWebview(),b.browser.name=b.browser.name.toLowerCase(),b.os.name=b.os.name.toLowerCase(),b},b.agent=function(){var a=j.create(c.navigator.userAgent);return d(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,e=b.agent(),f=e.os.version,g=e.browser.name,h=e.browser.version;return-1!==g.indexOf("chrome")?c=h>="25":/ie|edge|firefox|safari|inapp/.test(g)?c=!0:-1!==e.os.name.indexOf("android")&&(a=(j.ua.match(/\(.*\)/)||[null])[0],c=f>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||f>="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)),d(this,"isHWAccelerable",[c,e],c)},b.isTransitional=function(){var a=!1,c=b.agent(),e=c.browser.name;if(/chrome|firefox/.test(e))a=!0;else switch(c.os.name){case"ios":a=/safari|inapp/.test(e)&&parseInt(c.os.version,10)<6;break;case"window":a=-1!==e.indexOf("safari")||-1!==e.indexOf("ie")&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/chrome|firefox|safari/.test(e)}return d(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return d(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return e(a)},b.cancelAnimationFrame=function(a){f(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,h=a):(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,a(c).trigger("rotate"))}function g(a){var b,e,i=m();if("resize"===i)c.setTimeout(function(){f()},0);else{if(b=300,"android"===k.os.name){if(e=d.documentElement.clientWidth,"orientationchange"===a.type&&e===h)return c.setTimeout(function(){g(a)},500),!1;h=e}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),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"ios"===d.name?f.webview===!0?a=n: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("animate",["jQuery",window],function(a,b){function c(b){b=b.split(")");var c,e,f,g=a.trim,h=-1,i=b.length-1,j=o?new Float32Array(6):[],k=o?new Float32Array(6):[],l=o?new Float32Array(6):[1,0,0,1,0,0];for(j[0]=j[3]=l[0]=l[3]=1,j[1]=j[2]=j[4]=j[5]=0;++h1?f[1]:f[0];break;case"skewX":k[2]=Math.tan(d(f));break;case"skewY":k[1]=Math.tan(d(f));break;case"matrix":f=f.split(","),k[0]=f[0],k[1]=f[1],k[2]=f[2],k[3]=f[3],k[4]=parseInt(f[4],10),k[5]=parseInt(f[5],10)}l[0]=j[0]*k[0]+j[2]*k[1],l[1]=j[1]*k[0]+j[3]*k[1],l[2]=j[0]*k[2]+j[2]*k[3],l[3]=j[1]*k[2]+j[3]*k[3],l[4]=j[0]*k[4]+j[2]*k[5]+j[4],l[5]=j[1]*k[4]+j[3]*k[5]+j[5],j=[l[0],l[1],l[2],l[3],l[4],l[5]]}return l}function d(a){return~a.indexOf("deg")?parseInt(a,10)*(2*Math.PI/360):~a.indexOf("grad")?parseInt(a,10)*(Math.PI/200):parseFloat(a)}function e(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 f(a,b,c){for(var d,f="",g=a.split(")"),h=0,i=g.length-1;i>h;h++){var j=g[h];if((d=j.match(/(translate([XYZ]|3d)?|rotate)\(([^)]*)/))&&d.length>1)if("rotate"===d[1])-1===d[3].indexOf("deg")&&(j=d[1]+"("+d[3]+"deg");else switch(d[2]){case"X":j=d[1]+"("+e(d[3],b);break;case"Y":j=d[1]+"("+e(d[3],c);break;case"Z":break;default:for(var k=d[3].split(","),l=[b,c,100],m=0,n=k.length;n>m;m++)k[m]=e(k[m],l[m]);j=d[1]+"("+k.join(",")}j=" "+j+")",f+=j}return f=f.replace("%","").replace("+=","")}function g(a){var b=a.match(/(-*[\d|\.]+)(px|deg|rad)*/);return b&&b.length>=1?{num:parseFloat(b[1]),unit:b[2]}:void 0}function h(b){for(var c=b.split(")"),d=[],e=0,f=c.length-1;f>e;e++){var h=l(c[e]);h[1]=a.map(h[1],g),d.push(h)}return function(b){var c="",e=0;return a.each(d,function(f){"scale"===d[f][0]&&(e=1);var g=a.map(d[f][1],function(a){var c=a.num;return 1===e&&(c-=1),e+c*b+(a.unit||"")}).join(",");c+=d[f][0]+"("+g+") "}),c}}function i(b,c,d){var e,g,i=d.indexOf("+=")>=0;return d=f(d,parseFloat(a.css(b,"width"))||0,parseFloat(a.css(b,"height"))||0),i?(e=c&&"none"!==c?c:"matrix(1, 0, 0, 1, 0, 0)",g=h(d)):(e=m(c),g=m(d),e[1].lengthg[1].length&&(g=n(g))),function(a){var b=[],c="";if(i)return c=e+g(a);if(1===a)c=j(g);else{for(var d,f,h=0,k=e[1].length;k>h;h++)d=parseFloat(e[1][h]),f=parseFloat(g[1][h]),b.push(d+(f-d)*a);c=j([e[0],b])}return c}}function j(b){var c,d=[];if(a.isArray(b))return c=b[0],c+"("+b[1].join(k(c)+",")+k(c)+")";for(c in b)d.push(c);return a.map(d,function(a){return a+"("+b[a]+k(a)+")"}).join(" ")}function k(a){return a.indexOf("translate")>=0?"px":a.indexOf("rotate")>=0?"deg":""}function l(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 m(a){var b=[];return a&&"none"!==a?(b=p?l(new p(a).toString()):["matrix",c(a)],a.indexOf("3d")>=0&&b[0].indexOf("3d")<0&&(b=n(b)),b):["matrix",["1","0","0","1","0","0"]]}function n(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"]]}var o="Float32Array"in window,p=b.WebKitCSSMatrix||b.MSCSSMatrix||b.OCSSMatrix||b.MozMatrix||b.CSSMatrix;return a.fx.step.transform=function(b){b.rateFn=b.rateFn||i(b.elem,b.start,b.end),a.style(b.elem,"transform",b.rateFn(b.pos))},{toMatrix:m,toMatrix3d:n}}),eg.module("css",["jQuery",document],function(a,b){if(!a.cssHooks)throw new Error("jQuery 1.4.3+ is needed for this plugin to work");if(!(a.fn&&a.fn.jquery&&a.fn.jquery.replace(/\./,"")>="18")){var c=["Webkit","Moz","O","ms"],d=["transitionProperty","transitionDuration","transition","transform","transitionTimingFunction"],e=function(){for(var a=(b.head||b.getElementsByTagName("head")[0]).style,d=0,e=c.length;e>d;d++)if(c[d]+"Transition"in a)return c[d]}();if(e){for(var f=function(b){var c=b.charAt(0).toUpperCase()+b.slice(1),d=e+c,f="ms"===e?"Ms"+c:d;a.cssHooks[c]=a.cssHooks[e.toLowerCase()+c]=a.cssHooks[b]={get:function(b,c){return c?a.css(b,f):b.style[d]},set:function(a,b){a.style[d]=b}}},g=0,h=d.length;h>g;g++)f(d[g]);return{vendorPrefix:e,setCssHooks:f}}}}),eg.module("persist",["jQuery",eg,window,document],function(a,b,c,d){function e(a){s=s||a.originalEvent&&a.originalEvent.persisted,!s&&t?r.trigger("persist"):f()}function f(){i(null)}function g(){var a,b={},c=!1;if(u?(a=l.state,c="string"==typeof a&&"null"!==a):(a=v.getItem(m.href+p),c=a&&a.length>0),c)try{if(b=o.parse(a),"object"!==jQuery.type(b)||b instanceof Array)throw new Error}catch(d){console.warn("window.history or session/localStorage has no valid format data to be handled in persist.")}return b}function h(a){var b=g()[a];return("null"===b||"undefined"==typeof b)&&(b=null),b}function i(a){if(u)try{l.replaceState(null===a?null:o.stringify(a),d.title,m.href)}catch(b){console.warn(b.message)}else a?v.setItem(m.href+p,o.stringify(a)):v.removeItem(m.href+p);a?r.attr(p,!0):r.attr(p,null)}function j(a,b){var c=g();c[a]=b,i(c)}var k=c.performance,l=c.history,m=c.location,n=c.navigator.userAgent,o=c.JSON,p="___persist___",q="KEY"+p,r=a(c),s=r.attr(p)===!0,t=k&&k.navigation&&k.navigation.type===(k.navigation.TYPE_BACK_FORWARD||2),u="replaceState"in l&&"state"in l,v=function(){if(!u){if("sessionStorage"in c){var a="__tmp__"+p;return sessionStorage.setItem(a,p),sessionStorage.getItem(a)===p?sessionStorage:localStorage}return c.localStorage}}();return(u||v)&&(o||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"))?(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&&j(b,c),h(b)},a.persist.isNeeded=function(){var c=b.agent(n).os,d=!0;return("ios"===c.name||"android"===c.name&&parseFloat(c.version)<4.4)&&(d=!1),a.persist.isNeeded=function(){return d},d},!t&&f(),a.event.special.persist={setup:function(){r.on("pageshow",e)},teardown:function(){r.off("pageshow",e)},trigger:function(a){a.state=h(q)}},{isBackForwardNavigated:t,onPageshow:e,reset:f,getState:g,setState:i,persist:a.persist,isNeeded:a.persist.isNeeded,GLOBALKEY:q}):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,c,d){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("tap"===a.type)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),this._animateBy(this._getNextOffsetPos([e*(a.deltaX<0?-1:1)*d[0],g*(a.deltaY<0?-1:1)*d[1]]),this._animationEnd,!1,null,a)}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)},_animationEnd:function(){var b=this._pos,c=this.options.min,d=this.options.max;this._animateTo([Math.min(d[0],Math.max(c[0],b[0])),Math.min(d[1],Math.max(c[1],b[1]))],a.proxy(this.trigger,this,"animationEnd"),!0,null)},_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},_animateBy:function(a,b,c,d,e){var f=this._pos;return this._animateTo([f[0]+a[0],f[1]+a[1]],b,c,d,e)},_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],b},_isCircular:function(a,b,c,d){return a[0]&&b[1]d[0]||a[2]&&b[1]>d[1]||a[3]&&b[0]f?f:this.options.maximumDuration;var o=a.proxy(function(a){this._status.animationParam=null,h[0]=Math.round(m[0]),h[1]=Math.round(m[1]),h=this._getCircularPos(h,i,j,k),!a&&this._setInterrupt(!1),d()},this);if(0===n[0]&&0===n[1])return o(!e);g={duration:f,depaPos:h.concat(),destPos:m,isBounce:e,isCircular:l,done:o,hammerEvent:c.hammerEvent};var p=this.trigger("animationStart",g);if(l&&!p)throw new Error("You can't stop the 'animation' event when 'circular' is true.");if(g.depaPos=h,g.startTime=(new Date).getTime(),this._status.animationParam=g,p)if(g.duration){var q=this._status.animationParam,r=this;!function s(){return r._raf=null,r._frame(q)>=1?o(!0):void(r._raf=b.requestAnimationFrame(s))}()}else this._triggerChange(g.destPos,!1),o(!e)},_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(b){var c;a.each(["bounce","margin","circular"],function(d,e){c=b[e],null!=c&&(b[e]=a.isArray(c)?2===c.length?c.concat(c):c.concat():/string|number|boolean/.test(typeof c)?[c,c,c,c]:null)}),a.extend(this.options,b)},_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],this._animationEnd,!1,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].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,f){this.$wrapper=a(c);var g=this.$wrapper.children();if(!g.length)throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized.");a.extend(this.options={hwAccelerable:b.isHWAccelerable(),prefix:"eg-flick",deceleration:6e-4,horizontal:!0,circular:!1,previewPadding:[0,0],threshold:40,duration:100,panelEffect:a.easing.easeOutCubic,defaultIndex:0,inputType:["touch","mouse"]},d);var i=this.options.previewPadding;"number"==typeof i?i=this.options.previewPadding=[i,i]:i.constructor!==Array&&(i=this.options.previewPadding=[0,0]),this._conf={panel:{$list:g,index:0,no:0,size:0,count:0,origCount:0,changed:!1,animating:!1,minCount:i[0]+i[1]>0?5:3},touch:{holdPos:[0,0],destPos:[0,0],distance:0,direction:null,lastPos:0},customEvent:{flick:!0,restore:!1,restoreCall:!1},useLayerHack:this.options.hwAccelerable&&!h,dirData:[],indexToMove:0,eventPrefix:f||"",$dummyAnchor:null},a([["LEFT","RIGHT"],["UP","DOWN"]][+!this.options.horizontal]).each(a.proxy(function(a,b){this._conf.dirData.push(e["DIRECTION_"+b])},this)),!b._hasClickBug()&&(this._setPointerEvents=a.noop),this._build(),this._bindEvents(),this._applyPanelsCss(),this._arrangePanels(),this.options.hwAccelerable&&h&&this._setHint(),this._adjustContainerCss("end")},_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;this._setPadding(f,!0);var j=this._getDataByDirection([b.size,"100%"]);d.addClass(g+"-panel").css({position:"absolute",width:j[0],height:j[1],top:0,left:0}),a="position:relative;z-index:2000;width:100%;height:100%;"+(h?"":"top:"+f[0]+"px;"),this.$container=d.wrapAll("
").parent(),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}).bind(this.$wrapper,{scale:this._getDataByDirection([-1,0]),direction:e["DIRECTION_"+(h?"HORIZONTAL":"VERTICAL")],interruptable:!1,inputType:c.inputType}),this._setDefaultPanel(c.defaultIndex)},_setPadding:function(a,b){var c=this.options.horizontal,d=this._conf.panel;d.size=this.$wrapper[c?"outerWidth":"height"]()-(a[0]+a[1]);var e={padding:(c?"0 "+a.reverse().join("px 0 "):a.join("px 0 "))+"px"};b?e.overflow="hidden":c||this.$container.css("top",a[0]),this.$wrapper.css(e)},_addClonePanels:function(){var a,b=this._conf.panel,c=b.origCount,d=b.minCount-c,e=b.$list;if(this.options.circular&&c0&&d>=a&&this._movePanelPosition(a,!0),this._movePanelPosition(this._getBasePositionIndex(),!1),c.no=a):a>0&&d>=a&&(c.no=c.index=a,b=[-(c.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=this._conf,d=c.panel,e=c.touch,f=c.dirData;this.options.circular&&(c.customEvent.flick=!1,a&&(b&&(e.direction=f[+!Boolean(b>0)]),this._arrangePanelPosition(e.direction,b)),d.index=this._getBasePositionIndex(),c.customEvent.flick=!!this._setMovableCoord("setTo",[d.size*d.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&&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!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(){var a=this._conf.panel;return a.index=Math.floor(a.count/2-.1)},_bindEvents:function(){this._mcInst.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)})},_holdHandler:function(a){this._conf.touch.holdPos=a.pos,this._conf.panel.changed=!1,this._adjustContainerCss("start",a.pos)},_changeHandler:function(b){var c,d,e=this._conf,g=e.touch,h=b.pos,i=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&&(i=this._triggerEvent(f.flick,{pos:b.pos,holding:b.holding,direction:c||g.direction})),(i||null===i)&&this._setTranslate([-h[+!this.options.horizontal],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?b.prevIndex:b.index-d,b.no=b.prevNo>=0?b.prevNo:b.no-d):(b.index+=d,b.no+=d),b.no>c?b.no=0:b.no<0&&(b.no=c)},_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 this._getDataByDirection(a),{x:this._getUnitValue(a[0]),y:this._getUnitValue(a[1])}},_setTranslate:function(a){var b=this.options;g||b.horizontal||(a[0]+=b.previewPadding[0]),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(){return Math.abs(this._conf.touch.distance)>=this.options.threshold},_triggerEvent:function(b,c){var d=this._conf,e=d.panel;return this.trigger(d.eventPrefix+b,a.extend({eventType:b,index:e.index,no:e.no,direction:d.touch.direction},c))},_getElement:function(b,c,d){var e,f,g,h=this._conf.panel,i=this.options.circular,j=h.index,k=b===this._conf.dirData[0],l=null;return d?(e=h.count,f=j):(e=h.origCount,f=h.no),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?"index":"no"]},getElement:function(){var b=this._conf.panel;return a(b.$list[b.index])},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.panel,d=this.options;return c.animating?void 0:(this._setValueToMove(a),(d.circular||null!=this[a?"getNextIndex":"getPrevIndex"]())&&this._movePanelByPhase("setBy",[c.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.panel,f=this.options.circular,g=e.index;return a=this._getNumValue(a,-1),0>a||a>=e.origCount||a===e.no||e.animating?this:(e.prevIndex=g,e.prevNo=e.no,f?(c=a-e.no,d=c>0,Math.abs(c)>(d?e.count-(g+1):g)&&(c+=(d?-1:1)*e.count),e.no=a):(c=a-g,e.no=e.index=a),this._conf.indexToMove=c,this._setValueToMove(d),this._movePanelByPhase(f?"setBy":"setTo",[e.size*(f?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.size?(c.customEvent.restoreCall=!0,a=this._getNumValue(a,this.options.duration),this._setPanelNo(!0),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._setPanelNo(!0),c.touch.distance=c.indexToMove=0,d.prevIndex=d.prevNo=-1),this}})}),eg.module("infiniteGrid",["jQuery",eg,window,document,"Outlayer"],function(a,b,c,d,e){function f(b,c,d){var e;return a.each(d,function(d,f){e=c[f],null!=e&&(b[f]=a.isArray(e)?a.merge([],e):a.isPlainObject(e)?a.extend(!0,{},e):e)}),b}if(!e)return void(b.InfiniteGrid=b.Class({}));var g=e.create("InfiniteGrid");a.extend(g.prototype,{_resetLayout:function(){this._isLayoutInited||this._registGroupKey(this.options.defaultGroupKey,this.items),this.element.style.width=null,this.getSize(),this._measureColumns()},_getContainerSize:function(){return{height:Math.max.apply(Math,this._appendCols),width:this.size.innerWidth}},_getItemLayoutPosition:function(b){this._equalItemSize?b.size=this._equalItemSize:b.getSize(),null==b.isAppend&&(b.isAppend=!0);var c,d=parseInt(b.size.outerHeight,10),e=b.isAppend,f=e?this._appendCols:this._prependCols,g=Math[e?"min":"max"].apply(Math,f);if(e)c=a.inArray(g,f);else for(var h=f.length;h-->=0;)if(f[h]===g){c=h;break}return f[c]=g+(e?d:-d),{x:this.columnWidth*c,y:e?g:g-d}},resetLayout:function(){this._resetLayout(),this._isLayoutInited=!0},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.outerHeight:-e):0;return e},_getMinY:function(b){return Math.min.apply(Math,a.map(b,function(a){return a?a.position.y:0}))},_measureColumns:function(){var a=this.size.innerWidth,b=this._getColumnWidth(),c=a/b,d=b-a%b;for(c=Math.max(Math[d&&1>=d?"round":"floor"](c),1),this._appendCols=[],this._prependCols=[];c--;)this._appendCols.push(0),this._prependCols.push(0)},_getColumnWidth:function(){var a,b=this.items[0]&&this.items[0].element;return a=b?getSize(b):{outerWidth:0,outerHeight:0},this.options.isEqualSize&&(this._equalItemSize=a),this.columnWidth=a.outerWidth||this.size.outerWidth,this.columnWidth},_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},clone:function(b,c){return f(b,c,["_isLayoutInited","_equalItemSize","_appendCols","_prependCols","columnWidth","size","options"]),b.items=b.items||[],b.items.length=c.items.length,a.each(c.items,function(a){b.items[a]=f(b.items[a]||{},c.items[a],["position","size","isAppend","groupKey"])}),b},itemize:function(a,b){var c=this._itemize(a);return this._registGroupKey(b,c),c},_registGroupKey:function(a,b){if(null!=a)for(var c,d=0;c=b[d++];)c.groupKey=a},destroy:function(){this.off(),e.prototype.destroy.apply(this)}});var h={layoutComplete:"layoutComplete",append:"append",prepend:"prepend"};b.InfiniteGrid=b.Class.extend(b.Component,{_events:function(){return h},construct:function(d,e,f){this.options=a.extend({isEqualSize:!1,defaultGroupKey:null,count:30,threshold:300},e),this.options.transitionDuration=0,this.options.isInitLayout=!1,this.options.isResizeBound=!1,d instanceof a&&(d=d.get(0)),this._prefix=f||"",this.core=new g(d,this.options).on(h.layoutComplete,a.proxy(this._onlayoutComplete,this)),this.$view=a(c),this._reset(),this.core.$element.children().length>0&&this.layout(),this._onResize=a.proxy(this._onResize,this),this._onScroll=a.proxy(this._onScroll,this),this._isIos="ios"===b.agent().os.name,this._prevScrollTop=0,this._topElement=null,this._bottomElement=null,this._refreshViewport(),this.$view.on("resize",this._onResize),this.$view.on("scroll",this._onScroll)},_getScrollTop:function(){return d.body.scrollTop||d.documentElement.scrollTop},_onScroll:function(){if(!this.isProcessing()){var a=this._getScrollTop(),b=this._prevScrollTop;if(!(this._isIos&&0===a||b===a)){var c,d;if(a>b)c=this._bottomElement||this.getBottomElement(),d=c.getBoundingClientRect(),d.top<=this._clientHeight+this.options.threshold&&this.trigger(this._prefix+h.append,{scrollTop:a});else if(this.isRecycling()&&this._removedContent>0&&(c=this._topElement||this.getTopElement())&&(d=c.getBoundingClientRect(),d.bottom>=-this.options.threshold)){var e=this.fit();e>0&&(a-=e,this.$view.scrollTop(a)),this.trigger(this._prefix+h.prepend,{scrollTop:a})}this._prevScrollTop=a}}},_onResize:function(){function a(){b._refreshViewport(),b.core.element.style.width=null,b.core.needsResizeLayout()&&b.layout(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},_refreshViewport:function(){this._clientHeight=this.$view.height()},getStatus:function(){var a,b=[];for(a in this)this.hasOwnProperty(a)&&/^_/.test(a)&&b.push(a);return{core:this.core.clone({},this.core),data:f({},this,b),html:this.core.$element.html(),cssText:this.core.element.style.cssText}},setStatus:function(b){return this.core.element.style.cssText=b.cssText,this.core.$element.html(b.html),this.core.items=this.core.itemize(this.core.$element.children().toArray()),this.core.clone(this.core,b.core),a.extend(this,b.data),this},isProcessing:function(){return this._isProcessing},isRecycling:function(){return this.core.options.count>0&&this._isRecycling},getGroupKeys:function(){var a=[];if(this.core._isLayoutInited)for(var b,c=0;b=this.core.items[c++];)a.push(b.groupKey);return a},layout:function(){this._isProcessing=!0,this._isAppendType=!0;for(var a,b=0;a=this.core.items[b++];)a.isAppend=!0;return this.core.layout(),this},append:function(b,c){return this._isProcessing||0===b.length?void 0:(b=a(b),this._isProcessing=!0,this._isRecycling||(this._isRecycling=this.core.items.length+b.length>=this.core.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.core.$element.empty(),this.core.items.length=0,this._reset(),this.layout(),this},_getTopItem:function(){var b=null,c=1/0;return a.each(this.core.getColItems(!1),function(a,d){d&&d.position.yc&&(c=d.position.y+d.size.outerHeight,b=d)}),b},getBottomElement:function(){var a=this._getBottomItem();return a&&a.element},_onlayoutComplete:function(a){for(var b,c=0,d=this._isAppendType,e=0;b=a[e++];)"undefined"!=typeof b.oldVisibility&&(b.element.style.visibility=b.oldVisibility,delete b.oldVisibility);this._topElement=this.getTopElement(),this._bottomElement=this.getBottomElement(),d===!1&&(this._isFitted=!1,this._fit(!0),c=a.length>=this.core.items.length?0:this.core.items[a.length].position.y,c>0&&(this._prevScrollTop=this._getScrollTop()+c,this.$view.scrollTop(this._prevScrollTop))),this._reset(!0),this.trigger(this._prefix+h.layoutComplete,{target:a.concat(),isAppend:d,distance:c,croppedCount:this._removedContent})},_insert:function(b,c,d){if(0!==b.length){this._isAppendType=d;for(var e,f=b.toArray(),g=a(f),h=0,i=this.core.itemize(f,c);e=i[h++];)e.isAppend=d,e.oldVisibility=e.element.style.visibility,e.element.style.visibility="hidden";d?this.core.items=this.core.items.concat(i):(this.core.items=i.concat(this.core.items.slice(0)),i=i.reverse()),this.isRecycling()&&this._adjustRange(d,g);var j=0===this.core.$element.children().length;this.core.$element[d?"append":"prepend"](g),j&&this.core.resetLayout();var k=this._checkImageLoaded(g);if(k.length>0)this._waitImageLoaded(i,k);else{var l=this;setTimeout(function(){l.core.layoutItems(i,!0)},0)}}},_adjustRange:function(a,b){var c,d,e=this.core.items.length-this.core.options.count;if(!(0>=e||(d=this._getDelimiterIndex(a,e))<0)){a?(c=this.core.items.slice(0,d),this.core.items=this.core.items.slice(d),this._isFitted=!1):(c=this.core.items.slice(d),this.core.items=this.core.items.slice(0,d));for(var f,g,h=0;f=c[h++];)g=f.element,d=b.index(g),-1!==d?b.splice(d,1):g.parentNode.removeChild(g); + +this._removedContent+=a?c.length:-c.length}},_getDelimiterIndex:function(a,b){var c,d=this.core.items.length,e=0,f=a?b-1:d-b,g=f+(a?1:-1),h=this.core.items[f].groupKey;if(null!=h&&h===this.core.items[g].groupKey)if(a){for(c=f;c>0&&h===this.core.items[c].groupKey;c--);e=0===c?-1:c+1}else{for(c=f;d>c&&h===this.core.items[c].groupKey;c++);e=c===d?-1:c}else e=a?g:f;return e},_fit:function(a){if(this.core.options.count<=0)return this._fit=function(){return!1},this._isFitted=!0,!1;if(this._isFitted)return!1;for(var b,c,d=0,e=this.core.updateCols();b=this.core.items[d++];)b.position.y-=e,a&&b.css({top:b.position.y+"px"});return this.core.updateCols(!0),c=this.core._getContainerSize().height,a&&this.core._setContainerMeasure(c,!1),this._isFitted=!0,!0},fit:function(){var a=this._getTopItem(),b=a?a.position.y:0;return this._fit(!0),b},_reset:function(a){a||(this._isFitted=!0,this._isRecycling=!1,this._removedContent=0),this._isAppendType=null,this._isProcessing=!1},_checkImageLoaded:function(b){var c=[];return b.each(function(b,d){"IMG"===d.nodeName?!d.complete&&c.push(d):!d.nodeType||1!==d.nodeType&&9!==d.nodeType&&11!==d.nodeType||(c=c.concat(a(d).find("img").filter(function(a,b){return!b.complete}).toArray()))}),c},_waitImageLoaded:function(b,c){var d=this.core,e=c.length,f=function(c){e--,a(c.target).off("load error"),0>=e&&d.layoutItems(b,!0)};a.each(c,function(b,c){a(c).on("load error",f)})},destroy:function(){this.core&&(this.core.destroy(),this.core=null),this.$view.off("resize",this._onResize).off("scroll",this._onScroll),this.off()}})}); \ 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 0000000..d0d5c3c --- /dev/null +++ b/dist/pkgd/flicking.pkgd.min.js @@ -0,0 +1,29 @@ +/** +* 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.1.0 +* @SHA-1 fb4a69e (1.1.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/eg.js +* src/class.js +* src/component.js +* src/hook/css.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._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/"},Outlayer:{url:"https://github.com/metafizzy/outlayer/"}},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],function(a,b,c){function d(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 e=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,f=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(e&&!f){var g={},h=e;e=function(a){function b(){g[c]&&a()}var c=h(b);return g[c]=!0,c},f=function(a){delete g[a]}}else e&&f||(e=function(a){return c.setTimeout(a,16)},f=c.clearTimeout);b.VERSION="1.1.0",b.hook={};var i={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"}}},j={getBrowserName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.browser)},getBrowserVersion:function(a){var b,c;return a?(c=this.getBrowserRule(a).versionSearch||a,b=this.extractBrowserVersion(c,this.ua)):void 0},extractBrowserVersion:function(a,b){var c,d,e=i.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},getOSName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.os)},getOSVersion:function(a){var b,c,d,e,f=this.ua,g=this.getOSRule(a)||{},h=i.defaultString.os.version;return a?g.versionAlias?g.versionAlias:(c=g.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||h):void 0},getOSRule:function(a){return this.getRule(i.os,a)},getBrowserRule:function(a){return this.getRule(i.browser,a)},getRule:function(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&&this.isMatched(this.ua,c):d)return e},getIdentityStringFromArray:function(a,b){for(var c,d=0;c=a[d];d++)if(this.isMatched(this.ua,c.criteria))return c.identity||b.name;return b.name},isMatched:function(a,b){return b&&b.test?!!b.test(a):a.indexOf(b)>-1},isWebview:function(){for(var a,b,c=this.ua,d=i.webview,e=!1,f=0;b=d[f];f++)if(this.isMatched(c,b.criteria)&&(a=this.extractBrowserVersion(b.browserVersionSearch,c),this.isMatched(c,b.webviewToken)||this.isMatched(a,b.webviewBrowserVersion))){e=!0;break}return e}};j.create=function(a){j.ua=a;var b={os:{},browser:{}};return b.browser.name=j.getBrowserName(i.browser),b.browser.version=j.getBrowserVersion(b.browser.name),b.os.name=j.getOSName(i.os),b.os.version=j.getOSVersion(b.os.name),b.browser.webview=j.isWebview(),b.browser.name=b.browser.name.toLowerCase(),b.os.name=b.os.name.toLowerCase(),b},b.agent=function(){var a=j.create(c.navigator.userAgent);return d(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,e=b.agent(),f=e.os.version,g=e.browser.name,h=e.browser.version;return-1!==g.indexOf("chrome")?c=h>="25":/ie|edge|firefox|safari|inapp/.test(g)?c=!0:-1!==e.os.name.indexOf("android")&&(a=(j.ua.match(/\(.*\)/)||[null])[0],c=f>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||f>="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)),d(this,"isHWAccelerable",[c,e],c)},b.isTransitional=function(){var a=!1,c=b.agent(),e=c.browser.name;if(/chrome|firefox/.test(e))a=!0;else switch(c.os.name){case"ios":a=/safari|inapp/.test(e)&&parseInt(c.os.version,10)<6;break;case"window":a=-1!==e.indexOf("safari")||-1!==e.indexOf("ie")&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/chrome|firefox|safari/.test(e)}return d(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return d(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return e(a)},b.cancelAnimationFrame=function(a){f(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("css",["jQuery",document],function(a,b){if(!a.cssHooks)throw new Error("jQuery 1.4.3+ is needed for this plugin to work");if(!(a.fn&&a.fn.jquery&&a.fn.jquery.replace(/\./,"")>="18")){var c=["Webkit","Moz","O","ms"],d=["transitionProperty","transitionDuration","transition","transform","transitionTimingFunction"],e=function(){for(var a=(b.head||b.getElementsByTagName("head")[0]).style,d=0,e=c.length;e>d;d++)if(c[d]+"Transition"in a)return c[d]}();if(e){for(var f=function(b){var c=b.charAt(0).toUpperCase()+b.slice(1),d=e+c,f="ms"===e?"Ms"+c:d;a.cssHooks[c]=a.cssHooks[e.toLowerCase()+c]=a.cssHooks[b]={get:function(b,c){return c?a.css(b,f):b.style[d]},set:function(a,b){a.style[d]=b}}},g=0,h=d.length;h>g;g++)f(d[g]);return{vendorPrefix:e,setCssHooks:f}}}}),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){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},this._reviseOptions(b),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._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].get("pan").set({direction:g.direction}):(e=Math.round(Math.random()*(new Date).getTime()),this._hammers[e]=this._createHammer(d.get(0),g,h),d.data(f._KEY,e)),this):this},_createHammer:function(b,c,e){try{var f=new d.Manager(b,{recognizers:[[d.Tap,{time:3e4}],[d.Pan,{direction:c.direction,threshold:0},["tap"]]],cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",userDrag:"none"},inputClass:e});return f.on("hammer.input",a.proxy(function(a){a.isFirst&&(this._subOptions=c,this._status.curHammer=f,this._panstart(a))},this)).on("panstart panmove",this._panmove).on("panend tap",this._panend)}catch(g){}},_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].destroy(),delete this._hammers[d],c.data(f._KEY,null)),this},_grab:function(){if(this._status.animationParam){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,c,d){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("tap"===a.type)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),this._animateBy(this._getNextOffsetPos([e*(a.deltaX<0?-1:1)*d[0],g*(a.deltaY<0?-1:1)*d[1]]),this._animationEnd,!1,null,a)}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)},_animationEnd:function(){var b=this._pos,c=this.options.min,d=this.options.max;this._animateTo([Math.min(d[0],Math.max(c[0],b[0])),Math.min(d[1],Math.max(c[1],b[1]))],a.proxy(this.trigger,this,"animationEnd"),!0,null)},_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},_animateBy:function(a,b,c,d,e){var f=this._pos;return this._animateTo([f[0]+a[0],f[1]+a[1]],b,c,d,e)},_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],b},_isCircular:function(a,b,c,d){return a[0]&&b[1]d[0]||a[2]&&b[1]>d[1]||a[3]&&b[0]f?f:this.options.maximumDuration;var o=a.proxy(function(a){this._status.animationParam=null,h[0]=Math.round(m[0]),h[1]=Math.round(m[1]),h=this._getCircularPos(h,i,j,k),!a&&this._setInterrupt(!1),d()},this);if(0===n[0]&&0===n[1])return o(!e);g={duration:f,depaPos:h.concat(),destPos:m,isBounce:e,isCircular:l,done:o,hammerEvent:c.hammerEvent};var p=this.trigger("animationStart",g);if(l&&!p)throw new Error("You can't stop the 'animation' event when 'circular' is true.");if(g.depaPos=h,g.startTime=(new Date).getTime(),this._status.animationParam=g,p)if(g.duration){var q=this._status.animationParam,r=this;!function s(){return r._raf=null,r._frame(q)>=1?o(!0):void(r._raf=b.requestAnimationFrame(s))}()}else this._triggerChange(g.destPos,!1),o(!e)},_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(b){var c;a.each(["bounce","margin","circular"],function(d,e){c=b[e],null!=c&&(b[e]=a.isArray(c)?2===c.length?c.concat(c):c.concat():/string|number|boolean/.test(typeof c)?[c,c,c,c]:null)}),a.extend(this.options,b)},_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],this._animationEnd,!1,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].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,f){this.$wrapper=a(c);var g=this.$wrapper.children();if(!g.length)throw new Error("Given base element doesn't exist or it hasn't proper DOM structure to be initialized.");a.extend(this.options={hwAccelerable:b.isHWAccelerable(),prefix:"eg-flick",deceleration:6e-4,horizontal:!0,circular:!1,previewPadding:[0,0],threshold:40,duration:100,panelEffect:a.easing.easeOutCubic,defaultIndex:0,inputType:["touch","mouse"]},d);var i=this.options.previewPadding;"number"==typeof i?i=this.options.previewPadding=[i,i]:i.constructor!==Array&&(i=this.options.previewPadding=[0,0]),this._conf={panel:{$list:g,index:0,no:0,size:0,count:0,origCount:0,changed:!1,animating:!1,minCount:i[0]+i[1]>0?5:3},touch:{holdPos:[0,0],destPos:[0,0],distance:0,direction:null,lastPos:0},customEvent:{flick:!0,restore:!1,restoreCall:!1},useLayerHack:this.options.hwAccelerable&&!h,dirData:[],indexToMove:0,eventPrefix:f||"",$dummyAnchor:null},a([["LEFT","RIGHT"],["UP","DOWN"]][+!this.options.horizontal]).each(a.proxy(function(a,b){this._conf.dirData.push(e["DIRECTION_"+b])},this)),!b._hasClickBug()&&(this._setPointerEvents=a.noop),this._build(),this._bindEvents(),this._applyPanelsCss(),this._arrangePanels(),this.options.hwAccelerable&&h&&this._setHint(),this._adjustContainerCss("end")},_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;this._setPadding(f,!0);var j=this._getDataByDirection([b.size,"100%"]);d.addClass(g+"-panel").css({position:"absolute",width:j[0],height:j[1],top:0,left:0}),a="position:relative;z-index:2000;width:100%;height:100%;"+(h?"":"top:"+f[0]+"px;"),this.$container=d.wrapAll("
").parent(),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}).bind(this.$wrapper,{scale:this._getDataByDirection([-1,0]),direction:e["DIRECTION_"+(h?"HORIZONTAL":"VERTICAL")],interruptable:!1,inputType:c.inputType}),this._setDefaultPanel(c.defaultIndex)},_setPadding:function(a,b){var c=this.options.horizontal,d=this._conf.panel;d.size=this.$wrapper[c?"outerWidth":"height"]()-(a[0]+a[1]);var e={padding:(c?"0 "+a.reverse().join("px 0 "):a.join("px 0 "))+"px"};b?e.overflow="hidden":c||this.$container.css("top",a[0]),this.$wrapper.css(e)},_addClonePanels:function(){var a,b=this._conf.panel,c=b.origCount,d=b.minCount-c,e=b.$list;if(this.options.circular&&c0&&d>=a&&this._movePanelPosition(a,!0),this._movePanelPosition(this._getBasePositionIndex(),!1),c.no=a):a>0&&d>=a&&(c.no=c.index=a,b=[-(c.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=this._conf,d=c.panel,e=c.touch,f=c.dirData;this.options.circular&&(c.customEvent.flick=!1,a&&(b&&(e.direction=f[+!Boolean(b>0)]),this._arrangePanelPosition(e.direction,b)),d.index=this._getBasePositionIndex(),c.customEvent.flick=!!this._setMovableCoord("setTo",[d.size*d.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&&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!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(){var a=this._conf.panel;return a.index=Math.floor(a.count/2-.1)},_bindEvents:function(){this._mcInst.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)})},_holdHandler:function(a){this._conf.touch.holdPos=a.pos,this._conf.panel.changed=!1,this._adjustContainerCss("start",a.pos)},_changeHandler:function(b){var c,d,e=this._conf,g=e.touch,h=b.pos,i=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&&(i=this._triggerEvent(f.flick,{pos:b.pos,holding:b.holding,direction:c||g.direction})),(i||null===i)&&this._setTranslate([-h[+!this.options.horizontal],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?b.prevIndex:b.index-d,b.no=b.prevNo>=0?b.prevNo:b.no-d):(b.index+=d,b.no+=d),b.no>c?b.no=0:b.no<0&&(b.no=c)},_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 this._getDataByDirection(a),{x:this._getUnitValue(a[0]),y:this._getUnitValue(a[1])}},_setTranslate:function(a){var b=this.options;g||b.horizontal||(a[0]+=b.previewPadding[0]),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(){return Math.abs(this._conf.touch.distance)>=this.options.threshold},_triggerEvent:function(b,c){var d=this._conf,e=d.panel;return this.trigger(d.eventPrefix+b,a.extend({eventType:b,index:e.index,no:e.no,direction:d.touch.direction},c))},_getElement:function(b,c,d){var e,f,g,h=this._conf.panel,i=this.options.circular,j=h.index,k=b===this._conf.dirData[0],l=null;return d?(e=h.count,f=j):(e=h.origCount,f=h.no),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?"index":"no"]},getElement:function(){var b=this._conf.panel;return a(b.$list[b.index])},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.panel,d=this.options;return c.animating?void 0:(this._setValueToMove(a),(d.circular||null!=this[a?"getNextIndex":"getPrevIndex"]())&&this._movePanelByPhase("setBy",[c.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.panel,f=this.options.circular,g=e.index;return a=this._getNumValue(a,-1),0>a||a>=e.origCount||a===e.no||e.animating?this:(e.prevIndex=g,e.prevNo=e.no,f?(c=a-e.no,d=c>0,Math.abs(c)>(d?e.count-(g+1):g)&&(c+=(d?-1:1)*e.count),e.no=a):(c=a-g,e.no=e.index=a),this._conf.indexToMove=c,this._setValueToMove(d),this._movePanelByPhase(f?"setBy":"setTo",[e.size*(f?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.size?(c.customEvent.restoreCall=!0,a=this._getNumValue(a,this.options.duration),this._setPanelNo(!0),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._setPanelNo(!0),c.touch.distance=c.indexToMove=0,d.prevIndex=d.prevNo=-1),this}})}); \ 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 0000000..f06e58f --- /dev/null +++ b/dist/pkgd/infiniteGrid.pkgd.min.js @@ -0,0 +1,37 @@ +/** +* 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.1.0 +* @SHA-1 fb4a69e (1.1.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. +* +* bower_components/get-style-property/get-style-property.js +* bower_components/get-size/get-size.js +* bower_components/matches-selector/matches-selector.js +* bower_components/eventEmitter/EventEmitter.js +* bower_components/eventie/eventie.js +* bower_components/doc-ready/doc-ready.js +* bower_components/fizzy-ui-utils/utils.js +* bower_components/outlayer/item.js +* bower_components/outlayer/outlayer.js +* src/module.js +* src/eg.js +* src/class.js +* src/component.js +* src/customEvent/scrollEnd.js +* src/plugin/persist.js +* src/infiniteGrid.js +*/ +!function(a){function b(a){if(a){if("string"==typeof d[a])return a;a=a.charAt(0).toUpperCase()+a.slice(1);for(var b,e=0,f=c.length;f>e;e++)if(b=c[e]+a,"string"==typeof d[b])return b}}var c="Webkit Moz ms Ms O".split(" "),d=document.documentElement.style;"function"==typeof define&&define.amd?define(function(){return b}):"object"==typeof exports?module.exports=b:a.getStyleProperty=b}(window),function(a){function b(a){var b=parseFloat(a),c=-1===a.indexOf("%")&&!isNaN(b);return c&&b}function c(){}function d(){for(var a={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},b=0,c=g.length;c>b;b++){var d=g[b];a[d]=0}return a}function e(c){function e(){if(!m){m=!0;var d=a.getComputedStyle;if(j=function(){var a=d?function(a){return d(a,null)}:function(a){return a.currentStyle};return function(b){var c=a(b);return c||f("Style returned "+c+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),c}}(),k=c("boxSizing")){var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style[k]="border-box";var g=document.body||document.documentElement;g.appendChild(e);var h=j(e);l=200===b(h.width),g.removeChild(e)}}}function h(a){if(e(),"string"==typeof a&&(a=document.querySelector(a)),a&&"object"==typeof a&&a.nodeType){var c=j(a);if("none"===c.display)return d();var f={};f.width=a.offsetWidth,f.height=a.offsetHeight;for(var h=f.isBorderBox=!(!k||!c[k]||"border-box"!==c[k]),m=0,n=g.length;n>m;m++){var o=g[m],p=c[o];p=i(a,p);var q=parseFloat(p);f[o]=isNaN(q)?0:q}var r=f.paddingLeft+f.paddingRight,s=f.paddingTop+f.paddingBottom,t=f.marginLeft+f.marginRight,u=f.marginTop+f.marginBottom,v=f.borderLeftWidth+f.borderRightWidth,w=f.borderTopWidth+f.borderBottomWidth,x=h&&l,y=b(c.width);y!==!1&&(f.width=y+(x?0:r+v));var z=b(c.height);return z!==!1&&(f.height=z+(x?0:s+w)),f.innerWidth=f.width-(r+v),f.innerHeight=f.height-(s+w),f.outerWidth=f.width+t,f.outerHeight=f.height+u,f}}function i(b,c){if(a.getComputedStyle||-1===c.indexOf("%"))return c;var d=b.style,e=d.left,f=b.runtimeStyle,g=f&&f.left;return g&&(f.left=b.currentStyle.left),d.left=c,c=d.pixelLeft,d.left=e,g&&(f.left=g),c}var j,k,l,m=!1;return h}var f="undefined"==typeof console?c:function(a){console.error(a)},g=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"];"function"==typeof define&&define.amd?define(["get-style-property/get-style-property"],e):"object"==typeof exports?module.exports=e(require("desandro-get-style-property")):a.getSize=e(a.getStyleProperty)}(window),function(a){function b(a,b){return a[g](b)}function c(a){if(!a.parentNode){var b=document.createDocumentFragment();b.appendChild(a)}}function d(a,b){c(a);for(var d=a.parentNode.querySelectorAll(b),e=0,f=d.length;f>e;e++)if(d[e]===a)return!0;return!1}function e(a,d){return c(a),b(a,d)}var f,g=function(){if(a.matches)return"matches";if(a.matchesSelector)return"matchesSelector";for(var b=["webkit","moz","ms","o"],c=0,d=b.length;d>c;c++){var e=b[c],f=e+"MatchesSelector";if(a[f])return f}}();if(g){var h=document.createElement("div"),i=b(h,"div");f=i?b:e}else f=d;"function"==typeof define&&define.amd?define(function(){return f}):"object"==typeof exports?module.exports=f:window.matchesSelector=f}(Element.prototype),function(){function a(){}function b(a,b){for(var c=a.length;c--;)if(a[c].listener===b)return c;return-1}function c(a){return function(){return this[a].apply(this,arguments)}}var d=a.prototype,e=this,f=e.EventEmitter;d.getListeners=function(a){var b,c,d=this._getEvents();if(a instanceof RegExp){b={};for(c in d)d.hasOwnProperty(c)&&a.test(c)&&(b[c]=d[c])}else b=d[a]||(d[a]=[]);return b},d.flattenListeners=function(a){var b,c=[];for(b=0;ba;a++){var d=g[a];d()}}function e(e){return"complete"===f.readyState?d():(e.bind(f,"DOMContentLoaded",c),e.bind(f,"readystatechange",c),e.bind(a,"load",c)),b}var f=a.document,g=[];b.isReady=!1,"function"==typeof define&&define.amd?define(["eventie/eventie"],e):"object"==typeof exports?module.exports=e(require("eventie")):a.docReady=e(a.eventie)}(window),function(a,b){"function"==typeof define&&define.amd?define(["doc-ready/doc-ready","matches-selector/matches-selector"],function(c,d){return b(a,c,d)}):"object"==typeof exports?module.exports=b(a,require("doc-ready"),require("desandro-matches-selector")):a.fizzyUIUtils=b(a,a.docReady,a.matchesSelector)}(window,function(a,b,c){var d={};d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.modulo=function(a,b){return(a%b+b)%b};var e=Object.prototype.toString;d.isArray=function(a){return"[object Array]"==e.call(a)},d.makeArray=function(a){var b=[];if(d.isArray(a))b=a;else if(a&&"number"==typeof a.length)for(var c=0,e=a.length;e>c;c++)b.push(a[c]);else b.push(a);return b},d.indexOf=Array.prototype.indexOf?function(a,b){return a.indexOf(b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},d.removeFrom=function(a,b){var c=d.indexOf(a,b);-1!=c&&a.splice(c,1)},d.isElement="function"==typeof HTMLElement||"object"==typeof HTMLElement?function(a){return a instanceof HTMLElement}:function(a){return a&&"object"==typeof a&&1==a.nodeType&&"string"==typeof a.nodeName},d.setText=function(){function a(a,c){b=b||(void 0!==document.documentElement.textContent?"textContent":"innerText"),a[b]=c}var b;return a}(),d.getParent=function(a,b){for(;a!=document.body;)if(a=a.parentNode,c(a,b))return a},d.getQueryElement=function(a){return"string"==typeof a?document.querySelector(a):a},d.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},d.filterFindElements=function(a,b){a=d.makeArray(a);for(var e=[],f=0,g=a.length;g>f;f++){var h=a[f];if(d.isElement(h))if(b){c(h,b)&&e.push(h);for(var i=h.querySelectorAll(b),j=0,k=i.length;k>j;j++)e.push(i[j])}else e.push(h)}return e},d.debounceMethod=function(a,b,c){var d=a.prototype[b],e=b+"Timeout";a.prototype[b]=function(){var a=this[e];a&&clearTimeout(a);var b=arguments,f=this;this[e]=setTimeout(function(){d.apply(f,b),delete f[e]},c||100)}},d.toDashed=function(a){return a.replace(/(.)([A-Z])/g,function(a,b,c){return b+"-"+c}).toLowerCase()};var f=a.console;return d.htmlInit=function(c,e){b(function(){for(var b=d.toDashed(e),g=document.querySelectorAll(".js-"+b),h="data-"+b+"-options",i=0,j=g.length;j>i;i++){var k,l=g[i],m=l.getAttribute(h);try{k=m&&JSON.parse(m)}catch(n){f&&f.error("Error parsing "+h+" on "+l.nodeName.toLowerCase()+(l.id?"#"+l.id:"")+": "+n);continue}var o=new c(l,k),p=a.jQuery;p&&p.data(l,e,o)}})},d}),function(a,b){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","get-size/get-size","get-style-property/get-style-property","fizzy-ui-utils/utils"],function(c,d,e,f){return b(a,c,d,e,f)}):"object"==typeof exports?module.exports=b(a,require("wolfy87-eventemitter"),require("get-size"),require("desandro-get-style-property"),require("fizzy-ui-utils")):(a.Outlayer={},a.Outlayer.Item=b(a,a.EventEmitter,a.getSize,a.getStyleProperty,a.fizzyUIUtils))}(window,function(a,b,c,d,e){function f(a){for(var b in a)return!1;return b=null,!0}function g(a,b){a&&(this.element=a,this.layout=b,this.position={x:0,y:0},this._create())}function h(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}var i=a.getComputedStyle,j=i?function(a){return i(a,null)}:function(a){return a.currentStyle},k=d("transition"),l=d("transform"),m=k&&l,n=!!d("perspective"),o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend",transition:"transitionend"}[k],p=["transform","transition","transitionDuration","transitionProperty"],q=function(){for(var a={},b=0,c=p.length;c>b;b++){var e=p[b],f=d(e);f&&f!==e&&(a[e]=f)}return a}();e.extend(g.prototype,b.prototype),g.prototype._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.getSize=function(){this.size=c(this.element)},g.prototype.css=function(a){var b=this.element.style;for(var c in a){var d=q[c]||c;b[d]=a[c]}},g.prototype.getPosition=function(){var a=j(this.element),b=this.layout.options,c=b.isOriginLeft,d=b.isOriginTop,e=a[c?"left":"right"],f=a[d?"top":"bottom"],g=this.layout.size,h=-1!=e.indexOf("%")?parseFloat(e)/100*g.width:parseInt(e,10),i=-1!=f.indexOf("%")?parseFloat(f)/100*g.height:parseInt(f,10);h=isNaN(h)?0:h,i=isNaN(i)?0:i,h-=c?g.paddingLeft:g.paddingRight,i-=d?g.paddingTop:g.paddingBottom,this.position.x=h,this.position.y=i},g.prototype.layoutPosition=function(){var a=this.layout.size,b=this.layout.options,c={},d=b.isOriginLeft?"paddingLeft":"paddingRight",e=b.isOriginLeft?"left":"right",f=b.isOriginLeft?"right":"left",g=this.position.x+a[d];c[e]=this.getXValue(g),c[f]="";var h=b.isOriginTop?"paddingTop":"paddingBottom",i=b.isOriginTop?"top":"bottom",j=b.isOriginTop?"bottom":"top",k=this.position.y+a[h];c[i]=this.getYValue(k),c[j]="",this.css(c),this.emitEvent("layout",[this])},g.prototype.getXValue=function(a){var b=this.layout.options;return b.percentPosition&&!b.isHorizontal?a/this.layout.size.width*100+"%":a+"px"},g.prototype.getYValue=function(a){var b=this.layout.options;return b.percentPosition&&b.isHorizontal?a/this.layout.size.height*100+"%":a+"px"},g.prototype._transitionTo=function(a,b){this.getPosition();var c=this.position.x,d=this.position.y,e=parseInt(a,10),f=parseInt(b,10),g=e===this.position.x&&f===this.position.y;if(this.setPosition(a,b),g&&!this.isTransitioning)return void this.layoutPosition();var h=a-c,i=b-d,j={};j.transform=this.getTranslate(h,i),this.transition({to:j,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},g.prototype.getTranslate=function(a,b){var c=this.layout.options;return a=c.isOriginLeft?a:-a,b=c.isOriginTop?b:-b,n?"translate3d("+a+"px, "+b+"px, 0)":"translate("+a+"px, "+b+"px)"},g.prototype.goTo=function(a,b){this.setPosition(a,b),this.layoutPosition()},g.prototype.moveTo=m?g.prototype._transitionTo:g.prototype.goTo,g.prototype.setPosition=function(a,b){this.position.x=parseInt(a,10),this.position.y=parseInt(b,10)},g.prototype._nonTransition=function(a){this.css(a.to),a.isCleaning&&this._removeStyles(a.to);for(var b in a.onTransitionEnd)a.onTransitionEnd[b].call(this)},g.prototype._transition=function(a){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(a);var b=this._transn;for(var c in a.onTransitionEnd)b.onEnd[c]=a.onTransitionEnd[c];for(c in a.to)b.ingProperties[c]=!0,a.isCleaning&&(b.clean[c]=!0);if(a.from){this.css(a.from);var d=this.element.offsetHeight;d=null}this.enableTransition(a.to),this.css(a.to),this.isTransitioning=!0};var r="opacity,"+h(q.transform||"transform");g.prototype.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:r,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(o,this,!1))},g.prototype.transition=g.prototype[k?"_transition":"_nonTransition"],g.prototype.onwebkitTransitionEnd=function(a){this.ontransitionend(a)},g.prototype.onotransitionend=function(a){this.ontransitionend(a)};var s={"-webkit-transform":"transform","-moz-transform":"transform","-o-transform":"transform"};g.prototype.ontransitionend=function(a){if(a.target===this.element){var b=this._transn,c=s[a.propertyName]||a.propertyName;if(delete b.ingProperties[c],f(b.ingProperties)&&this.disableTransition(),c in b.clean&&(this.element.style[a.propertyName]="",delete b.clean[c]),c in b.onEnd){var d=b.onEnd[c];d.call(this),delete b.onEnd[c]}this.emitEvent("transitionEnd",[this])}},g.prototype.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(o,this,!1),this.isTransitioning=!1},g.prototype._removeStyles=function(a){var b={};for(var c in a)b[c]="";this.css(b)};var t={transitionProperty:"",transitionDuration:""};return g.prototype.removeTransitionStyles=function(){this.css(t)},g.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},g.prototype.remove=function(){if(!k||!parseFloat(this.layout.options.transitionDuration))return void this.removeElem();var a=this;this.once("transitionEnd",function(){a.removeElem()}),this.hide()},g.prototype.reveal=function(){delete this.isHidden,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("visibleStyle");b[c]=this.onRevealTransitionEnd,this.transition({from:a.hiddenStyle,to:a.visibleStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},g.prototype.getHideRevealTransitionEndProperty=function(a){var b=this.layout.options[a];if(b.opacity)return"opacity";for(var c in b)return c},g.prototype.hide=function(){this.isHidden=!0,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("hiddenStyle");b[c]=this.onHideTransitionEnd,this.transition({from:a.visibleStyle,to:a.hiddenStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},g.prototype.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},g}),function(a,b){"function"==typeof define&&define.amd?define(["eventie/eventie","eventEmitter/EventEmitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(c,d,e,f,g){return b(a,c,d,e,f,g)}):"object"==typeof exports?module.exports=b(a,require("eventie"),require("wolfy87-eventemitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):a.Outlayer=b(a,a.eventie,a.EventEmitter,a.getSize,a.fizzyUIUtils,a.Outlayer.Item)}(window,function(a,b,c,d,e,f){function g(a,b){var c=e.getQueryElement(a);if(!c)return void(h&&h.error("Bad element for "+this.constructor.namespace+": "+(c||a)));this.element=c,i&&(this.$element=i(this.element)),this.options=e.extend({},this.constructor.defaults),this.option(b);var d=++k;this.element.outlayerGUID=d,l[d]=this,this._create(),this.options.isInitLayout&&this.layout()}var h=a.console,i=a.jQuery,j=function(){},k=0,l={};return g.namespace="outlayer",g.Item=f,g.defaults={containerStyle:{position:"relative"},isInitLayout:!0,isOriginLeft:!0,isOriginTop:!0,isResizeBound:!0,isResizingContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}},e.extend(g.prototype,c.prototype),g.prototype.option=function(a){e.extend(this.options,a)},g.prototype._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),e.extend(this.element.style,this.options.containerStyle),this.options.isResizeBound&&this.bindResize()},g.prototype.reloadItems=function(){this.items=this._itemize(this.element.children)},g.prototype._itemize=function(a){for(var b=this._filterFindItemElements(a),c=this.constructor.Item,d=[],e=0,f=b.length;f>e;e++){var g=b[e],h=new c(g,this);d.push(h)}return d},g.prototype._filterFindItemElements=function(a){return e.filterFindElements(a,this.options.itemSelector)},g.prototype.getItemElements=function(){for(var a=[],b=0,c=this.items.length;c>b;b++)a.push(this.items[b].element);return a},g.prototype.layout=function(){this._resetLayout(),this._manageStamps();var a=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;this.layoutItems(this.items,a),this._isLayoutInited=!0},g.prototype._init=g.prototype.layout,g.prototype._resetLayout=function(){this.getSize()},g.prototype.getSize=function(){this.size=d(this.element)},g.prototype._getMeasurement=function(a,b){var c,f=this.options[a];f?("string"==typeof f?c=this.element.querySelector(f):e.isElement(f)&&(c=f),this[a]=c?d(c)[b]:f):this[a]=0},g.prototype.layoutItems=function(a,b){a=this._getItemsForLayout(a),this._layoutItems(a,b),this._postLayout()},g.prototype._getItemsForLayout=function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];e.isIgnored||b.push(e)}return b},g.prototype._layoutItems=function(a,b){if(this._emitCompleteOnItems("layout",a),a&&a.length){for(var c=[],d=0,e=a.length;e>d;d++){var f=a[d],g=this._getItemLayoutPosition(f);g.item=f,g.isInstant=b||f.isLayoutInstant,c.push(g)}this._processLayoutQueue(c)}},g.prototype._getItemLayoutPosition=function(){return{x:0,y:0}},g.prototype._processLayoutQueue=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];this._positionItem(d.item,d.x,d.y,d.isInstant)}},g.prototype._positionItem=function(a,b,c,d){d?a.goTo(b,c):a.moveTo(b,c)},g.prototype._postLayout=function(){this.resizeContainer()},g.prototype.resizeContainer=function(){if(this.options.isResizingContainer){var a=this._getContainerSize();a&&(this._setContainerMeasure(a.width,!0),this._setContainerMeasure(a.height,!1))}},g.prototype._getContainerSize=j,g.prototype._setContainerMeasure=function(a,b){if(void 0!==a){var c=this.size;c.isBorderBox&&(a+=b?c.paddingLeft+c.paddingRight+c.borderLeftWidth+c.borderRightWidth:c.paddingBottom+c.paddingTop+c.borderTopWidth+c.borderBottomWidth),a=Math.max(a,0),this.element.style[b?"width":"height"]=a+"px"}},g.prototype._emitCompleteOnItems=function(a,b){function c(){e.dispatchEvent(a+"Complete",null,[b])}function d(){g++,g===f&&c()}var e=this,f=b.length;if(!b||!f)return void c();for(var g=0,h=0,i=b.length;i>h;h++){var j=b[h];j.once(a,d)}},g.prototype.dispatchEvent=function(a,b,c){var d=b?[b].concat(c):c;if(this.emitEvent(a,d),i)if(this.$element=this.$element||i(this.element),b){var e=i.Event(b);e.type=a,this.$element.trigger(e,c)}else this.$element.trigger(a,c)},g.prototype.ignore=function(a){var b=this.getItem(a);b&&(b.isIgnored=!0)},g.prototype.unignore=function(a){var b=this.getItem(a);b&&delete b.isIgnored},g.prototype.stamp=function(a){if(a=this._find(a)){this.stamps=this.stamps.concat(a);for(var b=0,c=a.length;c>b;b++){var d=a[b];this.ignore(d)}}},g.prototype.unstamp=function(a){if(a=this._find(a))for(var b=0,c=a.length;c>b;b++){var d=a[b];e.removeFrom(this.stamps,d),this.unignore(d)}},g.prototype._find=function(a){return a?("string"==typeof a&&(a=this.element.querySelectorAll(a)),a=e.makeArray(a)):void 0},g.prototype._manageStamps=function(){if(this.stamps&&this.stamps.length){this._getBoundingRect();for(var a=0,b=this.stamps.length;b>a;a++){var c=this.stamps[a];this._manageStamp(c)}}},g.prototype._getBoundingRect=function(){var a=this.element.getBoundingClientRect(),b=this.size;this._boundingRect={left:a.left+b.paddingLeft+b.borderLeftWidth,top:a.top+b.paddingTop+b.borderTopWidth,right:a.right-(b.paddingRight+b.borderRightWidth),bottom:a.bottom-(b.paddingBottom+b.borderBottomWidth)}},g.prototype._manageStamp=j,g.prototype._getElementOffset=function(a){var b=a.getBoundingClientRect(),c=this._boundingRect,e=d(a),f={left:b.left-c.left-e.marginLeft,top:b.top-c.top-e.marginTop,right:c.right-b.right-e.marginRight,bottom:c.bottom-b.bottom-e.marginBottom};return f},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.bindResize=function(){this.isResizeBound||(b.bind(a,"resize",this),this.isResizeBound=!0)},g.prototype.unbindResize=function(){this.isResizeBound&&b.unbind(a,"resize",this),this.isResizeBound=!1},g.prototype.onresize=function(){function a(){b.resize(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},g.prototype.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},g.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a;return b&&a.innerWidth!==this.size.innerWidth},g.prototype.addItems=function(a){var b=this._itemize(a);return b.length&&(this.items=this.items.concat(b)),b},g.prototype.appended=function(a){var b=this.addItems(a);b.length&&(this.layoutItems(b,!0),this.reveal(b))},g.prototype.prepended=function(a){var b=this._itemize(a);if(b.length){var c=this.items.slice(0);this.items=b.concat(c),this._resetLayout(),this._manageStamps(),this.layoutItems(b,!0),this.reveal(b),this.layoutItems(c)}},g.prototype.reveal=function(a){this._emitCompleteOnItems("reveal",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.reveal()}},g.prototype.hide=function(a){this._emitCompleteOnItems("hide",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.hide()}},g.prototype.revealItemElements=function(a){var b=this.getItems(a);this.reveal(b)},g.prototype.hideItemElements=function(a){var b=this.getItems(a);this.hide(b)},g.prototype.getItem=function(a){for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];if(d.element===a)return d}},g.prototype.getItems=function(a){a=e.makeArray(a);for(var b=[],c=0,d=a.length;d>c;c++){var f=a[c],g=this.getItem(f);g&&b.push(g)}return b},g.prototype.remove=function(a){var b=this.getItems(a);if(this._emitCompleteOnItems("remove",b),b&&b.length)for(var c=0,d=b.length;d>c;c++){var f=b[c];f.remove(),e.removeFrom(this.items,f)}},g.prototype.destroy=function(){var a=this.element.style;a.height="",a.position="",a.width="";for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];d.destroy()}this.unbindResize();var e=this.element.outlayerGUID;delete l[e],delete this.element.outlayerGUID,i&&i.removeData(this.element,this.constructor.namespace)},g.data=function(a){a=e.getQueryElement(a);var b=a&&a.outlayerGUID;return b&&l[b]},g.create=function(a,b){function c(){g.apply(this,arguments)}return Object.create?c.prototype=Object.create(g.prototype):e.extend(c.prototype,g.prototype),c.prototype.constructor=c,c.defaults=e.extend({},g.defaults),e.extend(c.defaults,b),c.prototype.settings={},c.namespace=a,c.data=g.data,c.Item=function(){f.apply(this,arguments)},c.Item.prototype=new f,e.htmlInit(c,a),i&&i.bridget&&i.bridget(a,c),c},g.Item=f,g}),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._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/"},Outlayer:{url:"https://github.com/metafizzy/outlayer/"}},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],function(a,b,c){function d(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 e=c.requestAnimationFrame||c.webkitRequestAnimationFrame||c.mozRequestAnimationFrame||c.msRequestAnimationFrame,f=c.cancelAnimationFrame||c.webkitCancelAnimationFrame||c.mozCancelAnimationFrame||c.msCancelAnimationFrame;if(e&&!f){var g={},h=e;e=function(a){function b(){g[c]&&a()}var c=h(b);return g[c]=!0,c},f=function(a){delete g[a]}}else e&&f||(e=function(a){return c.setTimeout(a,16)},f=c.clearTimeout);b.VERSION="1.1.0",b.hook={};var i={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"}}},j={getBrowserName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.browser)},getBrowserVersion:function(a){var b,c;return a?(c=this.getBrowserRule(a).versionSearch||a,b=this.extractBrowserVersion(c,this.ua)):void 0},extractBrowserVersion:function(a,b){var c,d,e=i.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},getOSName:function(a){return this.getIdentityStringFromArray(a,i.defaultString.os)},getOSVersion:function(a){var b,c,d,e,f=this.ua,g=this.getOSRule(a)||{},h=i.defaultString.os.version;return a?g.versionAlias?g.versionAlias:(c=g.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||h):void 0},getOSRule:function(a){return this.getRule(i.os,a)},getBrowserRule:function(a){return this.getRule(i.browser,a)},getRule:function(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&&this.isMatched(this.ua,c):d)return e},getIdentityStringFromArray:function(a,b){for(var c,d=0;c=a[d];d++)if(this.isMatched(this.ua,c.criteria))return c.identity||b.name;return b.name},isMatched:function(a,b){return b&&b.test?!!b.test(a):a.indexOf(b)>-1},isWebview:function(){for(var a,b,c=this.ua,d=i.webview,e=!1,f=0;b=d[f];f++)if(this.isMatched(c,b.criteria)&&(a=this.extractBrowserVersion(b.browserVersionSearch,c),this.isMatched(c,b.webviewToken)||this.isMatched(a,b.webviewBrowserVersion))){e=!0;break}return e}};j.create=function(a){j.ua=a;var b={os:{},browser:{}};return b.browser.name=j.getBrowserName(i.browser),b.browser.version=j.getBrowserVersion(b.browser.name),b.os.name=j.getOSName(i.os),b.os.version=j.getOSVersion(b.os.name),b.browser.webview=j.isWebview(),b.browser.name=b.browser.name.toLowerCase(),b.os.name=b.os.name.toLowerCase(),b},b.agent=function(){var a=j.create(c.navigator.userAgent);return d(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,e=b.agent(),f=e.os.version,g=e.browser.name,h=e.browser.version;return-1!==g.indexOf("chrome")?c=h>="25":/ie|edge|firefox|safari|inapp/.test(g)?c=!0:-1!==e.os.name.indexOf("android")&&(a=(j.ua.match(/\(.*\)/)||[null])[0],c=f>="4.1.0"&&!/EK-GN120|SM-G386F/.test(a)||f>="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)),d(this,"isHWAccelerable",[c,e],c)},b.isTransitional=function(){var a=!1,c=b.agent(),e=c.browser.name;if(/chrome|firefox/.test(e))a=!0;else switch(c.os.name){case"ios": +a=/safari|inapp/.test(e)&&parseInt(c.os.version,10)<6;break;case"window":a=-1!==e.indexOf("safari")||-1!==e.indexOf("ie")&&parseInt(c.browser.nativeVersion,10)>=10;break;default:a=/chrome|firefox|safari/.test(e)}return d(this,"isTransitional",[a,c],a)},b._hasClickBug=function(){var a=b.agent(),c="safari"===a.browser.name;return d(this,"_hasClickBug",[c,a],c)},b.requestAnimationFrame=function(a){return e(a)},b.cancelAnimationFrame=function(a){f(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("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"ios"===d.name?f.webview===!0?a=n: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("persist",["jQuery",eg,window,document],function(a,b,c,d){function e(a){s=s||a.originalEvent&&a.originalEvent.persisted,!s&&t?r.trigger("persist"):f()}function f(){i(null)}function g(){var a,b={},c=!1;if(u?(a=l.state,c="string"==typeof a&&"null"!==a):(a=v.getItem(m.href+p),c=a&&a.length>0),c)try{if(b=o.parse(a),"object"!==jQuery.type(b)||b instanceof Array)throw new Error}catch(d){console.warn("window.history or session/localStorage has no valid format data to be handled in persist.")}return b}function h(a){var b=g()[a];return("null"===b||"undefined"==typeof b)&&(b=null),b}function i(a){if(u)try{l.replaceState(null===a?null:o.stringify(a),d.title,m.href)}catch(b){console.warn(b.message)}else a?v.setItem(m.href+p,o.stringify(a)):v.removeItem(m.href+p);a?r.attr(p,!0):r.attr(p,null)}function j(a,b){var c=g();c[a]=b,i(c)}var k=c.performance,l=c.history,m=c.location,n=c.navigator.userAgent,o=c.JSON,p="___persist___",q="KEY"+p,r=a(c),s=r.attr(p)===!0,t=k&&k.navigation&&k.navigation.type===(k.navigation.TYPE_BACK_FORWARD||2),u="replaceState"in l&&"state"in l,v=function(){if(!u){if("sessionStorage"in c){var a="__tmp__"+p;return sessionStorage.setItem(a,p),sessionStorage.getItem(a)===p?sessionStorage:localStorage}return c.localStorage}}();return(u||v)&&(o||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"))?(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&&j(b,c),h(b)},a.persist.isNeeded=function(){var c=b.agent(n).os,d=!0;return("ios"===c.name||"android"===c.name&&parseFloat(c.version)<4.4)&&(d=!1),a.persist.isNeeded=function(){return d},d},!t&&f(),a.event.special.persist={setup:function(){r.on("pageshow",e)},teardown:function(){r.off("pageshow",e)},trigger:function(a){a.state=h(q)}},{isBackForwardNavigated:t,onPageshow:e,reset:f,getState:g,setState:i,persist:a.persist,isNeeded:a.persist.isNeeded,GLOBALKEY:q}):void 0}),eg.module("infiniteGrid",["jQuery",eg,window,document,"Outlayer"],function(a,b,c,d,e){function f(b,c,d){var e;return a.each(d,function(d,f){e=c[f],null!=e&&(b[f]=a.isArray(e)?a.merge([],e):a.isPlainObject(e)?a.extend(!0,{},e):e)}),b}if(!e)return void(b.InfiniteGrid=b.Class({}));var g=e.create("InfiniteGrid");a.extend(g.prototype,{_resetLayout:function(){this._isLayoutInited||this._registGroupKey(this.options.defaultGroupKey,this.items),this.element.style.width=null,this.getSize(),this._measureColumns()},_getContainerSize:function(){return{height:Math.max.apply(Math,this._appendCols),width:this.size.innerWidth}},_getItemLayoutPosition:function(b){this._equalItemSize?b.size=this._equalItemSize:b.getSize(),null==b.isAppend&&(b.isAppend=!0);var c,d=parseInt(b.size.outerHeight,10),e=b.isAppend,f=e?this._appendCols:this._prependCols,g=Math[e?"min":"max"].apply(Math,f);if(e)c=a.inArray(g,f);else for(var h=f.length;h-->=0;)if(f[h]===g){c=h;break}return f[c]=g+(e?d:-d),{x:this.columnWidth*c,y:e?g:g-d}},resetLayout:function(){this._resetLayout(),this._isLayoutInited=!0},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.outerHeight:-e):0;return e},_getMinY:function(b){return Math.min.apply(Math,a.map(b,function(a){return a?a.position.y:0}))},_measureColumns:function(){var a=this.size.innerWidth,b=this._getColumnWidth(),c=a/b,d=b-a%b;for(c=Math.max(Math[d&&1>=d?"round":"floor"](c),1),this._appendCols=[],this._prependCols=[];c--;)this._appendCols.push(0),this._prependCols.push(0)},_getColumnWidth:function(){var a,b=this.items[0]&&this.items[0].element;return a=b?getSize(b):{outerWidth:0,outerHeight:0},this.options.isEqualSize&&(this._equalItemSize=a),this.columnWidth=a.outerWidth||this.size.outerWidth,this.columnWidth},_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},clone:function(b,c){return f(b,c,["_isLayoutInited","_equalItemSize","_appendCols","_prependCols","columnWidth","size","options"]),b.items=b.items||[],b.items.length=c.items.length,a.each(c.items,function(a){b.items[a]=f(b.items[a]||{},c.items[a],["position","size","isAppend","groupKey"])}),b},itemize:function(a,b){var c=this._itemize(a);return this._registGroupKey(b,c),c},_registGroupKey:function(a,b){if(null!=a)for(var c,d=0;c=b[d++];)c.groupKey=a},destroy:function(){this.off(),e.prototype.destroy.apply(this)}});var h={layoutComplete:"layoutComplete",append:"append",prepend:"prepend"};b.InfiniteGrid=b.Class.extend(b.Component,{_events:function(){return h},construct:function(d,e,f){this.options=a.extend({isEqualSize:!1,defaultGroupKey:null,count:30,threshold:300},e),this.options.transitionDuration=0,this.options.isInitLayout=!1,this.options.isResizeBound=!1,d instanceof a&&(d=d.get(0)),this._prefix=f||"",this.core=new g(d,this.options).on(h.layoutComplete,a.proxy(this._onlayoutComplete,this)),this.$view=a(c),this._reset(),this.core.$element.children().length>0&&this.layout(),this._onResize=a.proxy(this._onResize,this),this._onScroll=a.proxy(this._onScroll,this),this._isIos="ios"===b.agent().os.name,this._prevScrollTop=0,this._topElement=null,this._bottomElement=null,this._refreshViewport(),this.$view.on("resize",this._onResize),this.$view.on("scroll",this._onScroll)},_getScrollTop:function(){return d.body.scrollTop||d.documentElement.scrollTop},_onScroll:function(){if(!this.isProcessing()){var a=this._getScrollTop(),b=this._prevScrollTop;if(!(this._isIos&&0===a||b===a)){var c,d;if(a>b)c=this._bottomElement||this.getBottomElement(),d=c.getBoundingClientRect(),d.top<=this._clientHeight+this.options.threshold&&this.trigger(this._prefix+h.append,{scrollTop:a});else if(this.isRecycling()&&this._removedContent>0&&(c=this._topElement||this.getTopElement())&&(d=c.getBoundingClientRect(),d.bottom>=-this.options.threshold)){var e=this.fit();e>0&&(a-=e,this.$view.scrollTop(a)),this.trigger(this._prefix+h.prepend,{scrollTop:a})}this._prevScrollTop=a}}},_onResize:function(){function a(){b._refreshViewport(),b.core.element.style.width=null,b.core.needsResizeLayout()&&b.layout(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},_refreshViewport:function(){this._clientHeight=this.$view.height()},getStatus:function(){var a,b=[];for(a in this)this.hasOwnProperty(a)&&/^_/.test(a)&&b.push(a);return{core:this.core.clone({},this.core),data:f({},this,b),html:this.core.$element.html(),cssText:this.core.element.style.cssText}},setStatus:function(b){return this.core.element.style.cssText=b.cssText,this.core.$element.html(b.html),this.core.items=this.core.itemize(this.core.$element.children().toArray()),this.core.clone(this.core,b.core),a.extend(this,b.data),this},isProcessing:function(){return this._isProcessing},isRecycling:function(){return this.core.options.count>0&&this._isRecycling},getGroupKeys:function(){var a=[];if(this.core._isLayoutInited)for(var b,c=0;b=this.core.items[c++];)a.push(b.groupKey);return a},layout:function(){this._isProcessing=!0,this._isAppendType=!0;for(var a,b=0;a=this.core.items[b++];)a.isAppend=!0;return this.core.layout(),this},append:function(b,c){return this._isProcessing||0===b.length?void 0:(b=a(b),this._isProcessing=!0,this._isRecycling||(this._isRecycling=this.core.items.length+b.length>=this.core.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.core.$element.empty(),this.core.items.length=0,this._reset(),this.layout(),this},_getTopItem:function(){var b=null,c=1/0;return a.each(this.core.getColItems(!1),function(a,d){d&&d.position.yc&&(c=d.position.y+d.size.outerHeight,b=d)}),b},getBottomElement:function(){var a=this._getBottomItem();return a&&a.element},_onlayoutComplete:function(a){for(var b,c=0,d=this._isAppendType,e=0;b=a[e++];)"undefined"!=typeof b.oldVisibility&&(b.element.style.visibility=b.oldVisibility,delete b.oldVisibility);this._topElement=this.getTopElement(),this._bottomElement=this.getBottomElement(),d===!1&&(this._isFitted=!1,this._fit(!0),c=a.length>=this.core.items.length?0:this.core.items[a.length].position.y,c>0&&(this._prevScrollTop=this._getScrollTop()+c,this.$view.scrollTop(this._prevScrollTop))),this._reset(!0),this.trigger(this._prefix+h.layoutComplete,{target:a.concat(),isAppend:d,distance:c,croppedCount:this._removedContent})},_insert:function(b,c,d){if(0!==b.length){this._isAppendType=d;for(var e,f=b.toArray(),g=a(f),h=0,i=this.core.itemize(f,c);e=i[h++];)e.isAppend=d,e.oldVisibility=e.element.style.visibility,e.element.style.visibility="hidden";d?this.core.items=this.core.items.concat(i):(this.core.items=i.concat(this.core.items.slice(0)),i=i.reverse()),this.isRecycling()&&this._adjustRange(d,g);var j=0===this.core.$element.children().length;this.core.$element[d?"append":"prepend"](g),j&&this.core.resetLayout();var k=this._checkImageLoaded(g);if(k.length>0)this._waitImageLoaded(i,k);else{var l=this;setTimeout(function(){l.core.layoutItems(i,!0)},0)}}},_adjustRange:function(a,b){var c,d,e=this.core.items.length-this.core.options.count;if(!(0>=e||(d=this._getDelimiterIndex(a,e))<0)){a?(c=this.core.items.slice(0,d),this.core.items=this.core.items.slice(d),this._isFitted=!1):(c=this.core.items.slice(d),this.core.items=this.core.items.slice(0,d));for(var f,g,h=0;f=c[h++];)g=f.element,d=b.index(g),-1!==d?b.splice(d,1):g.parentNode.removeChild(g);this._removedContent+=a?c.length:-c.length}},_getDelimiterIndex:function(a,b){var c,d=this.core.items.length,e=0,f=a?b-1:d-b,g=f+(a?1:-1),h=this.core.items[f].groupKey;if(null!=h&&h===this.core.items[g].groupKey)if(a){for(c=f;c>0&&h===this.core.items[c].groupKey;c--);e=0===c?-1:c+1}else{for(c=f;d>c&&h===this.core.items[c].groupKey;c++);e=c===d?-1:c}else e=a?g:f;return e},_fit:function(a){if(this.core.options.count<=0)return this._fit=function(){return!1},this._isFitted=!0,!1;if(this._isFitted)return!1;for(var b,c,d=0,e=this.core.updateCols();b=this.core.items[d++];)b.position.y-=e,a&&b.css({top:b.position.y+"px"});return this.core.updateCols(!0),c=this.core._getContainerSize().height,a&&this.core._setContainerMeasure(c,!1),this._isFitted=!0,!0},fit:function(){var a=this._getTopItem(),b=a?a.position.y:0;return this._fit(!0),b},_reset:function(a){a||(this._isFitted=!0,this._isRecycling=!1,this._removedContent=0),this._isAppendType=null,this._isProcessing=!1},_checkImageLoaded:function(b){var c=[];return b.each(function(b,d){"IMG"===d.nodeName?!d.complete&&c.push(d):!d.nodeType||1!==d.nodeType&&9!==d.nodeType&&11!==d.nodeType||(c=c.concat(a(d).find("img").filter(function(a,b){return!b.complete}).toArray()))}),c},_waitImageLoaded:function(b,c){var d=this.core,e=c.length,f=function(c){e--,a(c.target).off("load error"),0>=e&&d.layoutItems(b,!0)};a.each(c,function(b,c){a(c).on("load error",f)})},destroy:function(){this.core&&(this.core.destroy(),this.core=null),this.$view.off("resize",this._onResize).off("scroll",this._onScroll),this.off()}})}); \ No newline at end of file diff --git a/doc/animate.js.html b/doc/animate.js.html new file mode 100644 index 0000000..777699b --- /dev/null +++ b/doc/animate.js.html @@ -0,0 +1,942 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Source: hook/animate.js

+ + + + +
+
+
/**
+* Copyright (c) 2015 NAVER Corp.
+* egjs projects are licensed under the MIT license
+*/
+
+eg.module("animate", ["jQuery", window], function($, global) {
+	"use strict";
+
+	/**
+     * Extends jQuery animate in order to use 'transform' property
+     * @ko jQuery animate 사용시 transform을 사용할 수 있도록 확장한 animate 메소드
+     * @name jQuery#animate
+     * @method
+     * @param {Object} properties An object of CSS properties and values that the animation will move toward. <ko>애니메이션 할 CSS 속성과 값으로 구성된 오브젝트</ko>
+     * @param {Number|String} [duration=4000] A string or number determining how long the animation will run. <ko>애니메이션 진행 시간</ko>
+     * @param {String} [easing="swing"] A string indicating which easing function to use for the transition. <ko>transition에 사용할 easing 함수명</ko>
+     * @param {Function} [complete] A function to call once the animation is complete. <ko>애니메이션이 완료한 후 호출하는 함수</ko>
+     *
+     * @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", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
+     */
+	var supportFloat32Array = "Float32Array" in window;
+	var CSSMatrix = global.WebKitCSSMatrix || global.MSCSSMatrix ||
+					global.OCSSMatrix || global.MozMatrix || global.CSSMatrix;
+
+	/**
+	 * Utility functions : matrix and toRadian is copied from transform2d
+	 * turns a transform string into its "matrix(A, B, C, D, X, Y)" form (as an array, though)
+	 */
+	function matrix(transform) {
+		transform = transform.split(")");
+		var trim = $.trim;
+		var i = -1;
+
+		// last element of the array is an empty string, get rid of it
+		var l = transform.length - 1;
+		var split;
+		var prop;
+		var val;
+		var prev = supportFloat32Array ? new Float32Array(6) : [];
+		var curr = supportFloat32Array ? new Float32Array(6) : [];
+		var rslt = supportFloat32Array ? new Float32Array(6) : [1, 0, 0, 1, 0, 0];
+
+		prev[0] = prev[3] = rslt[0] = rslt[3] = 1;
+		prev[1] = prev[2] = prev[4] = prev[5] = 0;
+
+		// Loop through the transform properties, parse and multiply them
+		while (++i < l) {
+			split = transform[i].split("(");
+			prop = trim(split[0]);
+			val = split[1];
+			curr[0] = curr[3] = 1;
+			curr[1] = curr[2] = curr[4] = curr[5] = 0;
+
+			switch (prop) {
+				case "translateX":
+					curr[4] = parseInt(val, 10);
+					break;
+
+				case "translateY":
+					curr[5] = parseInt(val, 10);
+					break;
+
+				case "translate":
+					val = val.split(",");
+					curr[4] = parseInt(val[0], 10);
+					curr[5] = parseInt(val[1] || 0, 10);
+					break;
+
+				case "rotate":
+					val = toRadian(val);
+					curr[0] = Math.cos(val);
+					curr[1] = Math.sin(val);
+					curr[2] = -Math.sin(val);
+					curr[3] = Math.cos(val);
+					break;
+
+				case "scaleX":
+					curr[0] = +val;
+					break;
+
+				case "scaleY":
+					curr[3] = val;
+					break;
+
+				case "scale":
+					val = val.split(",");
+					curr[0] = val[0];
+					curr[3] = val.length > 1 ? val[1] : val[0];
+					break;
+
+				case "skewX":
+					curr[2] = Math.tan(toRadian(val));
+					break;
+
+				case "skewY":
+					curr[1] = Math.tan(toRadian(val));
+					break;
+
+				case "matrix":
+					val = val.split(",");
+					curr[0] = val[0];
+					curr[1] = val[1];
+					curr[2] = val[2];
+					curr[3] = val[3];
+					curr[4] = parseInt(val[4], 10);
+					curr[5] = parseInt(val[5], 10);
+					break;
+			}
+
+			// Matrix product (array in column-major order)
+			rslt[0] = prev[0] * curr[0] + prev[2] * curr[1];
+			rslt[1] = prev[1] * curr[0] + prev[3] * curr[1];
+			rslt[2] = prev[0] * curr[2] + prev[2] * curr[3];
+			rslt[3] = prev[1] * curr[2] + prev[3] * curr[3];
+			rslt[4] = prev[0] * curr[4] + prev[2] * curr[5] + prev[4];
+			rslt[5] = prev[1] * curr[4] + prev[3] * curr[5] + prev[5];
+
+			prev = [rslt[0],rslt[1],rslt[2],rslt[3],rslt[4],rslt[5]];
+		}
+		return rslt;
+	}
+
+	// converts an angle string in any unit to a radian Float
+	function toRadian(value) {
+		return ~value.indexOf("deg") ?
+			parseInt(value, 10) * (Math.PI * 2 / 360) :
+			~value.indexOf("grad") ?
+				parseInt(value, 10) * (Math.PI / 200) :
+				parseFloat(value);
+	}
+
+	/**
+	 * 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[2]};
+		}
+	}
+
+	function getTransformGenerateFunction(transform) {
+		var splitted = transform.split(")");
+		var 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] === "scale") {
+					defaultVal = 1;
+				}
+
+				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;
+
+		// 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 = toMatrix(startTf);
+			end = toMatrix(endTf);
+
+			//If the type of matrix is not equal, then match to matrix3d
+			if (start[1].length < end[1].length) {
+				start = toMatrix3d(start);
+			} else if (start[1].length > end[1].length) {
+				end = toMatrix3d(end);
+			}
+		}
+
+		return function(pos) {
+			var result = [];
+			var ret = "";
+
+			if (isRelative) {
+				// This means a muliply between a matrix and a transform.
+				ret = start + end(pos);
+				return ret;
+			}
+
+			if (pos === 1) {
+				ret = data2String(end);
+			} else {
+				for (var i = 0, s, e, l = start[1].length; i < l; i++) {
+					s = parseFloat(start[1][i]);
+					e = parseFloat(end[1][i]);
+					result.push(s + (e - s) * pos);
+				}
+
+				ret = data2String([start[0], result]);
+			}
+
+			return ret;
+		};
+	}
+
+	/**
+	 * ["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;
+	}
+
+	function toMatrix(transform) {
+		var retMatrix = [];
+
+		if (!transform || transform === "none") {
+			return ["matrix", [ "1", "0", "0", "1", "0", "0"] ];
+		}
+
+		retMatrix = CSSMatrix ? parseStyle(new CSSMatrix(transform).toString()) :
+								["matrix", matrix(transform)];
+
+		/**
+		 * Make an unintended 2d matrix to 3d matrix.
+		 *
+		 * WebkitCSSMatrix changes 'transform3d' style to '2d matix' if it is judged as needless.
+		 * But generally, Developers would intend 3d transform by force for a HW Accelation. eg. translate3d(a, b, 0)
+		 */
+		if (transform.indexOf("3d") >= 0 && retMatrix[0].indexOf("3d") < 0) {
+			retMatrix = toMatrix3d(retMatrix);
+		}
+
+		return retMatrix;
+	}
+
+	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: toMatrix,
+		toMatrix3d: toMatrix3d
+	};
+});
+
+
+
+ + + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/class.js.html b/doc/class.js.html new file mode 100644 index 0000000..6b661e6 --- /dev/null +++ b/doc/class.js.html @@ -0,0 +1,635 @@ + + + + + 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";
+
+	/**
+	 *
+	 * The Class object is used to implement object-oriented style programming
+	 * @group egjs
+	 * @ko Class는 어플리케이션을 객체지향 프로그래밍 방식으로 구현하는데 사용합니다.
+	 * @class
+	 * @name eg.Class
+	 *
+	 * @support {"ie": "7+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
+	 * @param {Object} def Class definition of object literal type. <ko>리터럴 형태의 클래스 정의부</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;
+
+		/**
+		 * Retrun instance itself.
+		 * @ko 자신의 인스턴스를 반환한다.
+		 * @method eg.Class#instance
+		 * @return {eg.Class} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		typeClass.prototype.instance = function() {
+			return this;
+		};
+
+		typeClass.prototype.constructor = typeClass;
+		return typeClass;
+	};
+	/**
+	 * Extends class
+	 * @ko extend는 Class를 상속할 때 사용합니다.
+	 * @static
+	 * @method eg.Class.extend
+	 * @param {eg.Class} oSuperClass Super class. <ko>상속하려는 클래스</ko>
+	 * @param {Object} def Class definition of object literal type. <ko>리터럴 형태의 클래스 정의부</ko>
+	 * @return {eg.Class} instance of new eg.Class <ko>새로 생성된 eg.Class 인스턴스</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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/component.js.html b/doc/component.js.html new file mode 100644 index 0000000..fe114f7 --- /dev/null +++ b/doc/component.js.html @@ -0,0 +1,762 @@ + + + + + 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";
+
+	/**
+	 * Component
+	 * @class
+	 * @group egjs
+	 * @name eg.Component
+	 *
+	 * @support {"ie": "7+", "ch" : "latest", "ff" : "latest",  "sf" : "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 = {};
+		},
+		/**
+		 * Get or set option.
+		 * @ko 옵션을 관리한다.
+		 * @method eg.Component#option
+		 * @param {String} key
+		 * @param {Object} value
+		 * @return {eg.Component|Object} (set)instance of itself or (get)option value <ko>(set)자신의 인스턴스 혹은 (get)option 값</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;
+		},
+		/**
+		 * Trigger custom event.
+		 * @ko 커스텀 이벤트를 실행합니다.
+		 * @method eg.Component#trigger
+		 * @param {String} eventName
+		 * @param {Object} customEvent
+		 * @return {Boolean}
+		 * @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;
+		},
+		/**
+		 * Check whether the event has been registered in component.
+		 * @ko 컴포넌트에 등록된 이벤트를 확인합니다.
+		 * @method eg.Component#hasOn
+		 * @param {String} eventName
+		 * @return {Boolean}
+		 * @example
+			var Some = eg.Class.extend(eg.Component,{
+				"some": function(){
+					this.hasOn("hi");// check hi event.
+				}
+			});
+		 */
+		hasOn: function(eventName) {
+			return !!this.eventHandler[eventName];
+		},
+		/**
+		 * Attach an event handler function.
+		 * @ko 이벤트를 등록합니다.
+		 * @method eg.Component#on
+		 * @param {eventName} eventName
+		 * @param {Function} handlerToAttach
+		 * @return {eg.Component} instance of 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;
+		},
+		/**
+		 * Detach an event handler function.
+		 * @ko 이벤트를 해제합니다.
+		 * @method eg.Component#off
+		 * @param {eventName} eventName
+		 * @param {Function} handlerToDetach
+		 * @return {eg.Component} instance of 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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/css.js.html b/doc/css.js.html new file mode 100644 index 0000000..172ae20 --- /dev/null +++ b/doc/css.js.html @@ -0,0 +1,621 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Source: hook/css.js

+ + + + +
+
+
/**
+* Copyright (c) 2015 NAVER Corp.
+* egjs projects are licensed under the MIT license
+*/
+
+eg.module("css", ["jQuery", document], function($, doc) {
+	"use strict";
+
+	/**
+	 * Apply css prefix cssHooks
+	 * @ko css prefix cssHooks 적용
+	 *
+	 * @name jQuery#css
+	 * @method
+	 *
+	 * * @support {"ie": "10+", "ch" : "latest", "ff" : "latest",  "sf" : "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
+	if ($.fn && $.fn.jquery && $.fn.jquery.replace(/\./, "") >= "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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/eg.Class.html b/doc/eg.Class.html new file mode 100644 index 0000000..d8c5208 --- /dev/null +++ b/doc/eg.Class.html @@ -0,0 +1,1068 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: Class

+ + + + +
+ +
+

+ eg. + + Class +

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

+ + new eg.Class(def) +

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

The Class object is used to implement object-oriented style programming

+
+ + +
+ Class는 어플리케이션을 객체지향 프로그래밍 방식으로 구현하는데 사용합니다. +
+ + + + + + + + + +
    + +
  • + +
    + def + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    Class definition of object literal type.

    +

    리터럴 형태의 클래스 정의부

    + +
    + + + +
  • + +
+ + + + + + + + + + + + + +
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
iOS7+
Andorid2.1+ (except 3.x)
+ + + + +
+ + + + + + + + + + + + + + + +

Methods

+ +
+ +
+
+

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

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

Extends class

+
+ + +
+ extend는 Class를 상속할 때 사용합니다. +
+ + + + + + + + + +
    + +
  • + +
    + oSuperClass + + + +
    + + +
    Type: +eg.Class + +
    + + + +
    + +

    Super class.

    +

    상속하려는 클래스

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

    Class definition of object literal type.

    +

    리터럴 형태의 클래스 정의부

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Class + + + + +
instance of new eg.Class
+

새로 생성된 eg.Class 인스턴스

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

+ + instance(){eg.Class} +

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

Retrun instance itself.

+
+ + +
+ 자신의 인스턴스를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Class + + + + +
instance of itself
+

자신의 인스턴스

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + +
+ +
+ + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Mon May 09 2016 14:54:17 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 0000000..1de1105 --- /dev/null +++ b/doc/eg.Component.html @@ -0,0 +1,1606 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: Component

+ + + + +
+ +
+

+ eg. + + Component +

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

+ + new eg.Component() +

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

Component

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

Browser Support

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

Methods

+ +
+ +
+
+

+ + hasOn(eventName){Boolean} +

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

Check whether the event has been registered in component.

+
+ + +
+ 컴포넌트에 등록된 이벤트를 확인합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.hasOn("hi");// check hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Detach an event handler function.

+
+ + +
+ 이벤트를 해제합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToDetach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Attach an event handler function.

+
+ + +
+ 이벤트를 등록합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToAttach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Get or set option.

+
+ + +
+ 옵션을 관리한다. +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + value + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + | + + Object + + + + +
(set)instance of itself or (get)option value
+

(set)자신의 인스턴스 혹은 (get)option 값

+ + + +
+ + + + +
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} +

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

Trigger custom event.

+
+ + +
+ 커스텀 이벤트를 실행합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + customEvent + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
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 Mon May 09 2016 14:54:17 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 0000000..71dfedf --- /dev/null +++ b/doc/eg.Flicking.html @@ -0,0 +1,5661 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: Flicking

+ + + + +
+ +
+

+ eg. + + Flicking +

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

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

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

To build flickable UI

+
+ + +
+ 플리킹 UI를 구성한다. +
+ + + + + + + + + +
    + +
  • + +
    + element + + + +
    + + +
    Type: +HTMLElement +| + +String +| + +jQuery + +
    + + + +
    + +

    wrapper element

    +

    기준 요소

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

      Force to use HW compositing

      +

      하드웨어 가속 사용여부

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

      Prefix string for flicking elements

      +

      요소에 설정될 접두사

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

      Deceleration value can be altered to change the momentum animation duration. higher numbers make the animation shorter

      +

      감속계수는 가속도를 조절하여 애니메이션 시간을 변경할 수 있다. 높을수록 애니메이션이 짧아진다.

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

      For move direction (when horizontal is false, then move direction is vertical)

      +

      이동방향 설정 (horizontal == true 가로방향, horizontal == false 세로방향)

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

      To make panels rotate infinitely

      +

      순환 여부

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

      Padding value to display previous and next panels. If set array value the order is left(up) to right(down)

      +

      이전과 다음 패널을 출력하는 프리뷰 형태에 사용되는 padding 값. 배열 형태로 지정시 좌측(상단), 우측(하단) 순서로 지정

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

      Threshold pixels to move panels in prev/next direction

      +

      다음 패널로 이동되기 위한 임계치 픽셀

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

      Duration time of panel change animation in milliseconds

      +

      패널 이동 애니메이션 진행시간(ms) 값

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

      easing function which is used on panel move animation

      +

      패널 간의 이동 애니메이션에 사용되는 effect easing 함수

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

      Default panel index to show in first time

      +

      초기에 출력할 패널 인덱스

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

      inputType you can control input type. a kind of inputs are "touch", "mouse". default value is ["touch", "mouse"]

      +

      입력 타입을 지정할수 있다. 입력타입은 "touch", "mouse"가 있으며, 배열로 입력할 수 있다. (기본값은 ["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:

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

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

+ + + +
+ +
+ + + + +

Browser Support

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

Extends

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

Methods

+ +
+ +
+
+

+ + getAllElements(){jQuery} +

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

Get whole panel elements

+
+ + +
+ 패널을 구성하는 모든 요소들의 레퍼런스를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + jQuery + + + + +
jQuery All panel elements
+

모든 패널 요소

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

+ + getElement(){jQuery} +

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

Get current panel element

+
+ + +
+ 현재 패널 요소의 레퍼런스를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + jQuery + + + + +
jQuery Current element
+

현재 요소

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

+ + getIndex(physical){Number} +

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

Get current panel position

+
+ + +
+ 현재 패널의 인덱스 값을 반환한다. +
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Boolean to get physical or logical index (true : physical, false : logical)

    +

    물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적)

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
Number Current index number
+

현재 패널 인덱스 번호

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

+ + getNextElement(){jQuery|null} +

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

Get next panel element

+
+ + +
+ 다음 패널 요소의 레퍼런스를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + jQuery + | + + null + + + + +
Next element or null if no more element exist
+

다음 패널 요소. 패널이 없는 경우에는 null

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

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

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

Get next panel index

+
+ + +
+ 다음 패널의 인덱스 값을 반환한다. +
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Boolean to get physical or logical index (true : physical, false : logical)

    +

    물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적)

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

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

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

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

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

Get previous panel index

+
+ + +
+ 이전 패널의 인덱스 값을 반환한다. +
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Boolean to get physical or logical index (true : physical, false : logical)

    +

    물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적)

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

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

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

+ + getTotalCount(physical){Number} +

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

Get total panel count

+
+ + +
+ 전체 패널의 개수를 반환한다. +
+ + + + + + + + + +
    + +
  • + +
    + physical + + (default: false) + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    Boolean to get physical or logical index (true : physical, false : logical)

    +

    물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적)

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
Number Count of all elements
+

모든 패널 요소 개수

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

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

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

Check whether the event has been registered in component.

+
+ + +
+ 컴포넌트에 등록된 이벤트를 확인합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.hasOn("hi");// check hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + isPlaying(){Boolean} +

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

Return either panel is animating or not

+
+ + +
+ 현재 애니메이션중인지 여부를 리턴한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Move to indicated panel

+
+ + +
+ 지정한 패널로 이동한다. +
+ + + + + + + + + +
    + +
  • + +
    + no + + + + + + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    logical panel index

    +

    logical panel index

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

    Duration of animation in milliseconds

    +

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

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Flicking + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Move to next panel

+
+ + +
+ 다음 패널로 이동한다. +
+ + + + + + + + + +
    + +
  • + +
    + duration + + (default: options.duration) + + + + + optional + + + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    Duration of animation in milliseconds

    +

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

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Flicking + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Detach an event handler function.

+
+ + +
+ 이벤트를 해제합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToDetach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Attach an event handler function.

+
+ + +
+ 이벤트를 등록합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToAttach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Get or set option.

+
+ + +
+ 옵션을 관리한다. +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + value + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + | + + Object + + + + +
(set)instance of itself or (get)option value
+

(set)자신의 인스턴스 혹은 (get)option 값

+ + + +
+ + + + +
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} +

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

Move to previous panel

+
+ + +
+ 이전 패널로 이동한다. +
+ + + + + + + + + +
    + +
  • + +
    + duration + + (default: options.duration) + + + + + optional + + + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    Duration of animation in milliseconds

    +

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

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Flicking + + + + +
instance of itself
+

자신의 인스턴스

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

+ + resize(){eg.Flicking} +

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

Update panel size according current viewport

+
+ + +
+ 패널 사이즈 정보를 갱신한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Flicking + + + + +
instance of 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} +

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

Restore panel in its right position

+
+ + +
+ 패널의 위치가 올바로 위치하지 않게 되는 경우, 제대로 위치하도록 보정한다. +
+ + + + + + + + + +
    + +
  • + +
    + duration + + (default: options.duration) + + + + + optional + + + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    Duration of animation in milliseconds

    +

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

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Flicking + + + + +
instance of 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} +

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

Trigger custom event.

+
+ + +
+ 커스텀 이벤트를 실행합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + customEvent + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.trigger("hi");// fire hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + +

Events

+ +
+ +
+
+

+ + beforeFlickStart +

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

Before panel changes

+
+ + +
+ 플리킹이 시작되기 전에 발생하는 이벤트 +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + eventType + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      Name of event

      +

      이벤트명

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

      Current panel physical index

      +

      현재 패널 물리적 인덱스

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

      Current panel logical position

      +

      현재 패널 논리적 인덱스

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

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

      +

      플리킹 방향 (eg.MovableCoord.DIRECTION* constant 확인)

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

      Departure coordinate

      +

      출발점 좌표

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

        Departure x-coordinate

        +

        x 좌표

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

        Departure y-coordinate

        +

        y 좌표

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

      Destination coordinate

      +

      도착점 좌표

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

        Destination x-coordinate

        +

        x 좌표

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

        Destination y-coordinate

        +

        y 좌표

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

+ + beforeRestore +

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

Before panel restores it's last position

+
+ + +
+ 플리킹 임계치에 도달하지 못하고 사용자의 액션이 끝났을 경우, 원래 패널로 복원되기 전에 발생하는 이벤트 +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + eventType + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      Name of event

      +

      이벤트명

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

      Current panel physical index

      +

      현재 패널 물리적 인덱스

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

      Current panel logical position

      +

      현재 패널 논리적 인덱스

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

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

      +

      플리킹 방향 (eg.MovableCoord.DIRECTION* constant 확인)

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

      Departure coordinate

      +

      출발점 좌표

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

        Departure x-coordinate

        +

        x 좌표

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

        Departure y-coordinate

        +

        y 좌표

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

      Destination coordinate

      +

      도착점 좌표

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

        Destination x-coordinate

        +

        x 좌표

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

        Destination y-coordinate

        +

        y 좌표

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

+ + flick +

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

Occurs during the change

+
+ + +
+ 패널이 이동될 때 발생하는 이벤트 +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + eventType + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      Name of event

      +

      이벤트명

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

      Current panel physical index

      +

      현재 패널 물리적 인덱스

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

      Current panel logical position

      +

      현재 패널 논리적 인덱스

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

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

      +

      플리킹 방향 (eg.MovableCoord.DIRECTION* constant 확인)

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

      Departure coordinate

      +

      출발점 좌표

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

        Departure x-coordinate

        +

        x 좌표

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

      Holding if an area is pressed, this value is 'true'.

      +

      스크린을 사용자가 누르고 있을 경우 true

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

+ + flickEnd +

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

After panel changes

+
+ + +
+ 플리킹으로 패널이 이동된 후 발생하는 이벤트 +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + eventType + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      Name of event

      +

      이벤트명

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

      Current panel physical index

      +

      현재 패널 물리적 인덱스

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

      Current panel logical position

      +

      현재 패널 논리적 인덱스

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

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

      +

      플리킹 방향 (eg.MovableCoord.DIRECTION* constant 확인)

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

+ + restore +

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

After panel restores it's last position

+
+ + +
+ 플리킹 임계치에 도달하지 못하고 사용자의 액션이 끝났을 경우, 원래 인덱스로 복원된 후 발생하는 이벤트 +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + eventType + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      Name of event

      +

      이벤트명

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

      Current panel physical index

      +

      현재 패널 물리적 인덱스

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

      Current panel logical position

      +

      현재 패널 논리적 인덱스

      + +
      + + + +
    • + +
    • + +
      + 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 Mon May 09 2016 14:54:17 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 0000000..f01dccb --- /dev/null +++ b/doc/eg.InfiniteGrid.html @@ -0,0 +1,4129 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: InfiniteGrid

+ + + + +
+ +
+

+ eg. + + InfiniteGrid +

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

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

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

To build Grid layout UI +InfiniteGrid is composed using Outlayer and supports recycle-dom. +DOM elements are fixed even contents are added infinitely.

+
+ + +
+ 그리드 레이아웃을 구성하는 UI 컴포넌트. InfiniteGrid는 Outlayer로 구성되어 있다. 하지만, 이 컴포넌트는 recycle-dom을 지원한다. +컨텐츠를 계속 증가하면 할수록 일정한 DOM 개수를 유지할수 있다. +
+ + + + + + + + + +
    + +
  • + +
    + element + + + + + + + + +
    + + +
    Type: +HTMLElement +| + +String +| + +jQuery + +
    + + + +
    + +

    wrapper element

    +

    기준 요소

    + +
    + + + +
  • + +
  • + +
    + options + + + + + optional + + + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + itemSelector + + + + + optional + + + + + +
      + + +
      Type: +String + +
      + + + +
      + +

      selector string for layout item elements

      +

      레이아웃의 아이템으로 사용될 엘리먼트들의 셀렉터

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

      determine if all item's size are same

      +

      모든 아이템의 사이즈가 동일한지를 지정한다

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

      when encounter item markup during the initialization, then set defaultGroupKey as groupKey

      +

      초기화할때 마크업에 아이템이 있다면, defalutGroupKey를 groupKey로 지정한다

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

      when count value is greater than 0, grid will maintain same DOM length recycling

      +

      count값이 0보다 클 경우, 그리드는 일정한 dom 개수를 유지한다

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

      Threshold pixels to determine if grid needs to append or prepend elements

      +

      엘리먼트가 append 또는 prepend될지를 결정하는 임계치 픽셀

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + + + +
Example
+ + + +
    <!-- HTML -->
+    <ul id="grid">
+        <li class="item">
+          <div>테스트1</div>
+        </li>
+        <li class="item">
+          <div>테스트2</div>
+        </li>
+        <li class="item">
+          <div>테스트3</div>
+        </li>
+        <li class="item">
+          <div>테스트4</div>
+        </li>
+        <li class="item">
+          <div>테스트5</div>
+        </li>
+        <li class="item">
+          <div>테스트6</div>
+        </li>
+    </ul>
+    <script>
+    var some = new eg.InfiniteGrid("#grid", {
+        itemSelector : ".item"
+    }).on("layoutComplete", function(e) {
+        // ...
+    });
+    </script>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +

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
iOS7+
Andorid2.1+ (except 3.x)
+ + + + +
+ + + +

Extends

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

Methods

+ +
+ +
+
+

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

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

Append elements

+
+ + +
+ 엘리먼트를 append 한다. +
+ + + + + + + + + +
    + +
  • + +
    + elements + + + + + + + + +
    + + +
    Type: +Array +| + +String +| + +jQuery + +
    + + + +
    + +

    to be appended elements

    +

    append될 엘리먼트 배열

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

    to be appended groupkey of elements

    +

    append될 엘리먼트의 그룹키

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
length a number of elements
+
length a number of elements
+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + clear(){eg.InfiniteGrid} +

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

Clear elements and data

+
+ + +
+ 엘리먼트와 데이터를 지운다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.InfiniteGrid + + + + +
instance of itself
+

자신의 인스턴스

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

+ + destroy() +

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

Release resources and unbind custom events

+
+ + +
+ 모든 커스텀 이벤트와 자원을 해제한다. +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + fit(){Number} +

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

Remove white space which was removed by append action.

+
+ + +
+ append에 의해 제거된 빈공간을 제거한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
distance if empty space is removed, value is not zero.
+

빈공간이 제거되면 0이 아닌 값을 반환

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

+ + getBottomElement(){HTMLElement} +

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

Get the last element at the bottom

+
+ + +
+ 가장 아래에 있는 엘리먼트를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + HTMLElement + + + + +
element
+
element
+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getGroupKeys(){Array} +

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

Get group keys

+
+ + +
+ 그룹키들을 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Array + + + + +
groupKeys
+
groupKeys
+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + getStatue(){Object} +

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

Get current status

+
+ + +
+ infiniteGrid의 현재상태를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Object + + + + +
infiniteGrid status Object
+

infiniteGrid 상태 오브젝트

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

+ + getTopElement(){HTMLElement} +

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

Get the first element at the top

+
+ + +
+ 가장 위에 있는 엘리먼트를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + HTMLElement + + + + +
element
+
element
+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Check whether the event has been registered in component.

+
+ + +
+ 컴포넌트에 등록된 이벤트를 확인합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.hasOn("hi");// check hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + isProcessing(){Boolean} +

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

Check if element is appending or prepending

+
+ + +
+ append나 prepend가 진행중일 경우 true를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + isRecycling(){Boolean} +

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

Check if elements are in recycling mode

+
+ + +
+ recycle 모드 여부를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + layout(){eg.InfiniteGrid} +

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

Rearrange layout

+
+ + +
+ 레이아웃을 재배치한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.InfiniteGrid + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Detach an event handler function.

+
+ + +
+ 이벤트를 해제합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToDetach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Attach an event handler function.

+
+ + +
+ 이벤트를 등록합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToAttach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Get or set option.

+
+ + +
+ 옵션을 관리한다. +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + value + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + | + + Object + + + + +
(set)instance of itself or (get)option value
+

(set)자신의 인스턴스 혹은 (get)option 값

+ + + +
+ + + + +
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} +

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

Prepend elements

+
+ + +
+ 엘리먼트를 prepend 한다. +
+ + + + + + + + + +
    + +
  • + +
    + elements + + + + + + + + +
    + + +
    Type: +Array +| + +String +| + +jQuery + +
    + + + +
    + +

    to be prepended elements

    +

    prepend될 엘리먼트 배열

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

    to be prepended groupkey of elements

    +

    prepend될 엘리먼트의 그룹키

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
length a number of elements
+
length a number of elements
+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Set current status

+
+ + +
+ infiniteGrid의 현재상태를 설정한다. +
+ + + + + + + + + +
    + +
  • + +
    + status + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    Object

    +

    Object

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.InfiniteGrid + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Trigger custom event.

+
+ + +
+ 커스텀 이벤트를 실행합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + customEvent + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.trigger("hi");// fire hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + +

Events

+ +
+ +
+
+

+ + append +

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

Occurs when grid needs to append elements. +in order words, when scroll reaches end of page

+
+ + +
+ 엘리먼트가 append 될 필요가 있을 때 발생하는 이벤트. +즉, 스크롤이 페이지 하단에 도달했을 때 발생한다. +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + scrollTop + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      scrollTop scroll-y position of window

      +

      윈도우 y 스크롤의 값

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

+ + layoutComplete +

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

Occurs when layout is completed (after append / after prepend / after layout)

+
+ + +
+ 레이아웃이 완료 되었을 때 발생하는 이벤트 (append/prepend/layout 메소드 호출 후, 아이템의 배치가 완료되었을때 발생) +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + target + + + +
      + + +
      Type: +Array + +
      + + + +
      + +

      target rearranged elements

      +

      재배치된 엘리먼트들

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

      isAppend determine if append or prepend (value is true when call layout method)

      +

      아이템이 append로 추가되었는지, prepend로 추가되었는지를 반한환다. (layout호출시에는 true)

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

      the distance of moved top-element after layoutComplete event is triggered. in order words, prepended distance or height

      +

      최상단 엘리먼트가 layoutComplete 이벤트 발생 후,이동되어진 거리. 즉, prepend 되어 늘어난 거리(높이)

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

      the count of removed elements for recycle-dom.

      +

      순환 구조에 의해, 삭제된 엘리먼트 개수

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

+ + prepend +

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

Occurs when grid needs to prepend elements +in order words, when scroll reaches top of page and a count of cropped element is more than zero.

+
+ + +
+ 엘리먼트가 prepend 될 필요가 있을 때 발생하는 이벤트. +즉, 스크롤이 페이지 상단에 도달하고, 순환에 의해 잘려진 엘리먼트가 존재할때 발생한다. +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + scrollTop + + + +
      + + +
      Type: +Number + +
      + + + +
      + +

      scrollTop scroll-y position of window

      +

      윈도우 y 스크롤의 값

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ +
+ + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Mon May 09 2016 14:54:17 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 0000000..0825d7d --- /dev/null +++ b/doc/eg.MovableCoord.html @@ -0,0 +1,5584 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: MovableCoord

+ + + + +
+ +
+

+ eg. + + MovableCoord +

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

+ + new eg.MovableCoord(options) +

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

Easily get computed coordinate values according user actions.

+
+ + +
+ MovableCoord는 사용자 행동에 의해, 좌표계를 제어할 수 있다. +
+ + + + + + + + + +
    + +
  • + +
    + options + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + min + + + + + + + + +
      + + +
      Type: +Array + +
      + + + +
      + +

      The minimum coordinate

      +

      좌표계의 최소값

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

        The minimum x-coordinate

        +

        최소 X좌표

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

        The minimum y-coordinate

        +

        최소 Y좌표

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

      The maximum coordinate

      +

      좌표계의 최대값

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

        The maximum x-coordinate

        +

        최대 X좌표

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

        The maximum y-coordinate

        +

        최대 Y좌표

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

      The area can move using animation.

      +

      바운스: 애니메이션에 의해 이동할 수 있는 영역

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

        The bounce top range

        +

        top 바우스 영역

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

        The bounce right range

        +

        right 바우스 영역

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

        The bounce bottom range

        +

        bottom 바우스 영역

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

        The bounce left range

        +

        left 바우스 영역

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

      The area can move using user's action.

      +

      영역별 마진 영역: 사용자의 액션에 의해, 추가로 이동할수 있는 영역

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

        The margin top range

        +

        top 마진 영역

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

        The margin right range

        +

        right 마진 영역

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

        The margin bottom range

        +

        bottom 마진 영역

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

        The margin left range

        +

        left 마진 영역

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

      영역별 순환 여부

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

        The circular top range

        +

        top 순환 영역

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

        The circular right range

        +

        right 순환 영역

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

        The circular bottom range

        +

        bottom 순환 영역

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

        The circular left range

        +

        left 순환 영역

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

      Function of the Easing (jQuery UI Easing, jQuery Easing Plugin).

      +

      Easing 함수

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

      The maximum duration.

      +

      최대 좌표 이동 시간

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

      deceleration This value can be altered to change the momentum animation duration. higher numbers make the animation shorter.

      +

      감속계수. 높을값이 주어질수록 애니메이션의 동작 시간이 짧아진다.

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +

Codepen:

+ + + + + + + + +
MovableCoord 기본 예제
+
MovableCoord basic example
+

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

+ + + +
+ +
+ + + + +

Browser Support

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BrowserVersion
Desktop - Internet Explorer10+
Desktop - Chromelatest
Desktop - Firefoxlatest
Desktop - Safarilatest
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} +

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

Bind element

+
+ + +
+ movableCoord을 사용하기 위한 엘리먼트를 등록한다. +
+ + + + + + + + + +
    + +
  • + +
    + element + + + +
    + + +
    Type: +HTMLElement +| + +String +| + +jQuery + +
    + + + +
    + +

    A target element.

    +

    movableCoord을 사용하기 위한 엘리먼트

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

      The controllable directions.

      +

      움직일수 있는 방향

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

      The moving scale.

      +

      이동 배율

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

        x-scale

        +

        x축 배율

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

        y-scale

        +

        y축 배율

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

      The threshold angle about direction which range is 0~90

      +

      방향에 대한 임계각 (0~90)

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

      interruptable This value can be enabled to interrupt cycle of the animation event.

      +

      이 값이 true이면, 애니메이션의 이벤트 사이클을 중단할수 있다.

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

      inputType you can control input type. a kind of inputs are "touch", "mouse". default value is ["touch", "mouse"]

      +

      입력 타입을 지정할수 있다. 입력타입은 "touch", "mouse" 가 있으며, 배열로 입력할 수 있다. (기본값은 ["touch", "mouse"] 이다)

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.MovableCoord + + + + +
instance of itself
+

자신의 인스턴스

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

+ + destroy() +

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

Release resources and unbind custom events

+
+ + +
+ 모든 커스텀 이벤트와 자원을 해제한다. +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + get(){Array} +

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

Get current position

+
+ + +
+ 현재 위치를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pos + + Array + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
0 + + Number + + + + +
x position
+
x position
+ + + +
1 + + Number + + + + +
y position
+
y position
+ + + +
+ + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Check whether the event has been registered in component.

+
+ + +
+ 컴포넌트에 등록된 이벤트를 확인합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.hasOn("hi");// check hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Detach an event handler function.

+
+ + +
+ 이벤트를 해제합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToDetach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Attach an event handler function.

+
+ + +
+ 이벤트를 등록합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToAttach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Get or set option.

+
+ + +
+ 옵션을 관리한다. +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + value + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + | + + Object + + + + +
(set)instance of itself or (get)option value
+

(set)자신의 인스턴스 혹은 (get)option 값

+ + + +
+ + + + +
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} +

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

Set to relative position

+

When duration is greater than zero, 'change' event is triggered

+
+ + +
+ 현재를 기준으로 위치를 설정한다. 만약, duration이 0보다 크다면 'change' 이벤트가 발생한다. +
+ + + + + + + + + +
    + +
  • + +
    + x + + + + + + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    x-coordinate

    +

    이동할 x좌표

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

    y-coordinate

    +

    이동할 y좌표

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

    Duration of animation in milliseconds.

    +

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

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.MovableCoord + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Set to absolute position

+

When duration is greater than zero, 'change' event is triggered

+
+ + +
+ 위치를 설정한다. 만약, duration이 0보다 크다면 'change' 이벤트가 발생한다. +
+ + + + + + + + + +
    + +
  • + +
    + x + + + + + + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    x-coordinate

    +

    이동할 x좌표

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

    y-coordinate

    +

    이동할 y좌표

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

    Duration of animation in milliseconds.

    +

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

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.MovableCoord + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Trigger custom event.

+
+ + +
+ 커스텀 이벤트를 실행합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + customEvent + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.trigger("hi");// fire hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Unbind element

+
+ + +
+ movableCoord을 사용하기 위한 엘리먼트를 해제한다. +
+ + + + + + + + + +
    + +
  • + +
    + element + + + +
    + + +
    Type: +HTMLElement +| + +String +| + +jQuery + +
    + + + +
    + +

    The target element.

    +

    movableCoord을 사용하기 위한 설정한 엘리먼트

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.MovableCoord + + + + +
instance of itself
+

자신의 인스턴스

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

Events

+ +
+ +
+
+

+ + animationEnd +

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

When animation was ended.

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

+ + animationStart +

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

When animation was started.

+
+ + +
+ 에니메이션이 시작했을 때 발생한다. +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + duration + + + +
      + + +
      Type: +Number + +
      + + + +
      + +
      + + + +
    • + +
    • + +
      + depaPos + + + +
      + + +
      Type: +Array + +
      + + + +
      + +

      departure coordinate

      +

      현재 좌표

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

        departure x-coordinate

        +

        현재 x 좌표

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

        departure y-coordinate

        +

        현재 y 좌표

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

      destination coordinate

      +

      애니메이션에 의해 이동할 좌표

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

        destination x-coordinate

        +

        x 좌표

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

        destination y-coordinate

        +

        y 좌표

        + +
        + + + +
      • + +
      + +
    • + +
    • + +
      + isBounce + + + +
      + + +
      Type: +Boolean + +
      + + + +
      + +

      When an animation is bounced, a value is 'true'.

      +

      바운스 되는 애니메이션인 경우 true

      + +
      + + + +
    • + +
    • + +
      + isCircular + + + +
      + + +
      Type: +Boolean + +
      + + + +
      + +

      When the area is circular type, a value is 'true'.

      +

      순환하여 움직여야하는 애니메이션인경우 true

      + +
      + + + +
    • + +
    • + +
      + done + + + +
      + + +
      Type: +function + +
      + + + +
      + +

      If user control animation, user must call this function.

      +

      애니메이션이 끝났다는 것을 알려주는 함수

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

      Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event

      +

      사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환)

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

+ + change +

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

When coordinate was changed

+
+ + +
+ 좌표가 변경됐을 때 발생한다. +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + pos + + + +
      + + +
      Type: +Array + +
      + + + +
      + +

      departure coordinate

      +

      좌표

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

        departure x-coordinate

        +

        x 좌표

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

        departure y-coordinate

        +

        y 좌표

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

      If an area was pressed, this value is 'true'.

      +

      스크린을 사용자가 누르고 있을 경우 true

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

      Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event

      +

      사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환)

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

+ + hold +

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

When an area was pressed

+
+ + +
+ 스크린에서 사용자가 손을 대었을 때 +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + pos + + + +
      + + +
      Type: +Array + +
      + + + +
      + +

      coordinate

      +

      좌표 정보

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

        x-coordinate

        +

        x 좌표

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

        y-coordinate

        +

        y 좌표

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

      Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event

      +

      사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환)

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

+ + release +

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

When an area was released

+
+ + +
+ 스크린에서 사용자가 손을 떼었을 때 +
+ + + + + + + + + +
    + +
  • + +
    + param + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + + + +
      + +
    • + +
      + depaPos + + + +
      + + +
      Type: +Array + +
      + + + +
      + +

      departure coordinate

      +

      현재 좌표

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

        departure x-coordinate

        +

        현재 x 좌표

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

        departure y-coordinate

        +

        현재 y 좌표

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

      destination coordinate

      +

      애니메이션에 의해 이동할 좌표

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

        destination x-coordinate

        +

        x 좌표

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

        destination y-coordinate

        +

        y 좌표

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

      Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event

      +

      사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환)

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ +
+ + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Mon May 09 2016 14:54:17 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 0000000..eb74664 --- /dev/null +++ b/doc/eg.Visible.html @@ -0,0 +1,2220 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Class: Visible

+ + + + +
+ +
+

+ eg. + + Visible +

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

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

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

Check element's visible state within viewport, regardless scroll position

+
+ + +
+ scroll 위치와 상관없이 특정 엘리먼트나 viewport 안에 엘리먼트가 보이는지 확인한다. +
+ + + + + + + + + +
    + +
  • + +
    + element + + (default: document) + + + + + optional + + + + + +
    + + +
    Type: +HTMLElement +| + +String +| + +jQuery + +
    + + + +
    + +

    The parent element that to check targets (wrapper is only one.)

    +

    확인할 영역의 상위 엘리먼트

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

      A class name of targets

      +

      확인할 엘리먼트가 가진 클래스명

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

      expand size of the wrapper. +e.g. If a wrapper size is 100 x 100 and 'expandSize' option is 20, visible range is 120 x 120

      +
      +

      상위 엘리먼트 기준으로 추가적인 영역을 확인하도록 지정

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

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
iOS7+
Andorid2.1+ (except 3.x)
+ + + + +
+ + + +

Extends

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

Methods

+ +
+ +
+
+

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

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

Checks if the target elements has been changed.

+
+ + +
+ target들이 변경했는지 확인한다. +
+ + + + + + + + + +
    + +
  • + +
    + delay + + (default: -1) + + + + + optional + + + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    Delay time in milliseconds

    +

    호출 후, 일정 시간이 지난 후에 확인하고자 할때 사용한다.

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Visible + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Check whether the event has been registered in component.

+
+ + +
+ 컴포넌트에 등록된 이벤트를 확인합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.hasOn("hi");// check hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

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

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

Detach an event handler function.

+
+ + +
+ 이벤트를 해제합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToDetach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Attach an event handler function.

+
+ + +
+ 이벤트를 등록합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +eventName + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + handlerToAttach + + + +
    + + +
    Type: +function + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + + + + +
instance of 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} +

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

Get or set option.

+
+ + +
+ 옵션을 관리한다. +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + value + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Component + | + + Object + + + + +
(set)instance of itself or (get)option value
+

(set)자신의 인스턴스 혹은 (get)option 값

+ + + +
+ + + + +
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} +

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

Update targets

+
+ + +
+ target들을 갱신한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + eg.Visible + + + + +
instance of itself
+

자신의 인스턴스

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

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

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

Trigger custom event.

+
+ + +
+ 커스텀 이벤트를 실행합니다. +
+ + + + + + + + + +
    + +
  • + +
    + eventName + + + +
    + + +
    Type: +String + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + customEvent + + + +
    + + +
    Type: +Object + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +
        var Some = eg.Class.extend(eg.Component,{
+            "some": function(){
+                this.trigger("hi");// fire hi event.
+            }
+        });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + +

Events

+ +
+ +
+
+

+ + change +

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

Trigger when the target elements are visible or hidden based on the base area.

+
+ + +
+ 기준 영역을 기준으로 보이는 엘리먼트와 사라진 엘리먼트가 변경된 경우 발생하는 이벤트 +
+ + + + + + + + + +
    + +
  • + +
    + visible + + + +
    + + +
    Type: +Array + +
    + + + +
    + +

    The visible elements (the element type is HTMLElement)

    +

    보여지게 된 엘리먼트들

    + +
    + + + +
  • + +
  • + +
    + invisible + + + +
    + + +
    Type: +Array + +
    + + + +
    + +

    The invisible elements (the element type is HTMLElement)

    +

    안 보여지게 된 엘리먼트들

    + +
    + + + +
  • + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ +
+ + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + \ No newline at end of file diff --git a/doc/eg.html b/doc/eg.html new file mode 100644 index 0000000..0f971c1 --- /dev/null +++ b/doc/eg.html @@ -0,0 +1,1911 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Namespace: eg

+ + + + +
+ +
+

+ eg +

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

Classes

+ +
+
Class
+
+ +
Component
+
+ +
Flicking
+
+ +
InfiniteGrid
+
+ +
MovableCoord
+
+ +
Visible
+
+
+ + + + + +

Members

+ +
+ + +
+
+

staticeg.VERSION

+
+ +
+
+ +
+

version infomation

+
+ + +
+ 버전 정보 +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ +
+ + + +

Methods

+ +
+ +
+
+

+ + agent(){Object} +

+ + +
+ eg.js, line 69 +
+ +
+ + +
+
+ + +
+

Get browser agent information

+
+ + +
+ Agent 정보를 반환한다. 값은 캐싱된다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
agent + + Object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
os + + String + + + + +
os infomation
+

os 정보 객체

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + String + + + + +
os name (android, ios, window, mac)
+

os 이름 (android, ios, window, mac)

+ + + +
version + + String + + + + +
os version
+

os 버전

+ + + +
+ + +
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 + + + + +
check whether browser is webview
+

웹뷰 브라우저 여부

+ + + +
+ + +
+ + +
+ + + + +
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) +

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

/* +cancelAnimationFrame polyfill

+
+ + +
+ cancelAnimationFrame 폴리필 +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +Number + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + + + +
Example
+ + + +
    eg.cancelAnimationFrame(timerId);
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + isHWAccelerable(){Boolean} +

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

Check hardware acceleration support

+
+ + +
+ 해당 기기에서 하드웨어 가속을 할 수 있다면 true을 반환하며, 값은 캐싱된다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +

eg.isHWAccelerable(); // Returns 'true' when supports hardware acceleration

+

// 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} +

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

Check if device is in portrait mode

+
+ + +
+ 해당 기기가 portait(수직방향) 모드일 경우, true을 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +

eg.isPortrait(); // Check if device is in portrait mode

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

+ + isTransitional(){Boolean} +

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

Check CSS transition support

+
+ + +
+ 해당 기기에서 css transtion을 할 수 있다면 true을 반환하며, 값은 캐싱된다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Boolean + + + + + + +
+ + + + +
Example
+ + + +

eg.isTransitional(); // Returns 'true' when supports CSS transition

+

// 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} +

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

/* +requestAnimationFrame polyfill

+
+ + +
+ requestAnimationFrame 폴리필 +
+ + + + + + + + + +
    + +
  • + +
    + timer + + + +
    + + +
    Type: +function + +
    + + + +
    + +

    function

    +

    function

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Number + + + + +
key
+
key
+ + + +
+ + + + +
Example
+ + + +
    var timerId = eg.requestAnimationFrame(function() {
+        console.log("call");
+    });
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + translate(x, y, isHA){String} +

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

Get a translate string

+
+ + +
+ translate 문자를 반환한다. +
+ + + + + + + + + +
    + +
  • + +
    + x + + + + + + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    x-coordinate

    +

    x 좌표

    + +
    + + + +
  • + +
  • + +
    + y + + + + + + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    y-coordinate

    +

    y 좌표

    + +
    + + + +
  • + +
  • + +
    + isHA + + + + + optional + + + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +

    isHWAccelerable

    +

    하드웨어 가속 여부

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + String + + + + + + +
+ + + + +
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 Mon May 09 2016 14:54:17 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 0000000..680fabd --- /dev/null +++ b/doc/eg.js.html @@ -0,0 +1,1056 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Source: eg.js

+ + + + +
+
+
/**
+* Copyright (c) 2015 NAVER Corp.
+* egjs projects are licensed under the MIT license
+*/
+
+eg.module("eg", ["jQuery", eg, window], function($, ns, global) {
+	"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 version infomation
+	 * @ko 버전 정보
+	 */
+	ns.VERSION = "#__VERSION__#";
+	ns.hook =  {
+		// isHWAccelerable : null,
+		// isTransitional 	: null,
+		// agent : null
+	};
+	/**
+	* Get browser agent information
+	*
+	* @ko Agent 정보를 반환한다. 값은 캐싱된다.
+	* @method eg#agent
+	* @return {Object} agent
+	* @return {String} agent.os os infomation <ko>os 정보 객체</ko>
+	* @return {String} agent.os.name os name (android, ios, window, mac) <ko>os 이름 (android, ios, window, mac)</ko>
+	* @return {String} agent.os.version os version <ko>os 버전</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 check whether browser is webview <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;
+}
+}
+	*/
+	/*
+	*	{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 UAParser = {
+		getBrowserName: function(browserRules) {
+			return this.getIdentityStringFromArray(
+				browserRules,
+				userAgentRules.defaultString.browser
+			);
+		},
+		getBrowserVersion: function(browserName) {
+			var browserVersion;
+			var versionToken;
+
+			if (!browserName) {
+				return;
+			}
+
+			versionToken =
+				this.getBrowserRule(browserName).versionSearch || browserName;
+
+			browserVersion = this.extractBrowserVersion(versionToken, this.ua);
+
+			return browserVersion;
+		},
+		extractBrowserVersion: function(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;
+		},
+		getOSName: function(osRules) {
+			return this.getIdentityStringFromArray(
+				osRules,
+				userAgentRules.defaultString.os
+			);
+		},
+		getOSVersion: function(osName) {
+			var ua = this.ua;
+			var osRule = this.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;
+		},
+		getOSRule: function(osName) {
+			return this.getRule(userAgentRules.os, osName);
+		},
+		getBrowserRule: function(browserName) {
+			return this.getRule(userAgentRules.browser, browserName);
+		},
+		getRule: function(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 && this.isMatched(this.ua, criteria) :
+					identityMatched) {
+					return rule;
+				}
+			}
+		},
+		getIdentityStringFromArray: function(rules, defaultStrings) {
+			for (var i = 0, rule; rule = rules[i]; i++) {
+				if (this.isMatched(this.ua, rule.criteria)) {
+					return rule.identity || defaultStrings.name;
+				}
+			}
+			return defaultStrings.name;
+		},
+		isMatched: function(base, target) {
+			return target &&
+				target.test ? !!target.test(base) : base.indexOf(target) > -1;
+		},
+		isWebview: function() {
+			var ua = this.ua;
+			var webviewRules = userAgentRules.webview;
+			var isWebview = false;
+			var browserVersion;
+
+			for (var i = 0, rule; rule = webviewRules[i]; i++) {
+				if (!this.isMatched(ua, rule.criteria)) {
+					continue;
+				}
+
+				browserVersion =
+					this.extractBrowserVersion(rule.browserVersionSearch, ua);
+
+				if (this.isMatched(ua, rule.webviewToken) ||
+					this.isMatched(browserVersion, rule.webviewBrowserVersion)) {
+					isWebview = true;
+					break;
+				}
+			}
+
+			return isWebview;
+		}
+	};
+
+	UAParser.create = function(useragent) {
+		UAParser.ua = useragent;
+		var agent = {
+			os: {},
+			browser: {}
+		};
+
+		agent.browser.name = UAParser.getBrowserName(userAgentRules.browser);
+		agent.browser.version = UAParser.getBrowserVersion(agent.browser.name);
+		agent.os.name = UAParser.getOSName(userAgentRules.os);
+		agent.os.version = UAParser.getOSVersion(agent.os.name);
+		agent.browser.webview = UAParser.isWebview();
+
+		agent.browser.name = agent.browser.name.toLowerCase();
+		agent.os.name = agent.os.name.toLowerCase();
+
+		return agent;
+	};
+
+	ns.agent = function() {
+		var info = UAParser.create(global.navigator.userAgent);
+		return resultCache(this, "agent", [info], info);
+	};
+
+	/**
+	 * Get a translate string
+	 *
+	 * @ko translate 문자를 반환한다.
+	 * @method eg#translate
+	 * @param {String} x x-coordinate <ko>x 좌표</ko>
+	 * @param {String} y y-coordinate <ko>y 좌표</ko>
+	 * @param {Boolean} [isHA] isHWAccelerable <ko>하드웨어 가속 여부</ko>
+	 * @return {String}
+	 * @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)" :
+								")");
+	};
+
+	/**
+	 * Check hardware acceleration support
+	 *
+	 * @ko 해당 기기에서 하드웨어 가속을 할 수 있다면 true을 반환하며, 값은 캐싱된다.
+	 * @method eg#isHWAccelerable
+	 * @return {Boolean}
+	 * @example
+eg.isHWAccelerable();  // Returns 'true' when supports hardware acceleration
+
+// 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 = (UAParser.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);
+	};
+
+	/**
+	 * Check CSS transition support
+	 *
+	 * @ko 해당 기기에서 css transtion을 할 수 있다면 true을 반환하며, 값은 캐싱된다.
+	 * @method eg#isTransitional
+	 * @return {Boolean}
+	 * @example
+eg.isTransitional();  // Returns 'true' when supports CSS transition
+
+// 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/.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 = browser.indexOf("safari") !== -1 ||
+							(browser.indexOf("ie") !== -1 &&
+								parseInt(agent.browser.nativeVersion, 10) >= 10);
+					break;
+				default :
+					result = /chrome|firefox|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);
+	};
+
+	/*
+	* requestAnimationFrame polyfill
+	* @ko requestAnimationFrame 폴리필
+	* @method eg#requestAnimationFrame
+	* @param {Function} timer function
+	* @return {Number} key
+	* @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);
+	};
+	/*
+	* cancelAnimationFrame polyfill
+	* @ko cancelAnimationFrame 폴리필
+	* @method eg#cancelAnimationFrame
+	* @param {Number} key
+	* @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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/flicking.js.html b/doc/flicking.js.html new file mode 100644 index 0000000..756c0a1 --- /dev/null +++ b/doc/flicking.js.html @@ -0,0 +1,1951 @@ + + + + + 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
+	/**
+	 * To build flickable UI
+	 * @group egjs
+	 * @ko 플리킹 UI를 구성한다.
+	 * @class
+	 * @name eg.Flicking
+	 * @extends eg.Component
+	 *
+	 * @param {HTMLElement|String|jQuery} element wrapper element <ko>기준 요소</ko>
+	 * @param {Object} options
+	 * @param {Boolean} [options.hwAccelerable=eg.isHWAccelerable()] Force to use HW compositing <ko>하드웨어 가속 사용여부</ko>
+	 * @param {String} [options.prefix=eg-flick] Prefix string for flicking elements <ko>요소에 설정될 접두사</ko>
+	 * @param {Number} [options.deceleration=0.0006] Deceleration value can be altered to change the momentum animation duration. higher numbers make the animation shorter <ko>감속계수는 가속도를 조절하여 애니메이션 시간을 변경할 수 있다. 높을수록 애니메이션이 짧아진다.</ko>
+	 * @param {Boolean} [options.horizontal=true] For move direction (when horizontal is false, then move direction is vertical) <ko>이동방향 설정 (horizontal == true 가로방향, horizontal == false 세로방향)</ko>
+	 * @param {Boolean} [options.circular=false] To make panels rotate infinitely  <ko>순환 여부</ko>
+	 * @param {Number|Array} [options.previewPadding=[0,0]] Padding value to display previous and next panels. If set array value the order is left(up) to right(down) <ko>이전과 다음 패널을 출력하는 프리뷰 형태에 사용되는 padding 값. 배열 형태로 지정시 좌측(상단), 우측(하단) 순서로 지정</ko>
+	 * @param {Number} [options.threshold=40] Threshold pixels to move panels in prev/next direction <ko>다음 패널로 이동되기 위한 임계치 픽셀</ko>
+	 * @param {Number} [options.duration=100] Duration time of panel change animation in milliseconds <ko>패널 이동 애니메이션 진행시간(ms) 값</ko>
+	 * @param {Function} [options.panelEffect=easeOutCubic] easing function which is used on panel move animation<ko>패널 간의 이동 애니메이션에 사용되는 effect easing 함수</ko>
+	 * @param {Number} [options.defaultIndex=0] Default panel index to show in first time <ko>초기에 출력할 패널 인덱스</ko>
+	 * @param {Array} [options.inputType] inputType you can control input type. a kind of inputs are "touch", "mouse".  default value is ["touch", "mouse"] <ko>입력 타입을 지정할수 있다. 입력타입은 "touch", "mouse"가 있으며, 배열로 입력할 수 있다. (기본값은 ["touch", "mouse"] 이다)</ko>
+	 *
+	 * @codepen {"id":"rVOpPK", "ko":"플리킹 기본 예제", "en":"Flicking default example", "collectionId":"ArxyLK", "height" : 403}
+	 *
+	 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
+	 *
+	 * @see Easing Functions Cheat Sheet {@link http://easings.net/}
+	 * @see If you want to use another easing function then should be import jQuery easing plugin({@link http://gsgd.co.uk/sandbox/jquery/easing/}) or jQuery UI easing.({@link https://jqueryui.com/easing/})<ko>다른 easing 함수를 사용하고 싶다면, jQuery easing plugin({@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
+			}
+
+			$.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: [0, 0],	// preview padding value in left(up) to right(down) order. In this mode at least 5 panels are required.
+				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 padding = this.options.previewPadding;
+
+			if (typeof padding === "number") {
+				padding = this.options.previewPadding = [ padding, padding ];
+			} else if (padding.constructor !== Array) {
+				padding = this.options.previewPadding = [ 0, 0 ];
+			}
+
+			// config value
+			this._conf = {
+				panel: {
+					$list: $children,	// panel list
+					index: 0,			// current physical dom index
+					no: 0,				// current logical panel index
+					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
+				},
+				customEvent: {			// for custom events value
+					flick: true,
+					restore: false,
+					restoreCall: false
+				},
+				useLayerHack: this.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"]][+!this.options.horizontal]).each(
+				$.proxy(function (i, v) {
+					this._conf.dirData.push(MC["DIRECTION_" + v]);
+				}, this));
+
+			!ns._hasClickBug() && (this._setPointerEvents = $.noop);
+
+			this._build();
+			this._bindEvents();
+
+			this._applyPanelsCss();
+			this._arrangePanels();
+
+			this.options.hwAccelerable && SUPPORT_WILLCHANGE && this._setHint();
+			this._adjustContainerCss("end");
+		},
+
+		/**
+		 * 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;
+
+			this._setPadding(padding, true);
+			var sizeValue = this._getDataByDirection([ panel.size, "100%" ]);
+
+			// panels' css values
+			$children.addClass(prefix + "-panel").css({
+				position: "absolute",
+				width: sizeValue[0],
+				height: sizeValue[1],
+				top: 0,
+				left: 0
+			});
+
+			// create container element
+			cssValue = "position:relative;z-index:2000;width:100%;height:100%;" +
+				(!horizontal ? "top:" + padding[0] + "px;" : "");
+
+			this.$container = $children.wrapAll(
+				"<div class='" + prefix + "-container' style='" + cssValue + "' />"
+			).parent();
+
+			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
+			}).bind(this.$wrapper, {
+				scale: this._getDataByDirection([-1, 0]),
+				direction: MC["DIRECTION_" +
+					(horizontal ? "HORIZONTAL" : "VERTICAL")],
+				interruptable: false,
+				inputType: options.inputType
+			});
+
+			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;
+
+			panel.size = this.$wrapper[
+				horizontal ? "outerWidth" : "height"
+			]() - (padding[0] + padding[1]);
+
+			var cssValue = {
+				padding: (horizontal ?
+				"0 " + padding.reverse().join("px 0 ") :
+				padding.join("px 0 ")) + "px"
+			};
+
+			if (build) {
+				cssValue.overflow = "hidden";
+			} else if (!horizontal) {
+				this.$container.css("top", padding[0]);
+			}
+
+			this.$wrapper.css(cssValue);
+		},
+
+		/**
+		 * 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;
+
+			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
+				this._movePanelPosition(this._getBasePositionIndex(), false);
+
+				panel.no = index;
+			} else {
+				// if defaultIndex option is given, then move to that index panel
+				if (index > 0 && index <= lastIndex) {
+					panel.no = panel.index = 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;
+
+			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
+				panel.index = this._getBasePositionIndex();
+
+				// 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) {
+			isDirVal && 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) {
+			!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 () {
+			var panel = this._conf.panel;
+			return panel.index = Math.floor(panel.count / 2 - 0.1);
+		},
+
+		/**
+		 * Bind events
+		 */
+		_bindEvents: function () {
+			this._mcInst.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)
+			});
+		},
+
+		/**
+		 * 'hold' event handler
+		 */
+		_holdHandler: function (e) {
+			this._conf.touch.holdPos = e.pos;
+			this._conf.panel.changed = false;
+
+			this._adjustContainerCss("start", e.pos);
+		},
+
+		/**
+		 * 'change' event handler
+		 */
+		_changeHandler: function (e) {
+			var conf = this._conf;
+			var touch = conf.touch;
+			var pos = e.pos;
+			var direction;
+			var eventRes = null;
+			var movedPx;
+
+			this._setPointerEvents(e);  // for "click" bug
+
+			/**
+			 * Occurs during the change
+			 * @ko 패널이 이동될 때 발생하는 이벤트
+			 * @name eg.Flicking#flick
+			 * @event
+			 * @param {Object} param
+			 * @param {String} param.eventType Name of event <ko>이벤트명</ko>
+			 * @param {Number} param.index Current panel physical index <ko>현재 패널 물리적 인덱스</ko>
+			 * @param {Number} param.no Current panel logical position <ko>현재 패널 논리적 인덱스</ko>
+			 * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) <ko>플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인)</ko>
+			 * @param {Array} param.pos Departure coordinate <ko>출발점 좌표</ko>
+			 * @param {Number} param.pos.0 Departure x-coordinate <ko>x 좌표</ko>
+			 * @param {Boolean} param.holding Holding if an area is pressed, this value is 'true'. <ko>스크린을 사용자가 누르고 있을 경우 true </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
+			}));
+
+			(eventRes || eventRes === null) && this._setTranslate([
+				-pos[+!this.options.horizontal], 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");
+
+			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, "");
+
+			/**
+			 * Before panel restores it's last position
+			 * @ko 플리킹 임계치에 도달하지 못하고 사용자의 액션이 끝났을 경우, 원래 패널로 복원되기 전에 발생하는 이벤트
+			 * @name eg.Flicking#beforeRestore
+			 * @event
+			 *
+			 * @param {Object} param
+			 * @param {String} param.eventType Name of event <ko>이벤트명</ko>
+			 * @param {Number} param.index Current panel physical index <ko>현재 패널 물리적 인덱스</ko>
+			 * @param {Number} param.no Current panel logical position <ko>현재 패널 논리적 인덱스</ko>
+			 * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) <ko>플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인)</ko>
+			 * @param {Array} param.depaPos Departure coordinate <ko>출발점 좌표</ko>
+			 * @param {Number} param.depaPos.0 Departure x-coordinate <ko>x 좌표</ko>
+			 * @param {Number} param.depaPos.1 Departure y-coordinate <ko>y 좌표</ko>
+			 * @param {Array} param.destPos Destination coordinate <ko>도착점 좌표</ko>
+			 * @param {Number} param.destPos.0 Destination x-coordinate <ko>x 좌표</ko>
+			 * @param {Number} param.destPos.1 Destination 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;
+
+			/**
+			 * After panel restores it's last position
+			 * @ko 플리킹 임계치에 도달하지 못하고 사용자의 액션이 끝났을 경우, 원래 인덱스로 복원된 후 발생하는 이벤트
+			 * @name eg.Flicking#restore
+			 * @event
+			 *
+			 * @param {Object} param
+			 * @param {String} param.eventType Name of event <ko>이벤트명</ko>
+			 * @param {Number} param.index Current panel physical index <ko>현재 패널 물리적 인덱스</ko>
+			 * @param {Number} param.no Current panel logical position <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())) {
+				conf.indexToMove === 0 && this._setPanelNo();
+
+				/**
+				 * Before panel changes
+				 * @ko 플리킹이 시작되기 전에 발생하는 이벤트
+				 * @name eg.Flicking#beforeFlickStart
+				 * @event
+				 *
+				 * @param {Object} param
+				 * @param {String} param.eventType Name of event <ko>이벤트명</ko>
+				 * @param {Number} param.index Current panel physical index <ko>현재 패널 물리적 인덱스</ko>
+				 * @param {Number} param.no Current panel logical position <ko>현재 패널 논리적 인덱스</ko>
+				 * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) <ko>플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인)</ko>
+				 * @param {Array} param.depaPos Departure coordinate <ko>출발점 좌표</ko>
+				 * @param {Number} param.depaPos.0 Departure x-coordinate <ko>x 좌표</ko>
+				 * @param {Number} param.depaPos.1 Departure y-coordinate <ko>y 좌표</ko>
+				 * @param {Array} param.destPos Destination coordinate <ko>도착점 좌표</ko>
+				 * @param {Number} param.destPos.0 Destination x-coordinate <ko>x 좌표</ko>
+				 * @param {Number} param.destPos.1 Destination y-coordinate <ko>y 좌표</ko>
+				 */
+				if (!this._triggerEvent(EVENTS.beforeFlickStart, pos)) {
+					return panel.changed = panel.animating = false;
+				}
+			} 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;
+
+				/**
+				 * After panel changes
+				 * @ko 플리킹으로 패널이 이동된 후 발생하는 이벤트
+				 * @name eg.Flicking#flickEnd
+				 * @event
+				 *
+				 * @param {Object} param
+				 * @param {String} param.eventType Name of event <ko>이벤트명</ko>
+				 * @param {Number} param.index Current panel physical index <ko>현재 패널 물리적 인덱스</ko>
+				 * @param {Number} param.no Current panel logical position <ko>현재 패널 논리적 인덱스</ko>
+				 * @param {Number} param.direction Direction of the panel move (see eg.MovableCoord.DIRECTION_* constant) <ko>플리킹 방향 (eg.MovableCoord.DIRECTION_* constant 확인)</ko>
+				 */
+				panel.changed && this._triggerEvent(EVENTS.flickEnd);
+			}
+
+			!(phase === "start" && pos === undefined) && this._adjustContainerCss(phase);
+		},
+
+		/**
+		 * Set the logical panel index number
+		 * @param {Boolean} recover
+		 */
+		_setPanelNo: function (recover) {
+			var panel = this._conf.panel;
+			var count = panel.origCount - 1;
+			var num = this._conf.touch.direction === this._conf.dirData[0] ? 1 : -1;
+
+			if (recover) {
+				panel.index = panel.prevIndex >= 0 ?
+					panel.prevIndex : panel.index - num;
+
+				panel.no = panel.prevNo >= 0 ?
+					panel.prevNo : panel.no - num;
+
+			} else {
+				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.
+			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) {
+			var options = this.options;
+
+			if (!SUPPORT_TRANSFORM && !options.horizontal) {
+				coords[0] += options.previewPadding[0];
+			}
+
+			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 () {
+			return Math.abs(this._conf.touch.distance) >= this.options.threshold;
+		},
+
+		/**
+		 * 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;
+
+			return this.trigger(conf.eventPrefix + name, $.extend({
+				eventType: name,
+				index: panel.index,
+				no: panel.no,
+				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.index;
+			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.no;
+			}
+
+			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;
+		},
+
+		/**
+		 * Get current panel position
+		 * @ko 현재 패널의 인덱스 값을 반환한다.
+		 * @method eg.Flicking#getIndex
+		 * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) <ko>물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적)</ko>
+		 * @return {Number} Number Current index number <ko>현재 패널 인덱스 번호</ko>
+		 */
+		getIndex: function (physical) {
+			return this._conf.panel[ physical ? "index" : "no" ];
+		},
+
+		/**
+		 * Get current panel element
+		 * @ko 현재 패널 요소의 레퍼런스를 반환한다.
+		 * @method eg.Flicking#getElement
+		 * @return {jQuery} jQuery Current element <ko>현재 요소</ko>
+		 */
+		getElement: function () {
+			var panel = this._conf.panel;
+			return $(panel.$list[panel.index]);
+		},
+
+		/**
+		 * Get next panel element
+		 * @ko 다음 패널 요소의 레퍼런스를 반환한다.
+		 * @method eg.Flicking#getNextElement
+		 * @return {jQuery|null} Next element or null if no more element exist<ko>다음 패널 요소. 패널이 없는 경우에는 null</ko>
+		 */
+		getNextElement: function () {
+			return this._getElement(this._conf.dirData[0], true);
+		},
+
+		/**
+		 * Get next panel index
+		 * @ko 다음 패널의 인덱스 값을 반환한다.
+		 * @method eg.Flicking#getNextIndex
+		 * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) <ko>물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적)</ko>
+		 * @return {Number|null} Next element index value or null if no more element exist<ko>다음 패널 인덱스 번호. 패널이 없는 경우에는 null</ko>
+		 */
+		getNextIndex: function (physical) {
+			return this._getElement(this._conf.dirData[0], false, physical);
+		},
+
+		/**
+		 * Get whole panel elements
+		 * @ko 패널을 구성하는 모든 요소들의 레퍼런스를 반환한다.
+		 * @method eg.Flicking#getAllElements
+		 * @return {jQuery} jQuery All panel elements <ko>모든 패널 요소</ko>
+		 */
+		getAllElements: function () {
+			return this._conf.panel.$list;
+		},
+
+		/**
+		 * Get previous panel element
+		 * @ko 이전 패널 요소의 레퍼런스를 반환한다.
+		 * @method ns.Flicking#getPrevElement
+		 * @return {jQuery|null} Previous element or null if no more element exist <ko>이전 패널 요소. 패널이 없는 경우에는 null</ko>
+		 */
+		getPrevElement: function () {
+			return this._getElement(this._conf.dirData[1], true);
+		},
+
+		/**
+		 * Get previous panel index
+		 * @ko 이전 패널의 인덱스 값을 반환한다.
+		 * @method eg.Flicking#getPrevIndex
+		 * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) <ko>물리적/논리적 값 인덱스 불리언(true: 물리적, 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);
+		},
+
+		/**
+		 * Get total panel count
+		 * @ko 전체 패널의 개수를 반환한다.
+		 * @method eg.Flicking#getTotalCount
+		 * @param {Boolean} [physical=false] Boolean to get physical or logical index (true : physical, false : logical) <ko>물리적/논리적 값 인덱스 불리언(true: 물리적, false: 논리적)</ko>
+		 * @return {Number} Number Count of all elements <ko>모든 패널 요소 개수</ko>
+		 */
+		getTotalCount: function (physical) {
+			return this._conf.panel[ physical ? "count" : "origCount" ];
+		},
+
+		/**
+		 * Return either panel is animating or not
+		 * @ko 현재 애니메이션중인지 여부를 리턴한다.
+		 * @method eg.Flicking#isPlaying
+		 * @return {Boolean}
+		 */
+		isPlaying: function () {
+			return this._conf.panel.animating;
+		},
+
+		/**
+		 * Move panel to the given direction
+		 * @param {Boolean} next
+		 * @param {Number} duration
+		 */
+		_movePanel: function (next, duration) {
+			var panel = this._conf.panel;
+			var options = this.options;
+
+			if (panel.animating) {
+				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");
+			}
+		},
+
+		/**
+		 * Move to next panel
+		 * @ko 다음 패널로 이동한다.
+		 * @method eg.Flicking#next
+		 * @param {Number} [duration=options.duration] Duration of animation in milliseconds <ko>애니메이션 진행시간(ms)</ko>
+		 * @return {eg.Flicking} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		next: function (duration) {
+			return this._movePanel(true, duration);
+		},
+
+		/**
+		 * Move to previous panel
+		 * @ko 이전 패널로 이동한다.
+		 * @method eg.Flicking#prev
+		 * @param {Number} [duration=options.duration] Duration of animation in milliseconds <ko>애니메이션 진행시간(ms)</ko>
+		 * @return {eg.Flicking} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		prev: function (duration) {
+			return this._movePanel(false, duration);
+		},
+
+		/**
+		 * Move to indicated panel
+		 * @ko 지정한 패널로 이동한다.
+		 * @method eg.Flicking#moveTo
+		 * @param {Number} no logical panel index
+		 * @param {Number} [duration=options.duration] Duration of animation in milliseconds <ko>애니메이션 진행시간(ms)</ko>
+		 * @return {eg.Flicking} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		moveTo: function (no, duration) {
+			var panel = this._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) {
+				return this;
+			}
+
+			// remember current value in case of restoring
+			panel.prevIndex = currentIndex;
+			panel.prevNo = panel.no;
+
+			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;
+				}
+
+				panel.no = no;
+			} else {
+				indexToMove = no - currentIndex;
+				panel.no = panel.index = 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);
+			}
+		},
+
+		/**
+		 * Update panel size according current viewport
+		 * @ko 패널 사이즈 정보를 갱신한다.
+		 * @method eg.Flicking#resize
+		 * @return {eg.Flicking} instance of 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;
+		},
+
+		/**
+		 * Restore panel in its right position
+		 * @ko 패널의 위치가 올바로 위치하지 않게 되는 경우, 제대로 위치하도록 보정한다.
+		 * @method eg.Flicking#restore
+		 * @param {Number} [duration=options.duration] Duration of animation in milliseconds <ko>애니메이션 진행시간(ms)</ko>
+		 * @return {eg.Flicking} instance of 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.size) {
+				conf.customEvent.restoreCall = true;
+				duration = this._getNumValue(duration, this.options.duration);
+
+				this._setPanelNo(true);
+				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._setPanelNo(true);
+
+				conf.touch.distance = conf.indexToMove = 0;
+				panel.prevIndex = panel.prevNo = -1;
+			}
+
+			return this;
+		}
+	});
+});
+/**
+ * Flicking in jQuery plugin
+ *
+ * @ko Flicking in jQuery plugin
+ * @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
+ */
+/**
+ * flicking:beforeRestore jQuery event plugin
+ *
+ * @ko flicking:beforeRestore jQuery event plugin
+ * @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
+ */
+/**
+ * flicking:beforeFlickStart jQuery event plugin
+ *
+ * @ko flicking:beforeFlickStart jQuery event plugin
+ * @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
+ */
+/**
+ * flicking:flick jQuery event plugin
+ *
+ * @ko flicking:flick jQuery event plugin
+ * @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
+ */
+/**
+ * flicking:flickEnd jQuery event plugin
+ *
+ * @ko flicking:flickEnd jQuery event plugin
+ * @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
+ */
+/**
+ * flicking:restore jQuery event plugin
+ *
+ * @ko flicking:restore jQuery event plugin
+ * @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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/fonts/glyphicons-halflings-regular.eot b/doc/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..423bd5d Binary files /dev/null and b/doc/fonts/glyphicons-halflings-regular.eot differ diff --git a/doc/fonts/glyphicons-halflings-regular.svg b/doc/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..4469488 --- /dev/null +++ b/doc/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 0000000..a498ef4 Binary files /dev/null and b/doc/fonts/glyphicons-halflings-regular.ttf differ diff --git a/doc/fonts/glyphicons-halflings-regular.woff b/doc/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..d83c539 Binary files /dev/null and b/doc/fonts/glyphicons-halflings-regular.woff differ diff --git a/doc/global.html b/doc/global.html new file mode 100644 index 0000000..6bee395 --- /dev/null +++ b/doc/global.html @@ -0,0 +1,4995 @@ + + + + + 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", "ios" : "7+", "an" : "2.1+ (except 3.x)"}() +

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

Apply css prefix cssHooks

+
+ + +
+ 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 events

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

+ + _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 + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + _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

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

+ + _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/

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

+ + _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
+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + _setPadding(padding, build) +

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

Set preview padding value

+
+ + + + + + + + + + +
    + +
  • + +
    + padding + + + +
    + + +
    Type: +Array + +
    + + + +
    + +
    + + + +
  • + +
  • + +
    + build + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + _setPanelNo(recover) +

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

Set the logical panel index number

+
+ + + + + + + + + + +
    + +
  • + +
    + recover + + + +
    + + +
    Type: +Boolean + +
    + + + +
    + +
    + + + +
  • + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + _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 Mon May 09 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 0000000..52dc5f3 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,734 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Index

+ + + + + + +

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

egjs

+

Build Status

+

'egjs' is a set of UI interactions, effects and utilities components library using jQuery, which brings easiest and fastest way to build web application in your way.

+
+ +
+ +

Components

+
    +
  • eg : Collection of base utilities, which are used in diverse egjs components.
  • +
  • eg.Class : Provide class methods to make object oriented programming style code.
  • +
  • eg.Component : Base class utility to help develop modules in component.
  • +
  • eg.MovableCoord : Easily get computed coordinate values according user actions.
  • +
  • eg.Flicking : Implement flicking interaction UI.
  • +
  • eg.Visible : Check whether elements are within viewport.
  • +
  • eg.infiniteGrid : Make card style UI arranged in grid style in infinite way.
  • +
+

jQuery Extensions

+

Methods

+
    +
  • persist : Provide cache interface to handle persisted data among history navigation.
  • +
  • css : Help to use css properties without browser's vendor prefix.
  • +
  • animate : Support transform and 3d acceleration extending jQuery's animate.
  • +
+

Events

+
    +
  • rotate : Trigger event detecting device orientation.
  • +
  • scrollEnd : Trigger event detecting end of scroll's position.
  • +
+

Download

+

For latest version, check out - https://github.com/naver/egjs/tree/gh-pages/latest/dist

+

Uncompressed (for development)

+ +

Compressed (for production)

+ +

with Bower

+
# Intall bower if not (admin account required)
+$ npm install bower -g
+
+# then intall egjs using bower
+$ bower install egjs
+

Browser support

+ + + + + + + + + + + + + + + + + + + + + +
Internet ExplorerChromeFireFoxSafariiOSAndroid
7+LatestLatestLatest7+2.3+ (except 3.x)
+
    +
  • Coverage could be vary among components. For more details check out API documentation.
  • +
+

Dependency library

+

egjs has following dependencies.

+ + + + + + + + + + + + + + + +
jQueryhammer.jsOutlayer
1.7.0+2.0.4+1.4.1+
+
    +
  • Except jQuery, others are not mandatory. Required dependencies may differ according components.
  • +
+

How to use?

+

Load jQuery first, then load egjs.

+
<!-- load jQuery --> 
+<script src="bower_components/jquery/jquery.js"></script>
+
+<!-- load egjs packaged with all dependencies (hammer.js and outlayer) --> 
+<script src="bower_components/egjs/dist/pkgd/eg.pkgd.min.js"></script>
+
+

NOTE: For more details on separate dependency file inclusion, check out Download and Using egjs wiki page.

+
+

All done, ready to start using egjs! +egjs has eg namespace and can be used as below example.

+
var Klass = eg.Class({
+    "construct" : function(){}
+});
+var Komponent = eg.Class.extend(eg.Component,{
+    "construct" : function(){}
+});
+

How to start developing egjs?

+

For anyone interested to develop egjs, follow below instructions.

+

Steps for setting project

+

1. Install grunt-cli and bower

+
# Install grunt-cli and bower globally (admin account required)
+$ npm install grunt-cli -g  # grunt-cli
+$ npm install bower -g  # bower
+

2. Clone from repo and install dependency modules

+
# make directory and enter
+$ mkdir egjs && cd egjs
+
+# get the clone from the repo
+$ git clone https://github.com/naver/egjs.git
+
+# install bower dependency modules
+$ bower install
+
+# install node dependency modules
+$ npm install
+

3. Build

+

Run grunt build task to build.

+
$ grunt build
+

If the build successfully complete :

+
    +
  • eg.js and eg.min.js are created in dist folder.
  • +
  • API documentations are created in doc folder, and can be accessed doc/index.html.
  • +
+

Test

+

After development has been done from your branch, must run unit test before push. +Running grunt test task, jshint, qunit and istanbul coverage task will be run.

+
$ grunt test
+
    +
  • Coverage results can be shown immediately and also can be found at ./report/index.html.
  • +
+

Issues

+

If you find a bug, please report us via issues page.

+

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 Mon May 09 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 0000000..678e5fc --- /dev/null +++ b/doc/infiniteGrid.js.html @@ -0,0 +1,1471 @@ + + + + + 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, "Outlayer"], function($, ns, global, doc, Outlayer) {
+	"use strict";
+
+	// jscs:enable validateLineBreaks, maximumLineLength
+	if (!Outlayer) {
+		ns.InfiniteGrid = ns.Class({});
+		return;
+	}
+
+	function clone(target, source, what) {
+		var s;
+		$.each(what, function(i, v) {
+			s = source[v];
+			if (s != null) {
+				if ($.isArray(s)) {
+					target[v] = $.merge([], s);
+				} else if ($.isPlainObject(s)) {
+					target[v] = $.extend(true, {}, s);
+				} else {
+					target[v] = s;
+				}
+			}
+		});
+		return target;
+	}
+
+	var InfiniteGridCore = Outlayer.create("InfiniteGrid");
+	$.extend(InfiniteGridCore.prototype, {
+		// @override (from layout)
+		_resetLayout: function() {
+			if (!this._isLayoutInited) {
+				this._registGroupKey(this.options.defaultGroupKey, this.items);
+			}
+			this.element.style.width = null;
+			this.getSize();	// create size property
+			this._measureColumns();
+		},
+
+		// @override
+		_getContainerSize: function() {
+			return {
+				height: Math.max.apply(Math, this._appendCols),
+				width: this.size.innerWidth
+			};
+		},
+
+		// @override
+		_getItemLayoutPosition: function(item) {
+			if (this._equalItemSize) {
+				item.size = this._equalItemSize;
+			} else {
+				item.getSize();
+			}
+			(item.isAppend == null) && (item.isAppend = true);
+			var outerHeight = parseInt(item.size.outerHeight, 10);
+			var shortColIndex;
+			var isAppend = item.isAppend;
+			var cols = isAppend ? this._appendCols : this._prependCols;
+			var y = Math[isAppend ? "min" : "max"].apply(Math, cols);
+			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 ? outerHeight : -outerHeight);
+
+			return {
+				x: this.columnWidth * shortColIndex,
+				y: isAppend ? y : y - outerHeight
+			};
+		},
+		resetLayout: function() {
+			this._resetLayout();
+			this._isLayoutInited = true;
+		},
+		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.outerHeight : -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;
+			}));
+		},
+		_measureColumns: function() {
+			var containerWidth = this.size.innerWidth;
+			var columnWidth = this._getColumnWidth();
+			var cols = containerWidth / columnWidth;
+			var excess = columnWidth - containerWidth % 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._appendCols = [];
+			this._prependCols = [];
+			while (cols--) {
+				this._appendCols.push(0);
+				this._prependCols.push(0);
+			}
+		},
+		_getColumnWidth: function() {
+			var el = this.items[0] && this.items[0].element;
+			var size;
+			if (el) {
+				/* jshint ignore:start */
+				size = getSize(el);
+				/* jshint ignore:end */
+			} else {
+				size = {
+					outerWidth: 0,
+					outerHeight: 0
+				};
+			}
+			this.options.isEqualSize && (this._equalItemSize = size);
+			this.columnWidth = size.outerWidth || this.size.outerWidth;
+			return this.columnWidth;
+		},
+		_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;
+		},
+		clone: function(target, source) {
+			clone(target, source, [
+				"_isLayoutInited",
+				"_equalItemSize",
+				"_appendCols",
+				"_prependCols",
+				"columnWidth",
+				"size",
+				"options"
+				]);
+			target.items = target.items || [];
+			target.items.length = source.items.length;
+			$.each(source.items, function(i) {
+				target.items[i] = clone(target.items[i] || {}, source.items[i],
+					["position", "size", "isAppend", "groupKey"]);
+			});
+			return target;
+		},
+		itemize: function(elements, groupKey) {
+			var items = this._itemize(elements);
+			this._registGroupKey(groupKey, items);
+			return items;
+		},
+		_registGroupKey: function(groupKey, array) {
+			if (groupKey != null) {
+				var i = 0;
+				var v;
+				while (v = array[i++]) {
+					v.groupKey = groupKey;
+				}
+			}
+		},
+
+		// @override
+		destroy: function() {
+			this.off();
+			Outlayer.prototype.destroy.apply(this);
+		}
+	});
+
+	/**
+	 * To build Grid layout UI
+	 * InfiniteGrid is composed using Outlayer and supports recycle-dom.
+	 * DOM elements are fixed even contents are added infinitely.
+	 * @group egjs
+	 * @ko 그리드 레이아웃을 구성하는 UI 컴포넌트. InfiniteGrid는 Outlayer로 구성되어 있다. 하지만, 이 컴포넌트는 recycle-dom을 지원한다.
+	 * 컨텐츠를 계속 증가하면 할수록 일정한 DOM 개수를 유지할수 있다.
+	 * @class
+	 * @name eg.InfiniteGrid
+	 * @extends eg.Component
+	 *
+	 * @param {HTMLElement|String|jQuery} element wrapper element <ko>기준 요소</ko>
+	 * @param {Object} [options]
+	 * @param {String} [options.itemSelector] selector string for layout item elements <ko>레이아웃의 아이템으로 사용될 엘리먼트들의 셀렉터</ko>
+	 * @param {Boolean} [options.isEqualSize=false] determine if all item's size are same <ko> 모든 아이템의 사이즈가 동일한지를 지정한다</ko>
+	 * @param {String} [options.defaultGroupKey=null] when encounter item markup during the initialization, then set `defaultGroupKey` as groupKey <ko>초기화할때 마크업에 아이템이 있다면, defalutGroupKey를 groupKey로 지정한다</ko>
+	 * @param {Number} [options.count=30] when count value is greater than 0, grid will maintain same DOM length recycling <ko>count값이 0보다 클 경우, 그리드는 일정한 dom 개수를 유지한다</ko>
+	 * @param {Number} [options.threshold=300] Threshold pixels to determine if grid needs to append or prepend elements<ko>엘리먼트가 append 또는 prepend될지를 결정하는 임계치 픽셀</ko>
+	 *
+	 * @codepen {"id":"zvrbap", "ko":"InfiniteGrid 데모", "en":"InfiniteGrid example", "collectionId":"DPYEww", "height": 403}
+	 *  @support {"ie": "8+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
+	 *
+	 *  @see Outlayer {@link https://github.com/metafizzy/outlayer}
+	 *
+	 * @example
+		<!-- HTML -->
+		<ul id="grid">
+			<li class="item">
+			  <div>테스트1</div>
+			</li>
+			<li class="item">
+			  <div>테스트2</div>
+			</li>
+			<li class="item">
+			  <div>테스트3</div>
+			</li>
+			<li class="item">
+			  <div>테스트4</div>
+			</li>
+			<li class="item">
+			  <div>테스트5</div>
+			</li>
+			<li class="item">
+			  <div>테스트6</div>
+			</li>
+		</ul>
+		<script>
+		var some = new eg.InfiniteGrid("#grid", {
+			itemSelector : ".item"
+		}).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);
+			this.options.transitionDuration = 0;	// don't use this option.
+			this.options.isInitLayout = false;	// isInitLayout is always 'false' in order to controll layout.
+			this.options.isResizeBound = false;	// isResizeBound is always 'false' in order to controll layout.
+
+			// if el is jQuery instance, el should change to HTMLElement.
+			if (el instanceof $) {
+				el = el.get(0);
+			}
+			this._prefix = _prefix || "";
+			this.core = new InfiniteGridCore(el, this.options)
+				.on(EVENTS.layoutComplete, $.proxy(this._onlayoutComplete, this));
+			this.$view = $(global);
+			this._reset();
+			this.core.$element.children().length > 0 && this.layout();
+			this._onResize = $.proxy(this._onResize, this);
+			this._onScroll = $.proxy(this._onScroll, this);
+			this._isIos = ns.agent().os.name === "ios";
+			this._prevScrollTop = 0;
+			this._topElement = null;
+			this._bottomElement = null;
+			this._refreshViewport();
+			this.$view.on("resize", this._onResize);
+			this.$view.on("scroll", this._onScroll);
+		},
+		_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) {
+				ele = this._bottomElement || this.getBottomElement();
+				rect = ele.getBoundingClientRect();
+				if (rect.top <= this._clientHeight + this.options.threshold) {
+					/**
+					 * Occurs when grid needs to append elements.
+					 * in order words, when scroll reaches end of page
+					 *
+					 * @ko 엘리먼트가 append 될 필요가 있을 때 발생하는 이벤트.
+					 * 즉, 스크롤이 페이지 하단에 도달했을 때 발생한다.
+					 * @name eg.InfiniteGrid#append
+					 * @event
+					 *
+					 * @param {Object} param
+					 * @param {Number} param.scrollTop scrollTop scroll-y position of window<ko>윈도우 y 스크롤의 값</ko>
+					 */
+					this.trigger(this._prefix + EVENTS.append, {
+						scrollTop: scrollTop
+					});
+				}
+			} else {
+				if (this.isRecycling() && this._removedContent > 0 &&
+					(ele = this._topElement || this.getTopElement())) {
+					rect = ele.getBoundingClientRect();
+					if (rect.bottom >= -this.options.threshold) {
+						/**
+						 * Occurs when grid needs to prepend elements
+						 * in order words, when scroll reaches top of page and a count of cropped element is more than zero.
+						 *
+						 * @ko 엘리먼트가 prepend 될 필요가 있을 때 발생하는 이벤트.
+						 * 즉, 스크롤이 페이지 상단에 도달하고, 순환에 의해 잘려진 엘리먼트가 존재할때 발생한다.
+						 * @name eg.InfiniteGrid#prepend
+						 * @event
+						 *
+						 * @param {Object} param
+						 * @param {Number} param.scrollTop scrollTop scroll-y position of window<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;
+			function delayed() {
+				self._refreshViewport();
+				self.core.element.style.width = null;
+				self.core.needsResizeLayout() && self.layout();
+				delete self.resizeTimeout;
+			}
+			this.resizeTimeout = setTimeout(delayed, 100);
+		},
+		_refreshViewport: function() {
+			this._clientHeight = this.$view.height();
+		},
+		/**
+		 * Get current status
+		 * @ko infiniteGrid의 현재상태를 반환한다.
+		 * @method eg.InfiniteGrid#getStatue
+		 * @return {Object} infiniteGrid status Object<ko>infiniteGrid 상태 오브젝트</ko>
+		 */
+		getStatus: function() {
+			var data = [];
+			var p;
+			for (p in this) {
+				if (this.hasOwnProperty(p) && /^_/.test(p)) {
+					data.push(p);
+				}
+			}
+			return {
+				core: this.core.clone({}, this.core),
+				data: clone({}, this, data),
+				html: this.core.$element.html(),
+				cssText: this.core.element.style.cssText
+			};
+		},
+		/**
+		 * Set current status
+		 * @ko infiniteGrid의 현재상태를 설정한다.
+		 * @method eg.InfiniteGrid#setStatus
+		 * @param {Object} status Object
+		 * @return {eg.InfiniteGrid} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		setStatus: function(status) {
+			this.core.element.style.cssText = status.cssText;
+			this.core.$element.html(status.html);
+			this.core.items = this.core.itemize(this.core.$element.children().toArray());
+			this.core.clone(this.core, status.core);
+			$.extend(this, status.data);
+			return this;
+		},
+		/**
+		 * Check if element is appending or prepending
+		 * @ko append나 prepend가 진행중일 경우 true를 반환한다.
+		 * @method eg.InfiniteGrid#isProcessing
+		 * @return {Boolean}
+		 */
+		isProcessing: function() {
+			return this._isProcessing;
+		},
+		/**
+		 * Check if elements are in recycling mode
+		 * @ko recycle 모드 여부를 반환한다.
+		 * @method eg.InfiniteGrid#isRecycling
+		 * @return {Boolean}
+		 */
+		isRecycling: function() {
+			return this.core.options.count > 0 && this._isRecycling;
+		},
+		/**
+		 * Get group keys
+		 * @ko 그룹키들을 반환한다.
+		 * @method eg.InfiniteGrid#getGroupKeys
+		 * @return {Array} groupKeys
+		 */
+		getGroupKeys: function() {
+			var result = [];
+			if (this.core._isLayoutInited) {
+				var i = 0;
+				var item;
+				while (item = this.core.items[i++]) {
+					result.push(item.groupKey);
+				}
+			}
+			return result;
+		},
+		/**
+		 * Rearrange layout
+		 * @ko 레이아웃을 재배치한다.
+		 * @method eg.InfiniteGrid#layout
+		 * @return {eg.InfiniteGrid} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		layout: function() {
+			this._isProcessing = true;
+			this._isAppendType = true;
+			var i = 0;
+			var v;
+			while (v = this.core.items[i++]) {
+				v.isAppend = true;
+			}
+			this.core.layout();
+			return this;
+		},
+		/**
+		 * Append elements
+		 * @ko 엘리먼트를 append 한다.
+		 * @method eg.InfiniteGrid#append
+		 * @param {Array|String|jQuery} elements to be appended elements <ko>append될 엘리먼트 배열</ko>
+		 * @param {Number|String} [groupKey] to be appended groupkey of elements<ko>append될 엘리먼트의 그룹키</ko>
+		 * @return {Number} length a number of 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.core.items.length + $elements.length) >= this.core.options.count;
+			}
+			this._insert($elements, groupKey, true);
+			return $elements.length;
+		},
+		/**
+		 * Prepend elements
+		 * @ko 엘리먼트를 prepend 한다.
+		 * @method eg.InfiniteGrid#prepend
+		 * @param {Array|String|jQuery} elements to be prepended elements <ko>prepend될 엘리먼트 배열</ko>
+		 * @param {Number|String} [groupKey] to be prepended groupkey of elements<ko>prepend될 엘리먼트의 그룹키</ko>
+		 * @return {Number} length a number of 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;
+		},
+		/**
+		 * Clear elements and data
+		 * @ko 엘리먼트와 데이터를 지운다.
+		 * @method eg.InfiniteGrid#clear
+		 * @return {eg.InfiniteGrid} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		clear: function() {
+			this.core.$element.empty();
+			this.core.items.length = 0;
+			this._reset();
+			this.layout();
+			return this;
+
+		},
+
+		_getTopItem: function() {
+			var item = null;
+			var min = Infinity;
+			$.each(this.core.getColItems(false), function(i, v) {
+				if (v && v.position.y < min) {
+					min = v.position.y;
+					item = v;
+				}
+			});
+			return item;
+		},
+
+		/**
+		 * Get the first element at the top
+		 * @ko 가장 위에 있는 엘리먼트를 반환한다.
+		 * @method eg.InfiniteGrid#getTopElement
+		 *
+		 * @return {HTMLElement} element
+		 */
+		getTopElement: function() {
+			var item = this._getTopItem();
+			return item && item.element;
+		},
+
+		_getBottomItem: function() {
+			var item = null;
+			var max = -Infinity;
+			$.each(this.core.getColItems(true), function(i, v) {
+				if (v && v.position.y + v.size.outerHeight > max) {
+					max = v.position.y + v.size.outerHeight;
+					item = v;
+				}
+			});
+			return item;
+		},
+
+		/**
+		 * Get the last element at the bottom
+		 * @ko 가장 아래에 있는 엘리먼트를 반환한다.
+		 * @method eg.InfiniteGrid#getBottomElement
+		 *
+		 * @return {HTMLElement} element
+		 */
+		getBottomElement: function() {
+			var item = this._getBottomItem();
+			return item && item.element;
+		},
+
+		_onlayoutComplete: function(e) {
+			var distance = 0;
+			var isAppend = this._isAppendType;
+			var item;
+			var i = 0;
+			while (item = e[i++]) {
+				if (typeof item.oldVisibility !== "undefined") {
+					item.element.style.visibility = item.oldVisibility;
+					delete item.oldVisibility;
+				}
+			}
+
+			// refresh element
+			this._topElement = this.getTopElement();
+			this._bottomElement = this.getBottomElement();
+
+			if (isAppend === false) {
+				this._isFitted = false;
+				this._fit(true);
+				distance = e.length >= this.core.items.length ?
+					0 : this.core.items[e.length].position.y;
+				if (distance > 0) {
+					this._prevScrollTop = this._getScrollTop() + distance;
+					this.$view.scrollTop(this._prevScrollTop);
+				}
+			}
+
+			// reset flags
+			this._reset(true);
+
+			/**
+			 * Occurs when layout is completed (after append / after prepend / after layout)
+			 * @ko 레이아웃이 완료 되었을 때 발생하는 이벤트 (append/prepend/layout 메소드 호출 후, 아이템의 배치가 완료되었을때 발생)
+			 * @name eg.InfiniteGrid#layoutComplete
+			 * @event
+			 *
+			 * @param {Object} param
+			 * @param {Array} param.target target rearranged elements<ko>재배치된 엘리먼트들</ko>
+			 * @param {Boolean} param.isAppend isAppend determine if append or prepend (value is true when call layout method)<ko>아이템이 append로 추가되었는지, prepend로 추가되었는지를 반한환다. (layout호출시에는 true)</ko>
+			 * @param {Number} param.distance the distance of moved top-element after layoutComplete event is triggered. in order words, prepended distance or height <ko>최상단 엘리먼트가 layoutComplete 이벤트 발생 후,이동되어진 거리. 즉, prepend 되어 늘어난 거리(높이)</ko>
+			 * @param {Number} param.croppedCount the count of removed elements for recycle-dom. <ko>순환 구조에 의해, 삭제된 엘리먼트 개수</ko>
+			 */
+			this.trigger(this._prefix + EVENTS.layoutComplete, {
+				target: e.concat(),
+				isAppend: isAppend,
+				distance: distance,
+				croppedCount: this._removedContent
+			});
+		},
+
+		// $elements => $([HTMLElement, HTMLElement, ...])
+		_insert: function($elements, groupKey, isAppend) {
+			if ($elements.length === 0) {
+				return;
+			}
+			this._isAppendType = isAppend;
+			var elements = $elements.toArray();
+			var $cloneElements = $(elements);
+			var i = 0;
+			var item;
+			var items = this.core.itemize(elements, groupKey);
+			while (item = items[i++]) {
+				item.isAppend = isAppend;
+				item.oldVisibility = item.element.style.visibility;
+				item.element.style.visibility = "hidden";
+			}
+			if (isAppend) {
+				this.core.items = this.core.items.concat(items);
+			} else {
+				this.core.items = items.concat(this.core.items.slice(0));
+				items = items.reverse();
+			}
+			if (this.isRecycling()) {
+				this._adjustRange(isAppend, $cloneElements);
+			}
+			var noChild = this.core.$element.children().length === 0;
+			this.core.$element[isAppend ? "append" : "prepend"]($cloneElements);
+			noChild && this.core.resetLayout();		// for init-items
+
+			var needCheck = this._checkImageLoaded($cloneElements);
+			if (needCheck.length > 0) {
+				this._waitImageLoaded(items, needCheck);
+			} else {
+				// convert to async
+				var self = this;
+				setTimeout(function() {
+					self.core.layoutItems(items, true);
+				}, 0);
+			}
+		},
+		_adjustRange: function (isTop, $elements) {
+			var diff = this.core.items.length - this.core.options.count;
+			var targets;
+			var idx;
+			if (diff <= 0 || (idx = this._getDelimiterIndex(isTop, diff)) < 0) {
+				return;
+			}
+			if (isTop) {
+				targets = this.core.items.slice(0, idx);
+				this.core.items = this.core.items.slice(idx);
+				this._isFitted = false;
+			} else {
+				targets = this.core.items.slice(idx);
+				this.core.items = this.core.items.slice(0, idx);
+			}
+
+			// @todo improve performance
+			var i = 0;
+			var item;
+			var el;
+			while (item = targets[i++]) {
+				el = item.element;
+				idx = $elements.index(el);
+				if (idx !== -1) {
+					$elements.splice(idx, 1);
+				} else {
+					el.parentNode.removeChild(el);
+				}
+			}
+			this._removedContent += isTop ? targets.length : -targets.length;
+
+		},
+		_getDelimiterIndex: function(isTop, removeCount) {
+			var len = this.core.items.length;
+			var i;
+			var idx = 0;
+			var baseIdx = isTop ? removeCount - 1 : len - removeCount;
+			var targetIdx = baseIdx + (isTop ? 1 : -1);
+			var groupKey = this.core.items[baseIdx].groupKey;
+			if (groupKey != null && groupKey === this.core.items[targetIdx].groupKey) {
+				if (isTop) {
+					for (i = baseIdx; i > 0; i--) {
+						if (groupKey !== this.core.items[i].groupKey) {
+							break;
+						}
+					}
+					idx =  i === 0 ? -1 : i + 1;
+				} else {
+					for (i = baseIdx; i < len; i++) {
+						if (groupKey !== this.core.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.core.options.count <= 0) {
+				this._fit = function() {
+					return false;
+				};
+				this._isFitted = true;
+				return false;
+			}
+
+			if (this._isFitted) {
+				return false;
+			}
+
+			var item;
+			var height;
+			var i = 0;
+			var y = this.core.updateCols();	// for prepend
+			while (item = this.core.items[i++]) {
+				item.position.y -= y;
+				applyDom && item.css({
+					"top": item.position.y + "px"
+				});
+			}
+			this.core.updateCols(true);	// for append
+			height = this.core._getContainerSize().height;
+			applyDom && this.core._setContainerMeasure(height, false);
+			this._isFitted = true;
+			return true;
+		},
+
+		/**
+		 * Remove white space which was removed by append action.
+		 * @ko append에 의해 제거된 빈공간을 제거한다.
+		 * @method eg.InfiniteGrid#fit
+		 * @return {Number} distance if empty space is removed, value is not zero. <ko>빈공간이 제거되면 0이 아닌 값을 반환</ko>
+		 */
+		fit: function() {
+			var item = this._getTopItem();
+			var distance = item ? item.position.y : 0;
+			this._fit(true);
+			return distance;
+		},
+		_reset: function(isLayoutComplete) {
+			if (!isLayoutComplete) {
+				this._isFitted = true;
+				this._isRecycling = false;
+				this._removedContent = 0;
+			}
+			this._isAppendType = null;
+			this._isProcessing = false;
+		},
+		_checkImageLoaded: function($elements) {
+			var needCheck = [];
+			$elements.each(function(k, v) {
+				if (v.nodeName === "IMG") {
+					!v.complete && needCheck.push(v);
+				} else if (v.nodeType &&
+					(v.nodeType === 1 || v.nodeType === 9 || v.nodeType === 11)) {	// ELEMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE
+					needCheck = needCheck.concat($(v).find("img").filter(function(fk, fv) {
+						return !fv.complete;
+					}).toArray());
+				}
+			});
+			return needCheck;
+		},
+		_waitImageLoaded: function(items, needCheck) {
+			var core = this.core;
+			var checkCount = needCheck.length;
+			var onCheck = function(e) {
+				checkCount--;
+				$(e.target).off("load error");
+				checkCount <= 0 && core.layoutItems(items, true);
+			};
+			$.each(needCheck, function(k, v) {
+				$(v).on("load error", onCheck);
+			});
+		},
+		/**
+		 * Release resources and unbind custom events
+		 * @ko 모든 커스텀 이벤트와 자원을 해제한다.
+		 * @method eg.InfiniteGrid#destroy
+		 */
+		destroy: function() {
+			if (this.core) {
+				this.core.destroy();
+				this.core = null;
+			}
+			this.$view.off("resize", this._onResize)
+				.off("scroll", this._onScroll);
+			this.off();
+		}
+	});
+});
+/**
+ * InfiniteGrid in jQuery plugin
+ * @ko InfiniteGrid in jQuery plugin
+ * @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({
+        itemSelector : ".item"
+    });
+ 	// method
+ 	$("#grid").infiniteGrid("option","itemSelector",".selected"); //Set option
+ 	$("#grid").infiniteGrid("instance"); // Return infiniteGrid instance
+ 	$("#grid").infiniteGrid("getBottomElement"); // Get bottom element
+ 	</script>
+ * @see eg.InfiniteGrid
+ */
+ /**
+ * infiniteGrid:layoutComplete jQuery event plugin
+ *
+ * @ko infiniteGrid:layoutComplete jQuery event plugin
+ * @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({
+        itemSelector : ".item"
+    });
+ 	// event
+ 	$("#grid").on("infiniteGrid:layoutComplete",callback);
+ 	$("#grid").off("infiniteGrid:layoutComplete",callback);
+ 	$("#grid").trigger("infiniteGrid:layoutComplete",callback);
+ 	</script>
+ * @see eg.InfiniteGrid#event:layoutComplete
+ */
+/**
+ * infiniteGrid:append jQuery event plugin
+ *
+ * @ko infiniteGrid:append jQuery event plugin
+ * @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({
+        itemSelector : ".item"
+    });
+ 	// event
+ 	$("#grid").on("infiniteGrid:append",callback);
+ 	$("#grid").off("infiniteGrid:append",callback);
+ 	$("#grid").trigger("infiniteGrid:append",callback);
+ 	</script>
+ * @see eg.InfiniteGrid#event:append
+ */
+/**
+ * infiniteGrid:prepend jQuery event plugin
+ *
+ * @ko infiniteGrid:prepend jQuery event plugin
+ * @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({
+        itemSelector : ".item"
+    });
+ 	// 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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/jQuery.html b/doc/jQuery.html new file mode 100644 index 0000000..7ddfb17 --- /dev/null +++ b/doc/jQuery.html @@ -0,0 +1,3021 @@ + + + + + egjs - API + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

Namespace: jQuery

+ + + + +
+ +
+

+ jQuery +

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

Methods

+ +
+ +
+
+

+ + staticjQuery.flicking() +

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

Flicking in jQuery plugin

+
+ + +
+ Flicking in jQuery plugin +
+ + + + + + + + + + + + + + + + + + + +
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() +

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

InfiniteGrid in jQuery plugin

+
+ + +
+ InfiniteGrid in jQuery plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +
 <ul id="grid">
+    <li class="item">
+      <div>test1</div>
+    </li>
+    <li class="item">
+      <div>test3</div>
+    </li>
+  </ul>
+<script>
+// create
+$("#grid").infiniteGrid({
+    itemSelector : ".item"
+});
+ // method
+ $("#grid").infiniteGrid("option","itemSelector",".selected"); //Set option
+ $("#grid").infiniteGrid("instance"); // Return infiniteGrid instance
+ $("#grid").infiniteGrid("getBottomElement"); // Get bottom element
+ </script>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + staticjQuery.persist(state) +

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

Save current state

+
+ + +
+ 인자로 넘긴 현재 상태정보를 저장한다. +
+ + + + + + + + + +
    + +
  • + +
    + state + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    State object to be stored in order to restore UI component's state

    +

    UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체

    + +
    + + + +
  • + +
+ + + + + + + + + + + + + +
Example
+ + + +
$("a").on("click",function(e){
+    e.preventdefault();
+    // save state
+    $.persist(state);
+});
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + staticjQuery.persist(){Object} +

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

Return current state

+
+ + +
+ 인자로 넘긴 현재 상태정보를 반환한다. +
+ + + + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Object + + + + +
state Stored state object
+

복원을 위해 저장되어있는 상태 객체

+ + + +
+ + + + +
Example
+ + + +
$("a").on("click",function(e){
+    e.preventdefault();
+    // get state
+    var state = $.persist();
+});
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + staticjQuery.persist(key, state){Object} +

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

Save current state

+
+ + +
+ 인자로 넘긴 현재 상태정보를 저장한다. +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    State key to be stored in order to restore UI component's state

    +

    UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키

    + +
    + + + +
  • + +
  • + +
    + state + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    State object to be stored in order to restore UI component's state

    +

    UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Object + + + + +
state Stored state object
+

복원을 위해 저장되어있는 상태 객체

+ + + +
+ + + + +
Example
+ + + +
$("a").on("click",function(e){
+    e.preventdefault();
+    // save state
+    $.persist("KEY",state);
+});
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + staticjQuery.persist(key){Object} +

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

Return current state

+
+ + +
+ 인자로 넘긴 현재 상태정보를 반환한다. +
+ + + + + + + + + +
    + +
  • + +
    + key + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    State key to be stored in order to restore UI component's state

    +

    UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키

    + +
    + + + +
  • + +
+ + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + Object + + + + +
state Stored state object
+

복원을 위해 저장되어있는 상태 객체

+ + + +
+ + + + +
Example
+ + + +
$("a").on("click",function(e){
+    e.preventdefault();
+    // get state
+    var state = $.persist("KEY");
+});
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+ + staticjQuery.visible() +

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

visible:change jQuery event plugin

+
+ + +
+ visible:change jQuery 이벤트 plugin +
+ + + + + + + + + + + + + + + + + + + +
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) +

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

Extends jQuery animate in order to use 'transform' property

+
+ + +
+ jQuery animate 사용시 transform을 사용할 수 있도록 확장한 animate 메소드 +
+ + + + + + + + + +
    + +
  • + +
    + properties + + + + + + + + +
    + + +
    Type: +Object + +
    + + + +
    + +

    An object of CSS properties and values that the animation will move toward.

    +

    애니메이션 할 CSS 속성과 값으로 구성된 오브젝트

    + +
    + + + +
  • + +
  • + +
    + duration + + (default: 4000) + + + + + optional + + + + + +
    + + +
    Type: +Number +| + +String + +
    + + + +
    + +

    A string or number determining how long the animation will run.

    +

    애니메이션 진행 시간

    + +
    + + + +
  • + +
  • + +
    + easing + + (default: "swing") + + + + + optional + + + + + +
    + + +
    Type: +String + +
    + + + +
    + +

    A string indicating which easing function to use for the transition.

    +

    transition에 사용할 easing 함수명

    + +
    + + + +
  • + +
  • + +
    + complete + + + + + optional + + + + + +
    + + +
    Type: +function + +
    + + + +
    + +

    A function to call 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:
+
+ +
+ + + + + + +
+ +
+ +
+ + + + + +

Events

+ +
+ +
+
+

+ + rotate +

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

Add rotate event support in jQuery

+
+ + +
+ jQuery custom rotate 이벤트 지원 +
+ + + + + + + + + +
    + +
  • + +
    + e + + + +
    + + +
    Type: +Event + +
    + + + +
    + +

    event

    +

    event

    + +
    + + + + + +
      + +
    • + +
      + isVertical + + + +
      + + +
      Type: +Boolean + +
      + + + +
      + +

      vertical

      +

      수직여부

      + +
      + + + +
    • + +
    + +
  • + +
+ + + + + + + + + + + + + +
Example
+ + + +

$(window).on("rotate",function(e){ + e.isVertical; +});

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

+ + scrollEnd +

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

Add scrollEnd event support in jQuery

+
+ + +
+ jQuery custom scrollEnd 이벤트 지원 +
+ + + + + + + + + +
    + +
  • + +
    + e.top + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    top position

    +

    상단(top) 위치 값

    + +
    + + + +
  • + +
  • + +
    + e.left + + + +
    + + +
    Type: +Number + +
    + + + +
    + +

    left position

    +

    왼쪽(left) 위치 값

    + +
    + + + +
  • + +
+ + + + + + + + + + + + + +
Example
+ + + +

$(window).on("scrollend",function(e){ + e.top; + e.left; +});

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

+ + flicking:beforeFlickStart +

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

flicking:beforeFlickStart jQuery event plugin

+
+ + +
+ flicking:beforeFlickStart jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +

$("#mflick").on("flicking:beforeFlickStart",callback); + $("#mflick").off("flicking:beforeFlickStart",callback); + $("#mflick").trigger("flicking:beforeFlickStart",callback);

+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + flicking:beforeRestore +

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

flicking:beforeRestore jQuery event plugin

+
+ + +
+ flicking:beforeRestore jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +

$("#mflick").on("flicking:beforeRestore",callback); + $("#mflick").off("flicking:beforeRestore",callback); + $("#mflick").trigger("flicking:beforeRestore",callback);

+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + flicking:flick +

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

flicking:flick jQuery event plugin

+
+ + +
+ flicking:flick jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +

$("#mflick").on("flicking:flick",callback); + $("#mflick").off("flicking:flick",callback); + $("#mflick").trigger("flicking:flick",callback);

+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + flicking:flickEnd +

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

flicking:flickEnd jQuery event plugin

+
+ + +
+ flicking:flickEnd jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +

$("#mflick").on("flicking:flickEnd",callback); + $("#mflick").off("flicking:flickEnd",callback); + $("#mflick").trigger("flicking:flickEnd",callback);

+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + flicking:restore +

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

flicking:restore jQuery event plugin

+
+ + +
+ flicking:restore jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +

$("#mflick").on("flicking:restore",callback); + $("#mflick").off("flicking:restore",callback); + $("#mflick").trigger("flicking:restore",callback);

+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + infiniteGrid:append +

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

infiniteGrid:append jQuery event plugin

+
+ + +
+ infiniteGrid:append jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +
 <ul id="grid">
+    <li class="item">
+      <div>test1</div>
+    </li>
+    <li class="item">
+      <div>test3</div>
+    </li>
+  </ul>
+<script>
+// create
+$("#grid").infiniteGrid({
+    itemSelector : ".item"
+});
+ // event
+ $("#grid").on("infiniteGrid:append",callback);
+ $("#grid").off("infiniteGrid:append",callback);
+ $("#grid").trigger("infiniteGrid:append",callback);
+ </script>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + infiniteGrid:layoutComplete +

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

infiniteGrid:layoutComplete jQuery event plugin

+
+ + +
+ infiniteGrid:layoutComplete jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +
 <ul id="grid">
+    <li class="item">
+      <div>test1</div>
+    </li>
+    <li class="item">
+      <div>test3</div>
+    </li>
+  </ul>
+<script>
+// create
+$("#grid").infiniteGrid({
+    itemSelector : ".item"
+});
+ // event
+ $("#grid").on("infiniteGrid:layoutComplete",callback);
+ $("#grid").off("infiniteGrid:layoutComplete",callback);
+ $("#grid").trigger("infiniteGrid:layoutComplete",callback);
+ </script>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + infiniteGrid:prepend +

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

infiniteGrid:prepend jQuery event plugin

+
+ + +
+ infiniteGrid:prepend jQuery event plugin +
+ + + + + + + + + + + + + + + + + + + +
Example
+ + + +
 <ul id="grid">
+    <li class="item">
+      <div>test1</div>
+    </li>
+    <li class="item">
+      <div>test3</div>
+    </li>
+  </ul>
+<script>
+// create
+$("#grid").infiniteGrid({
+    itemSelector : ".item"
+});
+ // event
+ $("#grid").on("infiniteGrid:prepend",callback);
+ $("#grid").off("infiniteGrid:prepend",callback);
+ $("#grid").trigger("infiniteGrid:prepend",callback);
+ </script>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + + + + +
+ +
+ + + +
+
+

+ + visible:change +

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

Visible in jQuery plugin

+
+ + +
+ Visible in jQuery plugin +
+ + + + + + + + + + + + + + + + + + + +
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 Mon May 09 2016 14:54:17 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 0000000..740bb37 --- /dev/null +++ b/doc/module.js.html @@ -0,0 +1,806 @@ + + + + + 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/"
+		},
+		"Outlayer": {
+			"url": "https://github.com/metafizzy/outlayer/"
+		}
+	};
+
+	// 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._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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/movableCoord.js.html b/doc/movableCoord.js.html new file mode 100644 index 0000000..f23aac2 --- /dev/null +++ b/doc/movableCoord.js.html @@ -0,0 +1,1423 @@ + + + + + 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
+	// It is scheduled to be removed in case of build process.
+	// ns.__checkLibrary__( !("Hammer" in window), "You must download Hammerjs. (http://hammerjs.github.io/)\n\ne.g. bower install hammerjs");
+	// ns.__checkLibrary__( !("easeOutQuint" in $.easing), "You must download jQuery Easing Plugin(http://gsgd.co.uk/sandbox/jquery/easing/)\n\ne.g. bower install jquery.easing");
+	/**
+	 * Easily get computed coordinate values according user actions.
+	 * @group egjs
+	 * @ko MovableCoord는 사용자 행동에 의해, 좌표계를 제어할 수 있다.
+	 * @class
+	 * @name eg.MovableCoord
+	 * @extends eg.Component
+	 *
+	 * @param {Object} options
+	 * @param {Array} options.min The minimum coordinate  <ko>좌표계의 최소값</ko>
+	 * @param {Number} [options.min.0=0] The minimum x-coordinate <ko>최소 X좌표</ko>
+	 * @param {Number} [options.min.1=0] The minimum y-coordinate <ko>최소 Y좌표</ko>
+	 *
+	 * @param {Array} options.max The maximum coordinate <ko>좌표계의 최대값</ko>
+	 * @param {Number} [options.max.0=100] The maximum x-coordinate <ko>최대 X좌표</ko>
+	 * @param {Number} [options.max.1=100] The maximum y-coordinate <ko>최대 Y좌표</ko>
+	 *
+	 * @param {Array} options.bounce The area can move using animation. <ko>바운스: 애니메이션에 의해 이동할 수 있는 영역 </ko>
+	 * @param {Boolean} [options.bounce.0=10] The bounce top range <ko>top 바우스 영역</ko>
+	 * @param {Boolean} [options.bounce.1=10] The bounce right range <ko>right 바우스 영역</ko>
+	 * @param {Boolean} [options.bounce.2=10] The bounce bottom range <ko>bottom 바우스 영역</ko>
+	 * @param {Boolean} [options.bounce.3=10] The bounce left range <ko>left 바우스 영역</ko>
+	 *
+	 * @param {Array} options.margin The area can move using user's action. <ko>영역별 마진 영역: 사용자의 액션에 의해, 추가로 이동할수 있는 영역</ko>
+	 * @param {Boolean} [options.margin.0=0] The margin top range <ko>top 마진 영역</ko>
+	 * @param {Boolean} [options.margin.1=0] The margin right range <ko>right 마진 영역</ko>
+	 * @param {Boolean} [options.margin.2=0] The margin bottom range <ko>bottom 마진 영역</ko>
+	 * @param {Boolean} [options.margin.3=0] The margin left range <ko>left 마진 영역</ko>
+	 * @param {Array} options.circular <ko>영역별 순환 여부</ko>
+	 * @param {Boolean} [options.circular.0=false] The circular top range <ko>top 순환 영역</ko>
+	 * @param {Boolean} [options.circular.1=false] The circular right range <ko>right 순환 영역</ko>
+	 * @param {Boolean} [options.circular.2=false] The circular bottom range <ko>bottom 순환 영역</ko>
+	 * @param {Boolean} [options.circular.3=false] The circular left range <ko>left 순환 영역</ko>
+	 *
+	 * @param {Function} [options.easing=easing.easeOutCubic] Function of the Easing (jQuery UI Easing, jQuery Easing Plugin). <ko>Easing 함수</ko>
+	 * @param {Number} [options.maximumDuration=Infinity] The maximum duration. <ko>최대 좌표 이동 시간</ko>
+	 * @param {Number} [options.deceleration=0.0006] deceleration This value can be altered to change the momentum animation duration. higher numbers make the animation shorter. <ko>감속계수. 높을값이 주어질수록 애니메이션의 동작 시간이 짧아진다.</ko>
+	 * @see Hammerjs {@link http://hammerjs.github.io}
+	 * @see There is usability issue due to default CSS properties ({@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}) settings from Hammerjs. movableCoord removes that settings to fix.
+	 * <ko>Hammerjs의 기본 CSS 속성({@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html}) 으로 인해 사용성 이슈가 있다. 따라서, movableCoord는 hammerjs의 기본 CSS 속성을 제거하였다.</ko>
+	 *
+	 * @codepen {"id":"bdVybg", "ko":"MovableCoord 기본 예제", "en":"MovableCoord basic example", "collectionId":"AKpkGW", "height": 403}
+	 *
+	 * @see Easing Functions Cheat Sheet {@link http://easings.net/}
+	 * @see To use other easing functions, import jQuery easing plugin({@link http://gsgd.co.uk/sandbox/jquery/easing/}) or jQuery UI easing.({@link https://jqueryui.com/easing/})<ko>다른 easing 함수를 사용하고 싶다면, jQuery easing plugin({@link http://gsgd.co.uk/sandbox/jquery/easing/})이나, jQuery UI easing({@link https://jqueryui.com/easing/}) 라이브러리를 삽입해야 한다.</ko>
+	 *
+	 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
+	 */
+	var MC = ns.MovableCoord = ns.Class.extend(ns.Component, {
+		construct: function(options) {
+			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
+			};
+			this._reviseOptions(options);
+			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._panmove = $.proxy(this._panmove, this);	// for caching
+			this._panend = $.proxy(this._panend, this);	// for caching
+		},
+		/**
+		 * Bind element
+		 * @ko movableCoord을 사용하기 위한 엘리먼트를 등록한다.
+		 * @method eg.MovableCoord#bind
+		 * @param {HTMLElement|String|jQuery} element  A target element. <ko>movableCoord을 사용하기 위한 엘리먼트</ko>
+		 * @param {Object} options
+		 * @param {Number} [options.direction=eg.MovableCoord.DIRECTION_ALL] The controllable directions. <ko>움직일수 있는 방향</ko>
+		 * @param {Array} options.scale The moving scale. <ko>이동 배율</ko>
+		 * @param {Number} [options.scale.0=1] x-scale <ko>x축 배율</ko>
+		 * @param {Number} [options.scale.1=1] y-scale <ko>y축 배율</ko>
+		 * @param {Number} [options.thresholdAngle=45] The threshold angle about direction which range is 0~90 <ko>방향에 대한 임계각 (0~90)</ko>
+		 * @param {Number} [options.interruptable=true] interruptable This value can be enabled to interrupt cycle of the animation event. <ko>이 값이  true이면, 애니메이션의 이벤트 사이클을 중단할수 있다.</ko>
+		 * @param {Array} [options.inputType] inputType you can control input type. a kind of inputs are "touch", "mouse".  default value is ["touch", "mouse"] <ko>입력 타입을 지정할수 있다. 입력타입은 "touch", "mouse" 가 있으며, 배열로 입력할 수 있다. (기본값은 ["touch", "mouse"] 이다)</ko>
+		 *
+		 * @return {eg.MovableCoord} instance of 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].get("pan").set({
+					direction: subOptions.direction
+				});
+			} else {
+				keyValue = Math.round(Math.random() * new Date().getTime());
+				this._hammers[keyValue] = this._createHammer(
+					$el.get(0),
+					subOptions,
+					inputClass
+				);
+				$el.data(MC._KEY, keyValue);
+			}
+			return this;
+		},
+
+		_createHammer: function(el, subOptions, inputClass) {
+			try {
+				// create Hammer
+				var hammer = new HM.Manager(el, {
+						recognizers: [
+							[
+								HM.Tap, {
+
+									// for long tap
+									time: 30000
+								}
+							],
+							[
+								HM.Pan, {
+									direction: subOptions.direction,
+									threshold: 0
+								}, ["tap"]
+							]
+						],
+
+						// 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 hammer.on("hammer.input", $.proxy(function(e) {
+					if (e.isFirst) {
+						// apply options each
+						this._subOptions = subOptions;
+						this._status.curHammer = hammer;
+						this._panstart(e);
+					}
+				}, this))
+				.on("panstart panmove", this._panmove)
+				.on("panend tap", this._panend);
+			} catch (e) {}
+		},
+
+		_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;
+		},
+
+		/**
+		 * Unbind element
+		 * @ko movableCoord을 사용하기 위한 엘리먼트를 해제한다.
+		 * @method eg.MovableCoord#unbind
+		 * @param {HTMLElement|String|jQuery} element The target element.<ko>movableCoord을 사용하기 위한 설정한 엘리먼트</ko>
+		 * @return {eg.MovableCoord} instance of itself<ko>자신의 인스턴스</ko>
+		 */
+		unbind: function(el) {
+			var $el = $(el);
+			var key = $el.data(MC._KEY);
+			if (key) {
+				this._hammers[key].destroy();
+				delete this._hammers[key];
+				$el.data(MC._KEY, null);
+			}
+			return this;
+		},
+
+		_grab: function() {
+			if (this._status.animationParam) {
+				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, min, 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();
+			/**
+			 * When an area was pressed
+			 * @ko 스크린에서 사용자가 손을 대었을 때
+			 * @name eg.MovableCoord#hold
+			 * @event
+			 * @param {Object} param
+			 * @param {Array} param.pos coordinate <ko>좌표 정보</ko>
+			 * @param {Number} param.pos.0 x-coordinate <ko>x 좌표</ko>
+			 * @param {Number} param.pos.1 y-coordinate <ko>y 좌표</ko>
+			 * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event <ko>사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, 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.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);
+
+				// console.log(e.velocityX, e.velocityY, e.deltaX, e.deltaY);
+				!(direction & MC.DIRECTION_HORIZONTAL) && (vX = 0);
+				!(direction & MC.DIRECTION_VERTICAL) && (vY = 0);
+
+				this._animateBy(
+					this._getNextOffsetPos([
+						vX * (e.deltaX < 0 ? -1 : 1) * scale[0],
+						vY * (e.deltaY < 0 ? -1 : 1) * scale[1]
+					]),
+				this._animationEnd, false, null, e);
+			}
+			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;
+		},
+
+		_animationEnd: function() {
+			/**
+			 * When animation was ended.
+			 * @ko 에니메이션이 끝났을 때 발생한다.
+			 * @name eg.MovableCoord#animationEnd
+			 * @event
+			 */
+			var pos = this._pos;
+			var min = this.options.min;
+			var max = this.options.max;
+			this._animateTo([
+				Math.min(max[0], Math.max(min[0], pos[0])),
+				Math.min(max[1], Math.max(min[1], pos[1]))
+			], $.proxy(this.trigger, this, "animationEnd"), true, null);
+		},
+
+		_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;
+		},
+
+		_animateBy: function(offset, callback, isBounce, duration, e) {
+			var pos = this._pos;
+			return this._animateTo([
+				pos[0] + offset[0],
+				pos[1] + offset[1]
+			], callback, isBounce, duration, e);
+		},
+
+		_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 destPos;
+
+		},
+
+		_isCircular: function(circular, destPos, min, 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]);
+		},
+
+		_animateTo: function(absPos, callback, isBounce, duration, e) {
+			var pos = this._pos;
+			var destPos = this._getPointOfIntersection(pos, absPos);
+			var param = {
+					depaPos: pos.concat(),
+					destPos: destPos,
+					hammerEvent: e || null
+				};
+			if (!isBounce && e) {	// check whether user's action
+				/**
+				 * When an area was released
+				 * @ko 스크린에서 사용자가 손을 떼었을 때
+				 * @name eg.MovableCoord#release
+				 * @event
+				 *
+				 * @param {Object} param
+				 * @param {Array} param.depaPos departure coordinate <ko>현재 좌표</ko>
+				 * @param {Number} param.depaPos.0 departure x-coordinate <ko>현재 x 좌표</ko>
+				 * @param {Number} param.depaPos.1 departure y-coordinate <ko>현재 y 좌표</ko>
+				 * @param {Array} param.destPos destination coordinate <ko>애니메이션에 의해 이동할 좌표</ko>
+				 * @param {Number} param.destPos.0 destination x-coordinate <ko>x 좌표</ko>
+				 * @param {Number} param.destPos.1 destination y-coordinate <ko>y 좌표</ko>
+				 * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event <ko>사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환)</ko>
+				 *
+				 */
+				this.trigger("release", param);
+			}
+			this._afterReleaseProcess(param, callback, isBounce, duration);
+		},
+
+		// when user release a finger, pointer or mouse
+		_afterReleaseProcess: function(param, callback, isBounce, duration) {
+			// caution: update option values, due to value was changed by "release" event
+			var pos = this._pos;
+			var min = this.options.min;
+			var max = this.options.max;
+			var circular = this.options.circular;
+			var isCircular = this._isCircular(
+								circular,
+								param.destPos,
+								min,
+								max
+							);
+			var destPos = this._isOutToOut(pos, param.destPos, min, max) ?
+				pos : param.destPos;
+			var distance = [
+				Math.abs(destPos[0] - pos[0]),
+				Math.abs(destPos[1] - pos[1])
+			];
+			var animationParam;
+			duration = duration === null ?
+						this._getDurationFromPos(distance) : duration;
+			duration = this.options.maximumDuration > duration ?
+						duration : this.options.maximumDuration;
+
+			var done = $.proxy(function(isNext) {
+					this._status.animationParam = null;
+					pos[0] = Math.round(destPos[0]);
+					pos[1] = Math.round(destPos[1]);
+					pos = this._getCircularPos(pos, min, max, circular);
+					!isNext && this._setInterrupt(false);
+					callback();
+				}, this);
+
+			if (distance[0] === 0 && distance[1] === 0) {
+				return done(!isBounce);
+			}
+
+			// prepare animation parameters
+			animationParam = {
+				duration: duration,
+				depaPos: pos.concat(),
+				destPos: destPos,
+				isBounce: isBounce,
+				isCircular: isCircular,
+				done: done,
+				hammerEvent: param.hammerEvent
+			};
+
+			/**
+			 * When animation was started.
+			 * @ko 에니메이션이 시작했을 때 발생한다.
+			 * @name eg.MovableCoord#animationStart
+			 * @event
+			 * @param {Object} param
+			 * @param {Number} param.duration
+			 * @param {Array} param.depaPos departure coordinate <ko>현재 좌표</ko>
+			 * @param {Number} param.depaPos.0 departure x-coordinate <ko>현재 x 좌표</ko>
+			 * @param {Number} param.depaPos.1 departure y-coordinate <ko>현재 y 좌표</ko>
+			 * @param {Array} param.destPos destination coordinate <ko>애니메이션에 의해 이동할 좌표</ko>
+			 * @param {Number} param.destPos.0 destination x-coordinate <ko>x 좌표</ko>
+			 * @param {Number} param.destPos.1 destination y-coordinate <ko>y 좌표</ko>
+			 * @param {Boolean} param.isBounce When an animation is bounced, a value is 'true'.  <ko>바운스 되는 애니메이션인 경우 true</ko>
+			 * @param {Boolean} param.isCircular When the area is circular type, a value is 'true'. <ko>순환하여 움직여야하는 애니메이션인경우 true</ko>
+			 * @param {Function} param.done If user control animation, user must call this function. <ko>애니메이션이 끝났다는 것을 알려주는 함수</ko>
+			 * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event <ko>사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환)</ko>
+			 *
+			 */
+			var retTrigger = this.trigger("animationStart", animationParam);
+
+			// You can't stop the 'animationStart' event when 'circular' is true.
+			if (isCircular && !retTrigger) {
+				throw new Error(
+					"You can't stop the 'animation' event when 'circular' is true."
+				);
+			}
+			animationParam.depaPos = pos;
+			animationParam.startTime = new Date().getTime();
+			this._status.animationParam = animationParam;
+			if (retTrigger) {
+				if (animationParam.duration) {
+					// console.error("depaPos", pos, "depaPos",destPos, "duration", duration, "ms");
+					var info = this._status.animationParam;
+					var self = this;
+					(function loop() {
+						self._raf = null;
+						if (self._frame(info) >= 1) {
+							return done(true);
+						} // animationEnd
+						self._raf = ns.requestAnimationFrame(loop);
+					})();
+				} else {
+					this._triggerChange(animationParam.destPos, false);
+					done(!isBounce);
+				}
+			}
+		},
+
+		// 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(options) {
+			var key;
+			$.each(["bounce", "margin", "circular"], function(i, v) {
+				key = options[v];
+				if (key != null) {
+					if ($.isArray(key)) {
+						options[v] = key.length === 2 ?
+							key.concat(key) : key.concat();
+					} else if (/string|number|boolean/.test(typeof key)) {
+						options[v] = [ key, key, key, key ];
+					} else {
+						options[v] = null;
+					}
+				}
+			});
+			$.extend(this.options, options);
+		},
+
+		// trigger 'change' event
+		_triggerChange: function(pos, holding, e) {
+			/**
+			 * When coordinate was changed
+			 * @ko 좌표가 변경됐을 때 발생한다.
+			 * @name eg.MovableCoord#change
+			 * @event
+			 *
+			 * @param {Object} param
+			 * @param {Array} param.pos departure coordinate  <ko>좌표</ko>
+			 * @param {Number} param.pos.0 departure x-coordinate <ko>x 좌표</ko>
+			 * @param {Number} param.pos.1 departure y-coordinate <ko>y 좌표</ko>
+			 * @param {Boolean} param.holding If an area was pressed, this value is 'true'. <ko>스크린을 사용자가 누르고 있을 경우 true </ko>
+			 * @param {Object} param.hammerEvent Hammerjs event. if you use api, this value is null. http://hammerjs.github.io/api/#hammer.input-event <ko>사용자의 액션에 대한 hammerjs 이벤트 정보 (API에 의해 호출될 경우, null 을 반환)</ko>
+			 *
+			 */
+			this._pos = pos.concat();
+			this.trigger("change", {
+				pos: pos.concat(),
+				holding: holding,
+				hammerEvent: e || null
+			});
+		},
+
+		/**
+		 * Get current position
+		 * @ko 현재 위치를 반환한다.
+		 * @method eg.MovableCoord#get
+		 * @return {Array} pos
+		 * @return {Number} pos.0 x position
+		 * @return {Number} pos.1 y position
+		 */
+		get: function() {
+			return this._pos.concat();
+		},
+
+		/**
+		 * Set to absolute position
+		 *
+		 * When duration is greater than zero, 'change' event is triggered
+		 * @ko 위치를 설정한다. 만약, duration이 0보다 크다면 'change' 이벤트가 발생한다.
+		 * @method eg.MovableCoord#setTo
+		 * @param {Number} x x-coordinate <ko>이동할 x좌표</ko>
+		 * @param {Number} y y-coordinate <ko>이동할 y좌표</ko>
+		 * @param {Number} [duration=0] Duration of animation in milliseconds. <ko>애니메이션 진행시간(ms)</ko>
+		 * @return {eg.MovableCoord} instance of 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 ], this._animationEnd, false, duration);
+			} else {
+				this._pos = this._getCircularPos([ x, y ]);
+				this._triggerChange(this._pos, false);
+				this._setInterrupt(false);
+			}
+			return this;
+		},
+		/**
+		 * Set to relative position
+		 *
+		 * When duration is greater than zero, 'change' event is triggered
+		 * @ko 현재를 기준으로 위치를 설정한다. 만약, duration이 0보다 크다면 'change' 이벤트가 발생한다.
+		 * @method eg.MovableCoord#setBy
+		 * @param {Number} x x-coordinate <ko>이동할 x좌표</ko>
+		 * @param {Number} y y-coordinate <ko>이동할 y좌표</ko>
+		 * @param {Number} [duration=0] Duration of animation in milliseconds. <ko>애니메이션 진행시간(ms)</ko>
+		 * @return {eg.MovableCoord} instance of 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);
+		},
+
+		/**
+		 * Release resources and unbind custom events
+		 * @ko 모든 커스텀 이벤트와 자원을 해제한다.
+		 * @method eg.MovableCoord#destroy
+		 */
+		destroy: function() {
+			this.off();
+			for (var p in this._hammers) {
+				this._hammers[p].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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/persist.js.html b/doc/persist.js.html new file mode 100644 index 0000000..b4ffa40 --- /dev/null +++ b/doc/persist.js.html @@ -0,0 +1,802 @@ + + + + + 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", eg, window, document], function($, ns, global, doc) {
+	"use strict";
+
+	// jscs:enable maximumLineLength
+	var wp = global.performance;
+	var history = global.history;
+	var location = global.location;
+	var userAgent = global.navigator.userAgent;
+	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 (!isSupportState) {
+			if ("sessionStorage" in global) {
+				var tmpKey = "__tmp__" + CONST_PERSIST;
+				sessionStorage.setItem(tmpKey, CONST_PERSIST);
+				return sessionStorage.getItem(tmpKey) === CONST_PERSIST ?
+						sessionStorage :
+						localStorage;
+			} else {
+				return global.localStorage;
+			}
+		}
+	})();
+
+	// jscs:disable maximumLineLength
+	/* jshint ignore:start */
+	if (!isSupportState && !storage ||
+		(!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 stateStr;
+		var state = {};
+		var isValidStateStr = false;
+
+		if (isSupportState) {
+			stateStr = history.state;
+
+			// "null" is not a valid
+			isValidStateStr = typeof stateStr === "string" && stateStr !== "null";
+		} else {
+			stateStr = storage.getItem(location.href + CONST_PERSIST);
+			isValidStateStr = stateStr && stateStr.length > 0;
+		}
+
+		if (isValidStateStr) {
+			try {
+				state = JSON.parse(stateStr);
+
+				// like '[ ... ]', '1', '1.234', '"123"' is also not valid
+				if (jQuery.type(state) !== "object" || state instanceof Array) {
+					throw new Error();
+				}
+			} catch (e) {
+				/* jshint ignore:start */
+				console.warn("window.history or session/localStorage has no valid " +
+						"format data to be handled in persist.");
+				/* jshint ignore:end */
+			}
+		}
+
+		// Note2 (Android 4.3) return value is null
+		return state;
+	}
+
+	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 (isSupportState) {
+			try {
+				history.replaceState(
+					state === null ? null : JSON.stringify(state),
+					doc.title,
+					location.href
+				);
+			} catch (e) {
+				/* jshint ignore:start */
+				console.warn(e.message);
+				/* jshint ignore:end */
+			}
+		} else {
+			if (state) {
+				storage.setItem(location.href + CONST_PERSIST, JSON.stringify(state));
+			} else {
+				storage.removeItem(location.href  + CONST_PERSIST);
+			}
+		}
+		state ? $global.attr(CONST_PERSIST, true) : $global.attr(CONST_PERSIST, null);
+	}
+
+	function setStateByKey(key, data) {
+		var beforeData = getState();
+		beforeData[key] = data;
+		setState(beforeData);
+	}
+
+	/**
+	* Save current state
+	* @ko 인자로 넘긴 현재 상태정보를 저장한다.
+	* @method jQuery.persist
+	* @support {"ie": "9+", "ch" : "latest", "ff" : "1.5+",  "sf" : "latest", "ios" : "7+", "an" : "2.2+ (except 3.x)"}
+	* @param {Object} state State object to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체</ko>
+	* @example
+	$("a").on("click",function(e){
+		e.preventdefault();
+		// save state
+		$.persist(state);
+	});
+	*/
+	/**
+	* Return current state
+	* @ko 인자로 넘긴 현재 상태정보를 반환한다.
+	* @method jQuery.persist
+	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
+	* @example
+	$("a").on("click",function(e){
+		e.preventdefault();
+		// get state
+		var state = $.persist();
+	});
+	*/
+	/**
+	* Save current state
+	* @ko 인자로 넘긴 현재 상태정보를 저장한다.
+	* @method jQuery.persist
+    * @param {String} key State key to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키</ko>
+    * @param {String} state State object to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체</ko>
+	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
+	* @example
+	$("a").on("click",function(e){
+		e.preventdefault();
+		// save state
+		$.persist("KEY",state);
+	});
+	*/
+	/**
+	* Return current state
+	* @ko 인자로 넘긴 현재 상태정보를 반환한다.
+	* @method jQuery.persist
+	* @param {String} key State key to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키</ko>
+	* @return {Object} state Stored state object <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 persist needs by checking bfCache support
+	* @ko Persist 동작 필요여부를 반환한다.
+	* @method $.persist.isApplicable
+	* @example
+	$.persist.isApplicable();
+	*/
+	$.persist.isNeeded = function() {
+		var agentOs = ns.agent(userAgent).os;
+		var isNeeded = true;
+		if (agentOs.name === "ios" ||
+				(agentOs.name === "android" && parseFloat(agentOs.version) < 4.4)) {
+			isNeeded = false;
+		}
+		$.persist.isNeeded = function() {
+			return isNeeded;
+		};
+		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,
+		"persist": $.persist,
+		"isNeeded": $.persist.isNeeded,
+		"GLOBALKEY": GLOBAL_KEY
+	};
+});
+
+
+ + + + + + + + +
+ + comments powered by Disqus + + + +
+ Documentation generated by JSDoc 3.2.2 on Mon May 09 2016 14:54:16 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/rotate.js.html b/doc/rotate.js.html new file mode 100644 index 0000000..f46d3a3 --- /dev/null +++ b/doc/rotate.js.html @@ -0,0 +1,724 @@ + + + + + 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
+	 */
+	/**
+	 * Add rotate event support in jQuery
+	 *
+	 * @ko jQuery custom rotate 이벤트 지원
+	 * @name jQuery#rotate
+	 * @event
+	 * @param {Event} e event
+	 * @param {Boolean} e.isVertical vertical <ko>수직여부</ko>
+	 * @support { "ios" : "7+", "an" : "2.1+ (except 3.x)"}
+	 * @example
+	 * $(window).on("rotate",function(e){
+	 *      e.isVertical;
+	 * });
+	 *
+	 */
+
+	var beforeScreenWidth = -1;
+	var beforeVertical = null;
+	var rotateTimer = null;
+	var agent = ns.agent();
+	var isMobile = /android|ios/.test(agent.os.name);
+
+	/**
+	 * 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;
+				}
+			}
+
+			beforeScreenWidth = screenWidth;
+		} 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;
+				$(global).trigger("rotate");
+			}
+		}
+	}
+
+	/**
+	* 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;
+				}
+				beforeScreenWidth = screenWidth;
+			}
+
+			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;
+		}
+	};
+
+	/**
+	 * Check if device is in portrait mode
+	 * @ko 해당 기기가 portait(수직방향) 모드일 경우, true을 반환한다.
+	 * @method eg#isPortrait
+	 * @return {Boolean}
+	 * @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 Mon May 09 2016 14:54:17 GMT+0900 (KST) +
+
+
+ + + + + diff --git a/doc/scripts/bootstrap.min.js b/doc/scripts/bootstrap.min.js new file mode 100644 index 0000000..1a6258e --- /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 0000000..9a85bd3 --- /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("