'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
(function () {
'use strict';
// root of function
var root = this,
win = this,
doc = win ? win.document : null,
docElem = win ? win.document.documentElement : null,
reIsJson = /^(["'](\\.|[^"\\\n\r])*?["']|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/,
reMs = /^-ms-/,
reSnakeCase = /[\-_]([\da-z])/gi,
reCamelCase = /([A-Z])/g,
reDot = /\./,
reInt = /[-|+]?[\D]/gi,
reNotNum = /\D/gi,
reMoneySplit = new RegExp('([0-9])([0-9][0-9][0-9][,.])'),
reAmp = /&/g,
reEq = /=/,
reClassNameSplit = /[ ]+/g,
/** @namespace {Object} ax5 */
ax5 = {},
info = void 0,
U = void 0,
dom = void 0;
/**
* guid
* @member {Number} ax5.guid
*/
ax5.guid = 1;
/**
* ax5.guid를 구하고 증가시킵니다.
* @method ax5.getGuid
* @returns {Number} guid
*/
ax5.getGuid = function () {
return ax5.guid++;
};
/**
* 상수모음
* @namespace ax5.info
*/
ax5.info = info = function () {
var _arguments = arguments;
/**
* ax5 version
* @member {String} ax5.info.version
*/
var version = "1.4.126";
/**
* ax5 library path
* @member {String} ax5.info.baseUrl
*/
var baseUrl = "";
/**
* ax5 에러 출력메세지 사용자 재 정의
* @member {Object} ax5.info.onerror
* @examples
* ```
* ax5.info.onerror = function(){
* console.log(arguments);
* }
* ```
*/
var onerror = function onerror() {
console.error(U.toArray(_arguments).join(":"));
};
/**
* event keyCodes
* @member {Object} ax5.info.eventKeys
* @example
* ```
* {
* BACKSPACE: 8, TAB: 9,
* RETURN: 13, ESC: 27, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, DELETE: 46,
* HOME: 36, END: 35, PAGEUP: 33, PAGEDOWN: 34, INSERT: 45, SPACE: 32
* }
* ```
*/
var eventKeys = {
BACKSPACE: 8, TAB: 9,
RETURN: 13, ESC: 27, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, DELETE: 46,
HOME: 36, END: 35, PAGEUP: 33, PAGEDOWN: 34, INSERT: 45, SPACE: 32
};
/**
* week names
* @member {Object[]} weekNames
* @member {string} weekNames[].label
*
* @example
* ```
* [
* {label: "SUN"},{label: "MON"},{label: "TUE"},{label: "WED"},{label: "THU"},{label: "FRI"},{label: "SAT"}
* ]
* console.log( weekNames[0] );
* console.log( ax5.info.weekNames[(new Date()).getDay()].label )
* ```
*/
var weekNames = [{ label: "SUN" }, { label: "MON" }, { label: "TUE" }, { label: "WED" }, { label: "THU" }, { label: "FRI" }, { label: "SAT" }];
/**
* 사용자 브라우저 식별용 오브젝트
* @member {Object} ax5.info.browser
* @example
* ```
* console.log( ax5.info.browser );
* //Object {name: "chrome", version: "39.0.2171.71", mobile: false}
* ```
*/
var browser = function (ua, mobile, browserName, match, browser, browserVersion) {
if (!win || !win.navigator) return {};
ua = navigator.userAgent.toLowerCase(), mobile = ua.search(/mobile/g) != -1, browserName, match, browser, browserVersion;
if (ua.search(/iphone/g) != -1) {
return { name: "iphone", version: 0, mobile: true };
} else if (ua.search(/ipad/g) != -1) {
return { name: "ipad", version: 0, mobile: true };
} else if (ua.search(/android/g) != -1) {
match = /(android)[ \/]([\w.]+)/.exec(ua) || [];
browserVersion = match[2] || "0";
return { name: "android", version: browserVersion, mobile: mobile };
} else {
browserName = "";
match = /(opr)[ \/]([\w.]+)/.exec(ua) || /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
browser = match[1] || "";
browserVersion = match[2] || "0";
if (browser == "msie") browser = "ie";
return {
name: browser,
version: browserVersion,
mobile: mobile
};
}
ua = null, mobile = null, browserName = null, match = null, browser = null, browserVersion = null;
}();
/**
* 브라우저 여부
* @member {Boolean} ax5.info.isBrowser
*/
var isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && win.document);
/**
* 브라우저에 따른 마우스 휠 이벤트이름
* @member {Object} ax5.info.wheelEnm
*/
var wheelEnm = win && /Firefox/i.test(navigator.userAgent) ? "DOMMouseScroll" : "mousewheel";
/**
* 첫번째 자리수 동사 - (필요한것이 없을때 : 4, 실행오류 : 5)
* 두번째 자리수 목적어 - 문자열 0, 숫자 1, 배열 2, 오브젝트 3, 함수 4, DOM 5, 파일 6, 기타 7
* 세번째 자리수 옵션
* @member {Object} ax5.info.errorMsg
*/
var errorMsg = {};
/**
* 현재 페이지의 Url 정보를 리턴합니다.
* @method ax5.info.urlUtil
* @returns {Object}
* @example
* ```
* console.log( ax5.util.toJson( ax5.info.urlUtil() ) );
* {
* "baseUrl": "http://ax5:2018",
* "href": "http://ax5:2018/samples/index.html?a=1&b=1#abc",
* "param": "a=1&b=1",
* "referrer": "",
* "pathname": "/samples/index.html",
* "hostname": "ax5",
* "port": "2018",
* "url": "http://ax5:2018/samples/index.html",
* "hashdata": "abc"
* }
* ```
*/
function urlUtil(url, urls) {
url = {
href: win.location.href,
param: win.location.search,
referrer: doc.referrer,
pathname: win.location.pathname,
hostname: win.location.hostname,
port: win.location.port
}, urls = url.href.split(/[\?#]/);
url.param = url.param.replace("?", "");
url.url = urls[0];
if (url.href.search("#") > -1) {
url.hashdata = U.last(urls);
}
urls = null;
url.baseUrl = U.left(url.href, "?").replace(url.pathname, "");
return url;
}
/**
* ax5-error-msg.js 에 정의된 ax5 error를 반환합니다.
* @method ax5.info.getError
* @returns {Object}
* @example
* ```
* console.log( ax5.info.getError("single-uploader", "460", "upload") );
*
* if(!this.selectedFile){
* if (cfg.onEvent) {
* var that = {
* action: "error",
* error: ax5.info.getError("single-uploader", "460", "upload")
* };
* cfg.onEvent.call(that, that);
* }
* return this;
* }
* ```
*/
function getError(className, errorCode, methodName) {
if (info.errorMsg && info.errorMsg[className]) {
return {
className: className,
errorCode: errorCode,
methodName: methodName,
msg: info.errorMsg[className][errorCode]
};
} else {
return { className: className, errorCode: errorCode, methodName: methodName };
}
}
/**
* 브라우져의 터치 기능 유무를 확인합니다.
* @method ax5.info.supportTouch
* @returns {boolean}
* @example
* ```
* var chkFlag = ax5.info.supportTouch;
*/
var supportTouch = win ? 'ontouchstart' in win || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 : false;
var supportFileApi = win ? win.FileReader && win.File && win.FileList && win.Blob : false;
return {
errorMsg: errorMsg,
version: version,
baseUrl: baseUrl,
onerror: onerror,
eventKeys: eventKeys,
weekNames: weekNames,
browser: browser,
isBrowser: isBrowser,
supportTouch: supportTouch,
supportFileApi: supportFileApi,
wheelEnm: wheelEnm,
urlUtil: urlUtil,
getError: getError
};
}();
/**
* Refer to this by {@link ax5}.
* @namespace ax5.util
*/
ax5['util'] = U = function () {
var _toString = Object.prototype.toString;
/**
* Object나 Array의 아이템으로 사용자 함수를 호출합니다.
* @method ax5.util.each
* @param {Object|Array} O
* @param {Function} _fn
* @example
* ```js
* var axf = ax5.util;
* axf.each([0,1,2], function(){
* // with this
* });
* axf.each({a:1, b:2}, function(){
* // with this
* });
* ```
*/
function each(O, _fn) {
if (isNothing(O)) return [];
var key = void 0,
i = 0,
l = O.length,
isObj = l === undefined || typeof O === "function";
if (isObj) {
for (key in O) {
if (typeof O[key] != "undefined") if (_fn.call(O[key], key, O[key]) === false) break;
}
} else {
for (; i < l;) {
if (typeof O[i] != "undefined") if (_fn.call(O[i], i, O[i++]) === false) break;
}
}
return O;
}
// In addition to using the http://underscorejs.org : map, reduce, reduceRight, find
/**
* 원본 아이템들을 이용하여 사용자 함수의 리턴값으로 이루어진 새로운 배열을 만듭니다.
* @method ax5.util.map
* @param {Object|Array} O
* @param {Function} _fn
* @returns {Array}
* @example
* ```js
* var myArray = [0,1,2,3,4];
* var myObject = {a:1, b:"2", c:{axj:"what", arrs:[0,2,"3"]},
* fn: function(abcdd){
* return abcdd;
* }
* };
*
* var _arr = ax5.util.map( myArray, function(index, I){
* return index+1;
* });
* console.log(_arr);
* // [1, 2, 3, 4, 5]
*
* var _arr = ax5.util.map( myObject, function(k, v){
* return v * 2;
* });
* console.log(_arr);
* // [2, 4, NaN, NaN]
* ```
*/
function map(O, _fn) {
if (isNothing(O)) return [];
var key = void 0,
i = 0,
l = O.length,
results = [],
fnResult = void 0;
if (isObject(O)) {
for (key in O) {
if (typeof O[key] != "undefined") {
fnResult = undefined;
if ((fnResult = _fn.call(O[key], key, O[key])) === false) break;else results.push(fnResult);
}
}
} else {
for (; i < l;) {
if (typeof O[i] != "undefined") {
fnResult = undefined;
if ((fnResult = _fn.call(O[i], i, O[i++])) === false) break;else results.push(fnResult);
}
}
}
return results;
}
/**
* 원본 아이템들을 이용하여 사용자 함수의 리턴값이 참인 아이템의 위치나 키값을 반환합니다.
* @method ax5.util.search
* @param {Object|Array} O
* @param {Function|String|Number} _fn - 함수 또는 값
* @returns {Number|String}
* @example
* ```js
* var myArray = [0,1,2,3,4,5,6];
* var myObject = {a:"123","b":"123",c:123};
*
* ax5.util.search(myArray, function(){
* return this > 3;
* });
* // 4
* ax5.util.search(myObject, function(k, v){
* return v === 123;
* });
* // "c"
* ax5.util.search([1,2,3,4], 3);
* // 2
* ax5.util.search([1,2], 4);
* // -1
* ax5.util.search(["name","value"], "value");
* // 1
* ax5.util.search(["name","value"], "values");
* // -1
* ax5.util.search({k1:"name",k2:"value"}, "value2");
* // -1
* ax5.util.search({k1:"name",k2:"value"}, "value");
* // "k2"
* ```
*/
function search(O, _fn) {
if (isNothing(O)) return -1;
if (isObject(O)) {
for (var key in O) {
if (typeof O[key] != "undefined" && isFunction(_fn) && _fn.call(O[key], key, O[key])) {
return key;
break;
} else if (O[key] == _fn) {
return key;
break;
}
}
} else {
for (var i = 0, l = O.length; i < l; i++) {
if (typeof O[i] != "undefined" && isFunction(_fn) && _fn.call(O[i], i, O[i])) {
return i;
break;
} else if (O[i] == _fn) {
return i;
break;
}
}
}
return -1;
}
/**
* @method ax5.util.sum
* @param {Array|Object} O
* @param {Number} [defaultValue]
* @param {Function} _fn
* @returns {Number}
* @example
* ```js
* var arr = [
* {name: "122", value: 9},
* {name: "122", value: 10},
* {name: "123", value: 11}
* ];
*
* var rs = ax5.util.sum(arr, function () {
* if(this.name == "122") {
* return this.value;
* }
* });
* console.log(rs); // 19
*
* console.log(ax5.util.sum(arr, 10, function () {
* return this.value;
* }));
* // 40
* ```
*/
function sum(O, defaultValue, _fn) {
var i = void 0,
l = void 0,
tokenValue = void 0;
if (isFunction(defaultValue) && typeof _fn === "undefined") {
_fn = defaultValue;
defaultValue = 0;
}
if (typeof defaultValue === "undefined") defaultValue = 0;
if (isArray(O)) {
i = 0;
l = O.length;
for (; i < l; i++) {
if (typeof O[i] !== "undefined") {
if ((tokenValue = _fn.call(O[i], O[i])) === false) break;else if (typeof tokenValue !== "undefined") defaultValue += tokenValue;
}
}
return defaultValue;
} else if (isObject(O)) {
for (i in O) {
if (typeof O[i] != "undefined") {
if ((tokenValue = _fn.call(O[i], O[i])) === false) break;else if (typeof tokenValue !== "undefined") defaultValue += tokenValue;
}
}
return defaultValue;
} else {
console.error("argument error : ax5.util.sum - use Array or Object");
return defaultValue;
}
}
/**
* @method ax5.util.avg
* @param {Array|Object} O
* @param {Number} [defaultValue]
* @param {Function} _fn
* @returns {Number}
* @example
* ```js
* var arr = [
* {name: "122", value: 9},
* {name: "122", value: 10},
* {name: "123", value: 11}
* ];
*
* var rs = ax5.util.avg(arr, function () {
* return this.value;
* });
*
* console.log(rs); // 10
* ```
*/
function avg(O, defaultValue, _fn) {
var i = void 0,
l = void 0,
tokenValue = void 0;
if (isFunction(defaultValue) && typeof _fn === "undefined") {
_fn = defaultValue;
defaultValue = 0;
}
if (typeof defaultValue === "undefined") defaultValue = 0;
if (isArray(O)) {
i = 0;
l = O.length;
for (; i < l; i++) {
if (typeof O[i] !== "undefined") {
if ((tokenValue = _fn.call(O[i], O[i])) === false) break;else if (typeof tokenValue !== "undefined") defaultValue += tokenValue;
}
}
return defaultValue / l;
} else if (isObject(O)) {
l = 0;
for (i in O) {
if (typeof O[i] != "undefined") {
if ((tokenValue = _fn.call(O[i], O[i])) === false) break;else if (typeof tokenValue !== "undefined") defaultValue += tokenValue;++l;
}
}
return defaultValue / l;
} else {
console.error("argument error : ax5.util.sum - use Array or Object");
return defaultValue;
}
}
/**
* 배열의 왼쪽에서 오른쪽으로 연산을 진행하는데 수행한 결과가 왼쪽 값으로 반영되어 최종 왼쪽 값을 반환합니다.
* @method ax5.util.reduce
* @param {Array|Object} O
* @param {Function} _fn
* @returns {Alltypes}
* @example
* ```js
* var aarray = [5,4,3,2,1];
* result = ax5.util.reduce( aarray, function(p, n){
* return p * n;
* });
* console.log(result, aarray);
* // 120 [5, 4, 3, 2, 1]
*
* ax5.util.reduce({a:1, b:2}, function(p, n){
* return parseInt(p|0) + parseInt(n);
* });
* // 3
* ```
*/
function reduce(O, _fn) {
var i, l, tokenItem;
if (isArray(O)) {
i = 0, l = O.length, tokenItem = O[i];
for (; i < l - 1;) {
if (typeof O[i] != "undefined") {
if ((tokenItem = _fn.call(root, tokenItem, O[++i])) === false) break;
}
}
return tokenItem;
} else if (isObject(O)) {
for (i in O) {
if (typeof O[i] != "undefined") {
if ((tokenItem = _fn.call(root, tokenItem, O[i])) === false) break;
}
}
return tokenItem;
} else {
console.error("argument error : ax5.util.reduce - use Array or Object");
return null;
}
}
/**
* 배열의 오른쪽에서 왼쪽으로 연산을 진행하는데 수행한 결과가 오른쪽 값으로 반영되어 최종 오른쪽 값을 반환합니다.
* @method ax5.util.reduceRight
* @param {Array} O
* @param {Function} _fn
* @returns {Alltypes}
* @example
* ```js
* var aarray = [5,4,3,2,1];
* result = ax5.util.reduceRight( aarray, function(p, n){
* console.log( n );
* return p * n;
* });
* console.log(result, aarray);
* 120 [5, 4, 3, 2, 1]
* ```
*/
function reduceRight(O, _fn) {
var i = O.length - 1,
tokenItem = O[i];
for (; i > 0;) {
if (typeof O[i] != "undefined") {
if ((tokenItem = _fn.call(root, tokenItem, O[--i])) === false) break;
}
}
return tokenItem;
}
/**
* 배열또는 오브젝트의 각 아이템을 인자로 하는 사용자 함수의 결과가 참인 아이템들의 배열을 반환합니다.
* @method ax5.util.filter
* @param {Object|Array} O
* @param {Function} _fn
* @returns {Array}
* @example
* ```js
* var aarray = [5,4,3,2,1];
* result = ax5.util.filter( aarray, function(){
* return this % 2;
* });
* console.log(result);
* // [5, 3, 1]
*
* var filObject = {a:1, s:"string", oa:{pickup:true, name:"AXISJ"}, os:{pickup:true, name:"AX5"}};
* result = ax5.util.filter( filObject, function(){
* return this.pickup;
* });
* console.log( ax5.util.toJson(result) );
* // [{"pickup": , "name": "AXISJ"}, {"pickup": , "name": "AX5"}]
* ```
*/
function filter(O, _fn) {
if (isNothing(O)) return [];
var k,
i = 0,
l = O.length,
results = [],
fnResult;
if (isObject(O)) {
for (k in O) {
if (typeof O[k] != "undefined") {
if (fnResult = _fn.call(O[k], k, O[k])) results.push(O[k]);
}
}
} else {
for (; i < l;) {
if (typeof O[i] != "undefined") {
if (fnResult = _fn.call(O[i], i, O[i])) results.push(O[i]);
i++;
}
}
}
return results;
}
/**
* Object를 JSONString 으로 반환합니다.
* @method ax5.util.toJson
* @param {Object|Array} O
* @returns {String} JSON
* @example
* ```js
* var ax = ax5.util;
* var myObject = {
* a:1, b:"2", c:{axj:"what", arrs:[0,2,"3"]},
* fn: function(abcdd){
* return abcdd;
* }
* };
* console.log( ax.toJson(myObject) );
* ```
*/
function toJson(O) {
var jsonString = "";
if (ax5.util.isArray(O)) {
var i = 0,
l = O.length;
jsonString += "[";
for (; i < l; i++) {
if (i > 0) jsonString += ",";
jsonString += toJson(O[i]);
}
jsonString += "]";
} else if (ax5.util.isObject(O)) {
jsonString += "{";
var jsonObjectBody = [];
each(O, function (key, value) {
jsonObjectBody.push('"' + key + '": ' + toJson(value));
});
jsonString += jsonObjectBody.join(", ");
jsonString += "}";
} else if (ax5.util.isString(O)) {
jsonString = '"' + O + '"';
} else if (ax5.util.isNumber(O)) {
jsonString = O;
} else if (ax5.util.isUndefined(O)) {
jsonString = "undefined";
} else if (ax5.util.isFunction(O)) {
jsonString = '"{Function}"';
} else {
jsonString = O;
}
return jsonString;
}
/**
* 관용의 JSON Parser
* @method ax5.util.parseJson
* @param {String} JSONString
* @param {Boolean} [force] - 강제 적용 여부 (json 문자열 검사를 무시하고 오브젝트 변환을 시도합니다.)
* @returns {Object}
* @example
* ```
* console.log(ax5.util.parseJson('{"a":1}'));
* // Object {a: 1}
* console.log(ax5.util.parseJson("{'a':1, 'b':'b'}"));
* // Object {a: 1, b: "b"}
* console.log(ax5.util.parseJson("{'a':1, 'b':function(){return 1;}}", true));
* // Object {a: 1, b: function}
* console.log(ax5.util.parseJson("{a:1}"));
* // Object {a: 1}
* console.log(ax5.util.parseJson("[1,2,3]"));
* // [1, 2, 3]
* console.log(ax5.util.parseJson("['1','2','3']"));
* // ["1", "2", "3"]
* console.log(ax5.util.parseJson("[{'a':'99'},'2','3']"));
* // [Object, "2", "3"]
* ```
*/
function parseJson(str, force) {
if (force || reIsJson.test(str)) {
try {
return new Function('', 'return ' + str)();
} catch (e) {
return { error: 500, msg: 'syntax error' };
}
} else {
return { error: 500, msg: 'syntax error' };
}
}
/**
* 인자의 타입을 반환합니다.
* @method ax5.util.getType
* @param {Object|Array|String|Number|Element|Etc} O
* @returns {String} window|element|object|array|function|string|number|undefined|nodelist
* @example
* ```js
* var axf = ax5.util;
* var a = 11;
* var b = "11";
* console.log( axf.getType(a) );
* console.log( axf.getType(b) );
* ```
*/
function getType(O) {
var typeName;
if (O != null && O == O.window) {
typeName = "window";
} else if (!!(O && O.nodeType == 1)) {
typeName = "element";
} else if (!!(O && O.nodeType == 11)) {
typeName = "fragment";
} else if (O === null) {
typeName = "null";
} else if (typeof O === "undefined") {
typeName = "undefined";
} else if (_toString.call(O) == "[object Object]") {
typeName = "object";
} else if (_toString.call(O) == "[object Array]") {
typeName = "array";
} else if (_toString.call(O) == "[object String]") {
typeName = "string";
} else if (_toString.call(O) == "[object Number]") {
typeName = "number";
} else if (_toString.call(O) == "[object NodeList]") {
typeName = "nodelist";
} else if (typeof O === "function") {
typeName = "function";
}
return typeName;
}
/**
* 오브젝트가 window 인지 판단합니다.
* @method ax5.util.isWindow
* @param {Object} O
* @returns {Boolean}
*/
function isWindow(O) {
return O != null && O == O.window;
}
/**
* 오브젝트가 HTML 엘리먼트여부인지 판단합니다.
* @method ax5.util.isElement
* @param {Object} O
* @returns {Boolean}
*/
function isElement(O) {
return !!(O && (O.nodeType == 1 || O.nodeType == 11));
}
/**
* 오브젝트가 Object인지 판단합니다.
* @method ax5.util.isObject
* @param {Object} O
* @returns {Boolean}
*/
function isObject(O) {
return _toString.call(O) == "[object Object]";
}
/**
* 오브젝트가 Array인지 판단합니다.
* @method ax5.util.isArray
* @param {Object} O
* @returns {Boolean}
*/
function isArray(O) {
return _toString.call(O) == "[object Array]";
}
/**
* 오브젝트가 Function인지 판단합니다.
* @method ax5.util.isFunction
* @param {Object} O
* @returns {Boolean}
*/
function isFunction(O) {
return typeof O === "function";
}
/**
* 오브젝트가 String인지 판단합니다.
* @method ax5.util.isString
* @param {Object} O
* @returns {Boolean}
*/
function isString(O) {
return _toString.call(O) == "[object String]";
}
/**
* 오브젝트가 Number인지 판단합니다.
* @method ax5.util.isNumber
* @param {Object} O
* @returns {Boolean}
*/
function isNumber(O) {
return _toString.call(O) == "[object Number]";
}
/**
* 오브젝트가 NodeList인지 판단합니다.
* @method ax5.util.isNodelist
* @param {Object} O
* @returns {Boolean}
*/
function isNodelist(O) {
return !!(_toString.call(O) == "[object NodeList]" || typeof O !== "undefined" && O && O[0] && O[0].nodeType == 1);
}
/**
* 오브젝트가 undefined인지 판단합니다.
* @method ax5.util.isUndefined
* @param {Object} O
* @returns {Boolean}
*/
function isUndefined(O) {
return typeof O === "undefined";
}
/**
* 오브젝트가 undefined이거나 null이거나 빈값인지 판단합니다.
* @method ax5.util.isNothing
* @param {Object} O
* @returns {Boolean}
*/
function isNothing(O) {
return typeof O === "undefined" || O === null || O === "";
}
/**
* 오브젝트가 날자값인지 판단합니다.
* @method ax5.util.isDate
* @param {Date} O
* @returns {Boolean}
* @example
* ```js
* ax5.util.isDate('2016-09-30');
* // false
* ax5.util.isDate( new Date('2016-09-30') );
* // true
* ```
*/
function isDate(O) {
return O instanceof Date && !isNaN(O.valueOf());
}
function isDateFormat(O) {
var result = false;
if (!O) {} else if (O instanceof Date && !isNaN(O.valueOf())) {
result = true;
} else {
if (O.length > 7) {
if (date(O) instanceof Date) {
return true;
}
}
O = O.replace(/\D/g, '');
if (O.length > 7) {
var mm = O.substr(4, 2),
dd = O.substr(6, 2);
O = date(O);
if (O.getMonth() == mm - 1 && O.getDate() == dd) {
result = true;
}
}
}
return result;
}
/**
* 오브젝트의 첫번째 아이템을 반환합니다.
* @method ax5.util.first
* @param {Object|Array} O
* @returns {Object}
* @example
* ```js
* ax5.util.first({a:1, b:2});
* // Object {a: 1}
* ax5.util.first([1,2,3,4]);
* // 1
* ```
*/
function first(O) {
if (isObject(O)) {
var keys = Object.keys(O);
var item = {};
item[keys[0]] = O[keys[0]];
return item;
} else if (isArray(O)) {
return O[0];
} else {
console.error("ax5.util.object.first", "argument type error");
return undefined;
}
}
/**
* 오브젝트의 마지막 아이템을 반환합니다.
* @method ax5.util.last
* @param {Object|Array} O
* @returns {Object}
* @example
* ```js
* ax5.util.last({a:1, b:2});
* // Object {b: 2}
* ax5.util.last([1,2,3,4]);
* // 4
* ```
*/
function last(O) {
if (isObject(O)) {
var keys = Object.keys(O);
var item = {};
item[keys[keys.length - 1]] = O[keys[keys.length - 1]];
return item;
} else if (isArray(O)) {
return O[O.length - 1];
} else {
console.error("ax5.util.object.last", "argument type error");
return undefined;
}
}
/**
* 쿠키를 설정합니다.
* @method ax5.util.setCookie
* @param {String} cname - 쿠키이름
* @param {String} cvalue - 쿠키값
* @param {Number} [exdays] - 쿠키 유지일수
* @param {Object} [opts] - path, domain 설정 옵션
* @example
* ```js
* ax5.util.setCookie("jslib", "AX5");
* ax5.util.setCookie("jslib", "AX5", 3);
* ax5.util.setCookie("jslib", "AX5", 3, {path:"/", domain:".axisj.com"});
* ```
*/
function setCookie(cn, cv, exdays, opts) {
var expire;
if (typeof exdays === "number") {
expire = new Date();
expire.setDate(expire.getDate() + exdays);
}
opts = opts || {};
return doc.cookie = [escape(cn), '=', escape(cv), expire ? "; expires=" + expire.toUTCString() : "", // use expires attribute, max-age is not supported by IE
opts.path ? "; path=" + opts.path : "", opts.domain ? "; domain=" + opts.domain : "", opts.secure ? "; secure" : ""].join("");
}
/**
* 쿠키를 가져옵니다.
* @method ax5.util.getCookie
* @param {String} cname
* @returns {String} cookie value
* @example
* ```js
* ax5.util.getCookie("jslib");
* ```
*/
function getCookie(cname) {
var name = cname + "=";
var ca = doc.cookie.split(';'),
i = 0,
l = ca.length;
for (; i < l; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}if (c.indexOf(name) != -1) return unescape(c.substring(name.length, c.length));
}
return "";
}
/**
* jsonString 으로 alert 합니다.
* @method ax5.util.alert
* @param {Object|Array|String|Number} O
* @returns {Object|Array|String|Number} O
* @example ```js
* ax5.util.alert({a:1,b:2});
* ax5.util.alert("정말?");
* ```
*/
function alert(O) {
win.alert(toJson(O));
return O;
}
/**
* 문자열의 특정 문자열까지 잘라주거나 원하는 포지션까지 잘라줍니다.
* @method ax5.util.left
* @param {String} str - 문자열
* @param {String|Number} pos - 찾을 문자열 또는 포지션
* @returns {String}
* @example
* ```js
* ax5.util.left("abcd.efd", 3);
* // abc
* ax5.util.left("abcd.efd", ".");
* // abcd
* ```
*/
function left(str, pos) {
if (typeof str === "undefined" || typeof pos === "undefined") return "";
if (isString(pos)) {
return str.indexOf(pos) > -1 ? str.substr(0, str.indexOf(pos)) : "";
} else if (isNumber(pos)) {
return str.substr(0, pos);
} else {
return "";
}
}
/**
* 문자열의 특정 문자열까지 잘라주거나 원하는 포지션까지 잘라줍니다.
* @method ax5.util.right
* @param {String} str - 문자열
* @param {String|Number} pos - 찾을 문자열 또는 포지션
* @returns {String}
* @example
* ```js
* ax5.util.right("abcd.efd", 3);
* // efd
* ax5.util.right("abcd.efd", ".");
* // efd
* ```
*/
function right(str, pos) {
if (typeof str === "undefined" || typeof pos === "undefined") return "";
str = '' + str;
if (isString(pos)) {
return str.lastIndexOf(pos) > -1 ? str.substr(str.lastIndexOf(pos) + 1) : "";
} else if (isNumber(pos)) {
return str.substr(str.length - pos);
} else {
return "";
}
}
/**
* css형 문자열이나 특수문자가 포함된 문자열을 카멜케이스로 바꾸어 반환합니다.
* @method ax5.util.camelCase
* @param {String} str
* @returns {String}
* @example
* ```js
* ax5.util.camelCase("inner-width");
* ax5.util.camelCase("innerWidth");
* // innerWidth
* ```
*/
function camelCase(str) {
return str.replace(reMs, "ms-").replace(reSnakeCase, function (all, letter) {
return letter.toUpperCase();
});
}
/**
* css형 문자열이나 카멜케이스문자열을 스네이크 케이스 문자열로 바꾸어 반환합니다.
* @method ax5.util.snakeCase
* @param {String} str
* @returns {String}
* @example
* ```js
* ax5.util.snakeCase("innerWidth");
* ax5.util.snakeCase("inner-Width");
* ax5.util.snakeCase("innerWidth");
* // inner-width
* ```
*/
function snakeCase(str) {
return camelCase(str).replace(reCamelCase, function (all, letter) {
return "-" + letter.toLowerCase();
});
}
/**
* 문자열에서 -. 을 제외한 모든 문자열을 제거하고 숫자로 반환합니다. 옵션에 따라 원하는 형식의 숫자로 변환 할 수 도 있습니다.
* @method ax5.util.number
* @param {String|Number} str
* @param {Object} cond - 옵션
* @returns {String|Number}
* @example
* ```js
* var cond = {
* round: {Number|Boolean} - 반올림할 자릿수,
* money: {Boolean} - 통화,
* abs: {Boolean} - 절대값,
* byte: {Boolean} - 바이트
* }
*
* console.log(ax5.util.number(123456789.678, {round:1}));
* console.log(ax5.util.number(123456789.678, {round:1, money:true}));
* console.log(ax5.util.number(123456789.678, {round:2, byte:true}));
* console.log(ax5.util.number(-123456789.8888, {abs:true, round:2, money:true}));
* console.log(ax5.util.number("A-1234~~56789.8~888PX", {abs:true, round:2, money:true}));
*
* //123456789.7
* //123,456,789.7
* //117.7MB
* //123,456,789.89
* //123,456,789.89
* ```
*/
function number(str, cond) {
var result,
pair = ('' + str).split(reDot),
isMinus,
returnValue;
isMinus = Number(pair[0].replace(/,/g, "")) < 0 || pair[0] == "-0";
returnValue = 0.0;
pair[0] = pair[0].replace(reInt, "");
if (pair[1]) {
pair[1] = pair[1].replace(reNotNum, "");
returnValue = Number(pair[0] + "." + pair[1]) || 0;
} else {
returnValue = Number(pair[0]) || 0;
}
result = isMinus ? -returnValue : returnValue;
each(cond, function (k, c) {
if (k == "round") {
if (isNumber(c)) {
if (c < 0) {
result = +(Math.round(result + "e-" + Math.abs(c)) + "e+" + Math.abs(c));
} else {
result = +(Math.round(result + "e+" + c) + "e-" + c);
}
} else {
result = Math.round(result);
}
}
if (k == "floor") {
result = Math.floor(result);
}
if (k == "ceil") {
result = Math.ceil(result);
} else if (k == "money") {
result = function (val) {
var txtNumber = '' + val;
if (isNaN(txtNumber) || txtNumber == "") {
return "";
} else {
var arrNumber = txtNumber.split('.');
arrNumber[0] += '.';
do {
arrNumber[0] = arrNumber[0].replace(reMoneySplit, '$1,$2');
} while (reMoneySplit.test(arrNumber[0]));
if (arrNumber.length > 1) {
return arrNumber.join('');
} else {
return arrNumber[0].split('.')[0];
}
}
}(result);
} else if (k == "abs") {
result = Math.abs(Number(result));
} else if (k == "byte") {
result = function (val) {
val = Number(result);
var nUnit = "KB";
var myByte = val / 1024;
if (myByte / 1024 > 1) {
nUnit = "MB";
myByte = myByte / 1024;
}
if (myByte / 1024 > 1) {
nUnit = "GB";
myByte = myByte / 1024;
}
return number(myByte, { round: 1 }) + nUnit;
}(result);
}
});
return result;
}
/**
* 배열 비슷한 오브젝트를 배열로 변환해줍니다.
* @method ax5.util.toArray
* @param {Object|Elements|Arguments} O
* @returns {Array}
* @example
* ```js
* ax5.util.toArray(arguments);
* //
* ```
*/
function toArray(O) {
if (typeof O.length != "undefined") return Array.prototype.slice.call(O);
return [];
}
/**
* 첫번째 인자에 두번째 인자 아이템을 합쳐줍니다. concat과 같은 역할을 하지만. 인자가 Array타입이 아니어도 됩니다.
* @method ax5.util.merge
* @param {Array|ArrayLike} first
* @param {Array|ArrayLike} second
* @returns {Array} first
* @example
* ```
*
* ```
*/
function merge(first, second) {
var l = second.length,
i = first.length,
j = 0;
if (typeof l === "number") {
for (; j < l; j++) {
first[i++] = second[j];
}
} else {
while (second[j] !== undefined) {
first[i++] = second[j++];
}
}
first.length = i;
return first;
}
/**
* 오브젝트를 파라미터형식으로 또는 파라미터를 오브젝트 형식으로 변환합니다.
* @method ax5.util.param
* @param {Object|Array|String} O
* @param {String} [cond] - param|object
* @returns {Object|String}
* @example
* ```
* ax5.util.param({a:1,b:'1232'}, "param");
* ax5.util.param("a=1&b=1232", "param");
* // "a=1&b=1232"
* ax5.util.param("a=1&b=1232");
* // {a: "1", b: "1232"}
* ```
*/
function param(O, cond) {
var p;
if (isString(O) && typeof cond !== "undefined" && cond == "param") {
return O;
} else if (isString(O) && typeof cond !== "undefined" && cond == "object" || isString(O) && typeof cond === "undefined") {
p = {};
each(O.split(reAmp), function () {
var item = this.split(reEq);
if (!p[item[0]]) p[item[0]] = item[1];else {
if (isString(p[item[0]])) p[item[0]] = [p[item[0]]];
p[item[0]].push(item[1]);
}
});
return p;
} else {
p = [];
each(O, function (k, v) {
p.push(k + "=" + escape(v));
});
return p.join('&');
}
}
function encode(s) {
return encodeURIComponent(s);
}
function decode(s) {
return decodeURIComponent(s);
}
function error() {
ax5.info.onerror.apply(this, arguments);
}
function localDate(yy, mm, dd, hh, mi, ss) {
var utcD, localD;
localD = new Date();
if (mm < 0) mm = 0;
if (typeof hh === "undefined") hh = 12;
if (typeof mi === "undefined") mi = 0;
utcD = new Date(Date.UTC(yy, mm, dd || 1, hh, mi, ss || 0));
if (mm == 0 && dd == 1 && utcD.getUTCHours() + utcD.getTimezoneOffset() / 60 < 0) {
utcD.setUTCHours(0);
} else {
utcD.setUTCHours(utcD.getUTCHours() + utcD.getTimezoneOffset() / 60);
}
return utcD;
}
/**
* 날짜 형식의 문자열이나 Date객체를 조건에 맞게 처리 한 후 원하는 return 값으로 반환합니다.
* @method ax5.util.date
* @param {String|Date} d
* @param {Object} cond
* @returns {Date|String}
* @example
* ```js
* ax5.util.date('2013-01-01'); // Tue Jan 01 2013 23:59:00 GMT+0900 (KST)
* ax5.util.date((new Date()), {add:{d:10}, return:'yyyy/MM/dd'}); // "2015/07/01"
* ax5.util.date('1919-03-01', {add:{d:10}, return:'yyyy/MM/dd hh:mm:ss'}); // "1919/03/11 23:59:00"
* ```
*/
function date(d, cond) {
var yy = void 0,
mm = void 0,
dd = void 0,
hh = void 0,
mi = void 0,
aDateTime = void 0,
aTimes = void 0,
aTime = void 0,
aDate = void 0,
va = void 0,
ISO_8601 = /^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?$/i,
ISO_8601_FULL = /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i;
if (isString(d)) {
if (d.length == 0) {
d = new Date();
} else if (d.length > 15) {
if (ISO_8601_FULL.test(d) || ISO_8601.test(d)) {
d = new Date(d);
} else {
aDateTime = d.split(/ /g), aTimes, aTime, aDate = aDateTime[0].split(/\D/g), yy = aDate[0];
mm = parseFloat(aDate[1]);
dd = parseFloat(aDate[2]);
aTime = aDateTime[1] || "09:00";
aTimes = aTime.substring(0, 5).split(":");
hh = parseFloat(aTimes[0]);
mi = parseFloat(aTimes[1]);
if (right(aTime, 2) === "AM" || right(aTime, 2) === "PM") hh += 12;
d = localDate(yy, mm - 1, dd, hh, mi);
}
} else if (d.length == 14) {
va = d.replace(/\D/g, "");
d = localDate(va.substr(0, 4), va.substr(4, 2) - 1, number(va.substr(6, 2)), number(va.substr(8, 2)), number(va.substr(10, 2)), number(va.substr(12, 2)));
} else if (d.length > 7) {
va = d.replace(/\D/g, "");
d = localDate(va.substr(0, 4), va.substr(4, 2) - 1, number(va.substr(6, 2)));
} else if (d.length > 4) {
va = d.replace(/\D/g, "");
d = localDate(va.substr(0, 4), va.substr(4, 2) - 1, 1);
} else if (d.length > 2) {
va = d.replace(/\D/g, "");
return localDate(va.substr(0, 4), va.substr(4, 2) - 1, 1);
} else {
d = new Date();
}
}
if (typeof cond === "undefined" || typeof d === "undefined") {
return d;
} else {
if ("add" in cond) {
d = function (_d, opts) {
var yy = void 0,
mm = void 0,
dd = void 0,
mxdd = void 0,
DyMilli = 1000 * 60 * 60 * 24;
if (typeof opts["d"] !== "undefined") {
_d.setTime(_d.getTime() + opts["d"] * DyMilli);
} else if (typeof opts["m"] !== "undefined") {
yy = _d.getFullYear();
mm = _d.getMonth();
dd = _d.getDate();
yy = yy + parseInt(opts["m"] / 12);
mm += opts["m"] % 12;
mxdd = daysOfMonth(yy, mm);
if (mxdd < dd) dd = mxdd;
_d = new Date(yy, mm, dd, 12);
} else if (typeof opts["y"] !== "undefined") {
_d.setTime(_d.getTime() + opts["y"] * 365 * DyMilli);
} else if (typeof opts["h"] !== "undefined") {
_d.setTime(_d.getTime() + opts["h"] * 1000 * 60 * 60);
}
return _d;
}(new Date(d), cond["add"]);
}
if ("set" in cond) {
d = function (_d, opts) {
var yy = void 0,
mm = void 0,
dd = void 0,
processor = {
"firstDayOfMonth": function firstDayOfMonth(date) {
yy = date.getFullYear();
mm = date.getMonth();
dd = 1;
return new Date(yy, mm, dd, 12);
},
"lastDayOfMonth": function lastDayOfMonth(date) {
yy = date.getFullYear();
mm = date.getMonth();
dd = daysOfMonth(yy, mm);
return new Date(yy, mm, dd, 12);
}
};
if (opts in processor) {
return processor[opts](_d);
} else {
return _d;
}
}(new Date(d), cond["set"]);
}
if ("return" in cond) {
return function () {
var fStr = cond["return"],
nY = void 0,
nM = void 0,
nD = void 0,
nH = void 0,
nMM = void 0,
nS = void 0,
nDW = void 0,
yre = void 0,
regY = void 0,
mre = void 0,
regM = void 0,
dre = void 0,
regD = void 0,
hre = void 0,
regH = void 0,
mire = void 0,
regMI = void 0,
sre = void 0,
regS = void 0,
dwre = void 0,
regDW = void 0;
nY = d.getUTCFullYear();
nM = setDigit(d.getMonth() + 1, 2);
nD = setDigit(d.getDate(), 2);
nH = setDigit(d.getHours(), 2);
nMM = setDigit(d.getMinutes(), 2);
nS = setDigit(d.getSeconds(), 2);
nDW = d.getDay();
yre = /[^y]*(yyyy)[^y]*/gi;
yre.exec(fStr);
regY = RegExp.$1;
mre = /[^m]*(MM)[^m]*/g;
mre.exec(fStr);
regM = RegExp.$1;
dre = /[^d]*(dd)[^d]*/gi;
dre.exec(fStr);
regD = RegExp.$1;
hre = /[^h]*(hh)[^h]*/gi;
hre.exec(fStr);
regH = RegExp.$1;
mire = /[^m]*(mm)[^i]*/g;
mire.exec(fStr);
regMI = RegExp.$1;
sre = /[^s]*(ss)[^s]*/gi;
sre.exec(fStr);
regS = RegExp.$1;
dwre = /[^d]*(dw)[^w]*/gi;
dwre.exec(fStr);
regDW = RegExp.$1;
if (regY === "yyyy") {
fStr = fStr.replace(regY, right(nY, regY.length));
}
if (regM === "MM") {
if (regM.length == 1) nM = d.getMonth() + 1;
fStr = fStr.replace(regM, nM);
}
if (regD === "dd") {
if (regD.length == 1) nD = d.getDate();
fStr = fStr.replace(regD, nD);
}
if (regH === "hh") {
fStr = fStr.replace(regH, nH);
}
if (regMI === "mm") {
fStr = fStr.replace(regMI, nMM);
}
if (regS === "ss") {
fStr = fStr.replace(regS, nS);
}
if (regDW == "dw") {
fStr = fStr.replace(regDW, info.weekNames[nDW].label);
}
return fStr;
}();
} else {
return d;
}
}
}
/**
* 인자인 날짜가 오늘부터 몇일전인지 반환합니다. 또는 인자인 날짜가 가까운 미래에 몇일 후인지 반환합니다.
* @method ax5.util.dday
* @param {String|Data} d
* @param {Object} cond
* @returns {Number}
* @example
* ```js
* ax5.util.dday('2016-01-29');
* // 1
* ax5.util.dday('2016-01-29', {today:'2016-01-28'});
* // 1
* ax5.util.dday('1977-03-29', {today:'2016-01-28', age:true});
* // 39
* ```
*/
function dday(d, cond) {
var memoryDay = date(d),
DyMilli = 1000 * 60 * 60 * 24,
today = new Date(),
diffnum,
thisYearMemoryDay;
function getDayTime(_d) {
return Math.floor(_d.getTime() / DyMilli) * DyMilli;
}
if (typeof cond === "undefined") {
diffnum = number((getDayTime(memoryDay) - getDayTime(today)) / DyMilli, { floor: true });
return diffnum;
} else {
diffnum = number((getDayTime(memoryDay) - getDayTime(today)) / DyMilli, { floor: true });
if (cond["today"]) {
today = date(cond.today);
diffnum = number((getDayTime(memoryDay) - getDayTime(today)) / DyMilli, { floor: true });
}
if (cond["thisYear"]) {
thisYearMemoryDay = new Date(today.getFullYear(), memoryDay.getMonth(), memoryDay.getDate());
diffnum = number((getDayTime(thisYearMemoryDay) - getDayTime(today)) / DyMilli, { floor: true });
if (diffnum < 0) {
thisYearMemoryDay = new Date(today.getFullYear() + 1, memoryDay.getMonth(), memoryDay.getDate());
diffnum = number((getDayTime(thisYearMemoryDay) - getDayTime(today)) / DyMilli, { floor: true });
}
}
if (cond["age"]) {
thisYearMemoryDay = new Date(today.getFullYear(), memoryDay.getMonth(), memoryDay.getDate());
diffnum = thisYearMemoryDay.getFullYear() - memoryDay.getFullYear();
}
return diffnum;
}
}
/**
* 인자인 날짜가 몇년 몇월의 몇번째 주차인지 반환합니다.
* @method ax5.util.weeksOfMonth
* @param {String|Data} d
* @returns {Object}
* @example
* ```js
* ax5.util.weeksOfMonth("2015-10-01"); // {year: 2015, month: 10, count: 1}
* ax5.util.weeksOfMonth("2015-09-19"); // {year: 2015, month: 9, count: 3}
* ```
*/
function weeksOfMonth(d) {
var myDate = date(d);
return {
year: myDate.getFullYear(),
month: myDate.getMonth() + 1,
count: parseInt(myDate.getDate() / 7 + 1)
};
}
/**
* 년월에 맞는 날자수를 반환합니다.
* (new Date()).getMonth() 기준으로 월값을 보냅니다. "2월" 인경우 "1" 을 넘기게 됩니다.
* @method ax5.util.daysOfMonth
* @param {Number} y
* @param {Number} m
* @returns {Number}
* @examples
* ```js
* ax5.util.daysOfMonth(2015, 11); // 31
* ax5.util.daysOfMonth(2015, 1); // 28
* ```
*/
function daysOfMonth(y, m) {
if (m == 3 || m == 5 || m == 8 || m == 10) {
return 30;
} else if (m == 1) {
return y % 4 == 0 && y % 100 != 0 || y % 400 == 0 ? 29 : 28;
} else {
return 31;
}
}
/**
* 원하는 횟수 만큼 자릿수 맞춤 문자열을 포함한 문자열을 반환합니다.
* 문자열 길이보다 작은값을 보내면 무시됩니다.
* @method ax5.util.setDigit
* @param {String|Number} num
* @param {Number} length
* @param {String} [padder=0]
* @param {Number} [radix]
* @returns {String}
* @example
* ```
* ax5.util.setDigit(2016, 6)
* // "002016"
* ax5.util.setDigit(2016, 2)
* // "2016"
* ```
*/
function setDigit(num, length, padder, radix) {
var s = num.toString(radix || 10);
return times(padder || '0', length - s.length) + s;
}
/**
* 문자열을 지정된 수만큼 반복 합니다.
* @param {String} s
* @param {Number} count
* @returns {string}
* @example
* ```
* ax5.util.times(2016, 2)
* //"20162016"
* ```
*/
function times(s, count) {
return count < 1 ? '' : new Array(count + 1).join(s);
}
/**
* 타겟엘리먼트의 부모 엘리멘트 트리에서 원하는 조건의 엘리먼트를 얻습니다.
* @method ax5.util.findParentNode
* @param {Element} _target - target element
* @param {Object|Function} cond - 원하는 element를 찾을 조건
* @returns {Element}
* @example
* ```
* // cond 속성정의
* var cond = {
* tagname: {String} - 태그명 (ex. a, div, span..),
* clazz: {String} - 클래스명
* [, 그 외 찾고 싶은 attribute명들]
* };
* console.log(
* console.log(
* ax5.util.findParentNode(e.target, {tagname:"a", clazz:"ax-menu-handel", "data-custom-attr":"attr_value"})
* );
* // cond 함수로 처리하기
* jQuery('#id').bind("click.app_expand", function(e){
* var target = ax5.util.findParentNode(e.target, function(target){
* if($(target).hasClass("aside")){
* return true;
* }
* else{
* return true;
* }
* });
* //client-aside
* if(target.id !== "client-aside"){
* // some action
* }
* });
* ```
*/
function findParentNode(_target, cond) {
if (_target) {
while (function () {
var result = true;
if (typeof cond === "undefined") {
_target = _target.parentNode ? _target.parentNode : false;
} else if (isFunction(cond)) {
result = cond(_target);
} else if (isObject(cond)) {
for (var k in cond) {
if (k === "tagname") {
if (_target.tagName.toLocaleLowerCase() != cond[k]) {
result = false;
break;
}
} else if (k === "clazz" || k === "class_name") {
if ("className" in _target) {
var klasss = _target.className.split(reClassNameSplit);
var hasClass = false;
for (var a = 0; a < klasss.length; a++) {
if (klasss[a] == cond[k]) {
hasClass = true;
break;
}
}
result = hasClass;
} else {
result = false;
break;
}
} else {
// 그외 속성값들.
if (_target.getAttribute) {
if (_target.getAttribute(k) != cond[k]) {
result = false;
break;
}
} else {
result = false;
break;
}
}
}
}
return !result;
}()) {
if (_target.parentNode && _target.parentNode.parentNode) {
_target = _target.parentNode;
} else {
_target = false;
break;
}
}
}
return _target;
}
/**
* @method ax5.util.cssNumber
* @param {String|Number} val
* @returns {String}
* @example
* ```
* console.log(ax5.util.cssNumber("100px"))
* console.log(ax5.util.cssNumber("100%"))
* console.log(ax5.util.cssNumber("100"))
* console.log(ax5.util.cssNumber(100))
* console.log(ax5.util.cssNumber("!!100@#"))
* ```
*/
function cssNumber(val) {
var re = /\D?(\d+)([a-zA-Z%]*)/i,
found = ('' + val).match(re),
unit = found[2] || "px";
return found[1] + unit;
}
/**
* css string 및 object 를 넘기면 object 및 string 으로 변환되어 리턴됩니다.
* @method ax5.util.css
* @param {Object|String} val - CSS String or CSS Object
* @returns {String|Object}
* @example
* ```
* console.log(ax5.util.css({background: "#ccc", padding: "50px", width: "100px"}));
* //"background:#ccc;padding:50px;width:100px;"
* console.log(ax5.util.css('width:100px;padding: 50px; background: #ccc'));
* // object {width: "100px", padding: "50px", background: "#ccc"}
* ```
*/
function css(val) {
var returns;
if (isObject(val)) {
returns = '';
for (var k in val) {
returns += k + ':' + val[k] + ';';
}
return returns;
} else if (isString(val)) {
returns = {};
var valSplited = val.split(/[ ]*;[ ]*/g);
valSplited.forEach(function (v) {
if ((v = v.trim()) !== "") {
var vSplited = v.split(/[ ]*:[ ]*/g);
returns[vSplited[0]] = vSplited[1];
}
});
return returns;
}
}
/**
* @method ax5.util.stopEvent
* @param {Event} e
* @example
* ```
* ax5.util.stopEvent(e);
* ```
*/
function stopEvent(e) {
// 이벤트 중지 구문
if (!e) var e = window.event;
//e.cancelBubble is supported by IE -
// this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = false;
//e.stopPropagation works only in Firefox.
if (e.stopPropagation) e.stopPropagation();
if (e.preventDefault) e.preventDefault();
return false;
// 이벤트 중지 구문 끝
}
/**
* @method ax5.util.selectRange
* @param {Element} el
* @param {Element} offset
* @example
* ```
* ax5.util.selectRange($("#select-test-0")); // selectAll
* ax5.util.selectRange($("#select-test-0"), "selectAll"); //selectAll
* ax5.util.selectRange($("#select-test-0"), "start"); // focus on start
* ax5.util.selectRange($("#select-test-0"), "end"); // focus on end
* ax5.util.selectRange($("#select-test-0"), [1, 5]); // select 1~5
* ```
*/
var selectRange = function () {
var processor = {
'textRange': {
'selectAll': function selectAll(el, range, offset) {},
'arr': function arr(el, range, offset) {
range.moveStart("character", offset[0]); // todo ie node select 체크필요
range.collapse();
range.moveEnd("character", offset[1]);
},
'start': function start(el, range, offset) {
range.moveStart("character", 0);
range.collapse();
},
'end': function end(el, range, offset) {
range.moveStart("character", range.text.length);
range.collapse();
}
},
'range': {
'selectAll': function selectAll(el, range, offset) {
range.selectNodeContents(el);
},
'arr': function arr(el, range, offset) {
if (isObject(offset[0])) {
range.setStart(offset[0].node, offset[0].offset);
range.setEnd(offset[1].node, offset[1].offset);
} else {
range.setStart(el.firstChild, offset[0]);
range.setEnd(el.firstChild, offset[1]);
}
},
'start': function start(el, range, offset) {
range.selectNodeContents(el);
range.collapse(true);
},
'end': function end(el, range, offset) {
range.selectNodeContents(el);
range.collapse(false);
}
}
};
return function (el, offset) {
var range, rangeType, selection;
if (el instanceof jQuery) {
el = el.get(0);
}
if (!el) return;
// 레인지 타입 선택
if (doc.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(el);
rangeType = "textRange";
} else if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
rangeType = "range";
}
// range 적용
if (typeof offset == "undefined") {
processor[rangeType].selectAll.call(this, el, range, offset);
} else if (isArray(offset)) {
processor[rangeType].arr.call(this, el, range, offset);
} else {
for (var key in processor[rangeType]) {
if (offset == key) {
processor[rangeType][key].call(this, el, range, offset);
break;
}
}
}
// 포커스 및 셀렉트
if (doc.body.createTextRange) {
range.select();
el.focus();
} else if (window.getSelection) {
el.focus();
selection.removeAllRanges();
selection.addRange(range);
}
};
}();
/**
* 지정한 시간을 지연시켜 함수를 실행합니다.
* @method ax5.util.debounce
* @param {Function} func
* @param {Number} wait
* @param {Object} options
* @returns {debounced}
* @example
* ```js
* var debounceFn = ax5.util.debounce(function( val ) { console.log(val); }, 300);
* $(document.body).click(function(){
* debounceFn(new Date());
* });
* ```
*/
// https://github.com/lodash/lodash/blob/master/debounce.js
function debounce(func, wait, options) {
var lastArgs = void 0,
lastThis = void 0,
maxWait = void 0,
result = void 0,
timerId = void 0,
lastCallTime = void 0;
var lastInvokeTime = 0;
var leading = false;
var maxing = false;
var trailing = true;
if (typeof func != 'function') {
throw new TypeError('Expected a function');
}
wait = +wait || 0;
if (isObject(options)) {
leading = !!options.leading;
maxing = 'maxWait' in options;
maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs;
var thisArg = lastThis;
lastArgs = lastThis = undefined;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
// Reset any `maxWait` timer.
lastInvokeTime = time;
// Start the timer for the trailing edge.
timerId = setTimeout(timerExpired, wait);
// Invoke the leading edge.
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime;
var timeSinceLastInvoke = time - lastInvokeTime;
var result = wait - timeSinceLastCall;
return maxing ? Math.min(result, maxWait - timeSinceLastInvoke) : result;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime;
var timeSinceLastInvoke = time - lastInvokeTime;
// Either this is the first call, activity has stopped and we're at the
// trailing edge, the system time has gone backwards and we're treating
// it as the trailing edge, or we've hit the `maxWait` limit.
return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
}
function timerExpired() {
var time = Date.now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
// Restart the timer.
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined;
// Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined;
return result;
}
function cancel() {
if (timerId !== undefined) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined;
}
function flush() {
return timerId === undefined ? result : trailingEdge(Date.now());
}
function debounced() {
var time = Date.now();
var isInvoking = shouldInvoke(time);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
lastArgs = args;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined) {
return leadingEdge(lastCallTime);
}
if (maxing) {
// Handle invocations in a tight loop.
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
/**
* @method ax5.util.throttle
* @param func
* @param wait
* @param options
* @return {debounced}
*/
//https://github.com/lodash/lodash/blob/master/throttle.js
function throttle(func, wait, options) {
var leading = true;
var trailing = true;
if (typeof func != 'function') {
throw new TypeError('Expected a function');
}
if (isObject(options)) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
return debounce(func, wait, {
'leading': leading,
'maxWait': wait,
'trailing': trailing
});
}
/**
* @method ax5.util.deepCopy
* @param {Object} obj
* @returns {Object}
* @example
* ```js
* var obj = [
* {name:"A", child:[{name:"a-1"}]},
* {name:"B", child:[{name:"b-1"}], callBack: function(){ console.log('callBack'); }}
* ];
* var copiedObj = ax5.util.deepCopy(obj)
* ```
*/
function deepCopy(obj) {
var r, l;
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) == 'object') {
if (U.isArray(obj)) {
l = obj.length;
r = new Array(l);
for (var i = 0; i < l; i++) {
r[i] = deepCopy(obj[i]);
}
return r;
} else {
return jQuery.extend({}, obj);
}
}
return obj;
}
/**
* HTML 문자열을 escape 처리합니다.
* "<" represents the < sign.
* ">" represents the > sign.
* "&" represents the & sign.
* "" represents the " mark.
* [Character entity references](https://www.w3.org/TR/html401/charset.html#h-5.3)
* @method ax5.util.escapeHtml
* @param {String} s
* @returns {string}
* @example
* ```
* ax5.util.escapeHtml('HTML string & "escape"')
* //"HTML <span>string</span> & "escape""
* ```
*/
function escapeHtml(s) {
if (_toString.call(s) != "[object String]") return s;
if (!s) return "";
return s.replace(/[\<\>\&\"]/gm, function (match) {
switch (match) {
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case "\"":
return """;
default:
return match;
}
});
}
/**
* HTML 문자열을 unescape 처리합니다.
* escapeHtml를 참고하세요.
* @method ax5.util.unescapeHtml
* @param {String} s
* @returns {string}
* @example
* ```
* ax5.util.unescapeHtml('HTML <span>string</span> & "escape"')
* //"HTML string & "escape""
* ```
*/
function unescapeHtml(s) {
if (_toString.call(s) != "[object String]") return s;
if (!s) return "";
return s.replace(/(<)|(>)|(&)|(")/gm, function (match) {
switch (match) {
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case """:
return "\"";
default:
return match;
}
});
}
/**
* @method ax5.util.string
* @param {String} tmpl
* @param {*} args
* @return {ax5string}
* @example
* ```js
* ax5.util.string("{0} is dead, but {1} is alive! {0} {2}").format("ASP", "ASP.NET");
* ax5.util.string("{0} is dead, but {1} is alive! {0} {2}").format(["ASP", "ASP.NET"]);
* ax5.util.stinrg("{0} counts").format(100);
* ```
*/
function string(_string) {
return new function (_string) {
this.value = _string;
this.toString = function () {
return this.value;
};
/**
* @method ax5.util.string.format
* @returns {*}
*/
this.format = function () {
var args = [];
for (var i = 0, l = arguments.length; i < l; i++) {
args = args.concat(arguments[i]);
}
return this.value.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] != 'undefined' ? args[number] : match;
});
};
/**
* @method ax5.util.string.escape
* @returns {*}
*/
this.escape = function () {
return escapeHtml(this.value);
};
/**
* @method ax5.util.string.unescape
* @returns {*}
*/
this.unescape = function () {
return unescapeHtml(this.value);
};
/**
* @method ax5.util.string.encode
* @returns {*}
*/
this.encode = function () {
return encode(this.value);
};
/**
* @method ax5.util.string.decode
* @returns {*}
*/
this.decode = function () {
return decode(this.value);
};
/**
* @method ax5.util.string.left
* @param {String|Number} pos - 찾을 문자열 또는 포지션
* @returns {*}
*/
this.left = function (_pos) {
return left(this.value, _pos);
};
/**
* @method ax5.util.string.right
* @param {String|Number} pos - 찾을 문자열 또는 포지션
* @returns {*}
*/
this.right = function (_pos) {
return right(this.value, _pos);
};
/**
* @method ax5.util.string.camelCase
* @returns {*}
*/
this.camelCase = function () {
return camelCase(this.value);
};
/**
* @method ax5.util.string.snakeCase
* @returns {*}
*/
this.snakeCase = function () {
return snakeCase(this.value);
};
}(_string);
}
/**
* @method ax5.util.color
* @param _hexColor
* @return {ax5color}
* @example
* ```js
* ax5.util.color("#ff3300").lighten(10).getHexValue()
* console.log(ax5.util.color("#ff3300").darken(10).getHexValue());
* ```
*/
function color(_hexColor) {
var matchers = function () {
//
var CSS_INTEGER = "[-\\+]?\\d+%?";
//
var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
// Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
// Actual matching.
// Parentheses and commas are optional, but not required.
// Whitespace can take the place of commas or opening paren
var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
return {
CSS_UNIT: new RegExp(CSS_UNIT),
rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
};
}();
var convertObject = function convertObject(_color) {
var match = void 0;
if (match = matchers.rgb.exec(_color)) {
return { r: match[1], g: match[2], b: match[3] };
}
if (match = matchers.rgba.exec(_color)) {
return { r: match[1], g: match[2], b: match[3], a: match[4] };
}
if (match = matchers.hsl.exec(_color)) {
return { h: match[1], s: match[2], l: match[3] };
}
if (match = matchers.hsla.exec(_color)) {
return { h: match[1], s: match[2], l: match[3], a: match[4] };
}
if (match = matchers.hsv.exec(_color)) {
return { h: match[1], s: match[2], v: match[3] };
}
if (match = matchers.hsva.exec(_color)) {
return { h: match[1], s: match[2], v: match[3], a: match[4] };
}
if (match = matchers.hex8.exec(_color)) {
return {
r: parseInt(match[1], 16),
g: parseInt(match[2], 16),
b: parseInt(match[3], 16),
a: parseInt(match[4] / 255, 16),
format: "hex8"
};
}
if (match = matchers.hex6.exec(_color)) {
return {
r: parseInt(match[1], 16),
g: parseInt(match[2], 16),
b: parseInt(match[3], 16),
format: "hex"
};
}
if (match = matchers.hex4.exec(_color)) {
return {
r: parseInt(match[1] + '' + match[1], 16),
g: parseInt(match[2] + '' + match[2], 16),
b: parseInt(match[3] + '' + match[3], 16),
a: parseInt(match[4] + '' + match[4], 16),
format: "hex8"
};
}
if (match = matchers.hex3.exec(_color)) {
return {
r: parseInt(match[1] + '' + match[1], 16),
g: parseInt(match[2] + '' + match[2], 16),
b: parseInt(match[3] + '' + match[3], 16),
format: "hex"
};
}
return false;
};
function isOnePointZero(n) {
return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
}
function isPercentage(n) {
return typeof n === "string" && n.indexOf('%') != -1;
}
function convertToPercentage(n) {
if (n <= 1) {
n = n * 100 + "%";
}
return n;
}
function convertTo255(n) {
return ax5.util.number(Math.min(255, Math.max(n, 0)), { 'round': 2 });
}
function convertToHex(n) {
return setDigit(Math.round(n).toString(16), 2);
}
function bound01(n, max) {
if (isOnePointZero(n)) {
n = "100%";
}
var processPercent = isPercentage(n);
n = Math.min(max, Math.max(0, parseFloat(n)));
// Automatically convert percentage into number
if (processPercent) {
n = parseInt(n * max, 10) / 100;
}
// Handle floating point rounding errors
if (Math.abs(n - max) < 0.000001) {
return 1;
}
// Convert into [0, 1] range if it isn't already
return n % max / parseFloat(max);
}
function rgbToHsl(r, g, b) {
r = bound01(r, 255);
g = bound01(g, 255);
b = bound01(b, 255);
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h,
s,
l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return { h: h, s: s, l: l };
}
function hslToRgb(h, s, l) {
var r = void 0,
g = void 0,
b = void 0;
h = bound01(h, 360);
s = bound01(s, 100);
l = bound01(l, 100);
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
if (s === 0) {
r = g = b = l; // achromatic
} else {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return { r: r * 255, g: g * 255, b: b * 255 };
}
return new function (_color) {
this._originalValue = _color;
_color = convertObject(_color);
this.r = _color.r;
this.g = _color.g;
this.b = _color.b;
this.a = _color.a || 1;
this._format = _color.format;
this._hex = convertToHex(this.r) + convertToHex(this.g) + convertToHex(this.b);
this.getHexValue = function () {
return this._hex;
};
this.lighten = function (amount) {
amount = amount === 0 ? 0 : amount || 10;
var hsl = rgbToHsl(this.r, this.g, this.b),
rgb = {};
hsl.l += amount / 100;
hsl.l = Math.min(1, Math.max(0, hsl.l));
hsl.h = hsl.h * 360;
rgb = hslToRgb(hsl.h, convertToPercentage(hsl.s), convertToPercentage(hsl.l));
return color('rgba(' + convertTo255(rgb.r) + ', ' + convertTo255(rgb.g) + ', ' + convertTo255(rgb.b) + ', ' + this.a + ')');
};
this.darken = function (amount) {
amount = amount === 0 ? 0 : amount || 10;
var hsl = rgbToHsl(this.r, this.g, this.b),
rgb = {};
hsl.l -= amount / 100;
hsl.l = Math.min(1, Math.max(0, hsl.l));
hsl.h = hsl.h * 360;
rgb = hslToRgb(hsl.h, convertToPercentage(hsl.s), convertToPercentage(hsl.l));
return color('rgba(' + convertTo255(rgb.r) + ', ' + convertTo255(rgb.g) + ', ' + convertTo255(rgb.b) + ', ' + this.a + ')');
};
this.getBrightness = function () {
return (this.r * 299 + this.g * 587 + this.b * 114) / 1000;
};
this.isDark = function () {
return this.getBrightness() < 128;
};
this.isLight = function () {
return !this.isDark();
};
this.getHsl = function () {
var hsl = rgbToHsl(this.r, this.g, this.b);
hsl.l = Math.min(1, Math.max(0, hsl.l));
hsl.h = hsl.h * 360;
return {
h: hsl.h,
s: hsl.s,
l: hsl.l
};
};
}(_hexColor);
}
return {
alert: alert,
each: each,
map: map,
search: search,
reduce: reduce,
reduceRight: reduceRight,
filter: filter,
sum: sum,
avg: avg,
toJson: toJson,
parseJson: parseJson,
first: first,
last: last,
deepCopy: deepCopy,
left: left,
right: right,
getType: getType,
isWindow: isWindow,
isElement: isElement,
isObject: isObject,
isArray: isArray,
isFunction: isFunction,
isString: isString,
isNumber: isNumber,
isNodelist: isNodelist,
isUndefined: isUndefined,
isNothing: isNothing,
setCookie: setCookie,
getCookie: getCookie,
camelCase: camelCase,
snakeCase: snakeCase,
number: number,
toArray: toArray,
merge: merge,
param: param,
error: error,
date: date,
dday: dday,
daysOfMonth: daysOfMonth,
weeksOfMonth: weeksOfMonth,
setDigit: setDigit,
times: times,
findParentNode: findParentNode,
cssNumber: cssNumber,
css: css,
isDate: isDate,
isDateFormat: isDateFormat,
stopEvent: stopEvent,
selectRange: selectRange,
debounce: debounce,
throttle: throttle,
escapeHtml: escapeHtml,
unescapeHtml: unescapeHtml,
string: string,
color: color
};
}();
if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === "object" && _typeof(module.exports) === "object") {
module.exports = ax5;
} else {
root.ax5 = function () {
return ax5;
}(); // ax5.ui에 연결
}
}).call(typeof window !== "undefined" ? window : undefined);
ax5.def = {};
ax5.info.errorMsg["ax5dialog"] = {
"501": "Duplicate call error"
};
ax5.info.errorMsg["ax5picker"] = {
"401": "Can not find target element",
"402": "Can not find boundID",
"501": "Can not find content key"
};
ax5.info.errorMsg["single-uploader"] = {
"460": "There are no files to be uploaded.",
"461": "There is no uploaded files."
};
ax5.info.errorMsg["ax5calendar"] = {
"401": "Can not find target element"
};
ax5.info.errorMsg["ax5formatter"] = {
"401": "Can not find target element",
"402": "Can not find boundID",
"501": "Can not find pattern"
};
ax5.info.errorMsg["ax5menu"] = {
"501": "Can not find menu item"
};
ax5.info.errorMsg["ax5select"] = {
"401": "Can not find target element",
"402": "Can not find boundID",
"501": "Can not find option"
};
ax5.info.errorMsg["ax5combobox"] = {
"401": "Can not find target element",
"402": "Can not find boundID",
"501": "Can not find option"
};
// 필수 Ployfill 확장 구문
(function () {
'use strict';
var root = this,
re_trim = /^\s*|\s*$/g;
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = function () {
var hwp = Object.prototype.hasOwnProperty,
hdeb = !{ toString: null }.propertyIsEnumerable('toString'),
de = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'],
del = de.length;
return function (obj) {
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' && (typeof obj !== 'function' || obj === null)) throw new TypeError('type err');
var r = [],
prop,
i;
for (prop in obj) {
if (hwp.call(obj, prop)) r.push(prop);
}if (hdeb) {
for (i = 0; i < del; i++) {
if (hwp.call(obj, de[i])) r.push(de[i]);
}
}
return r;
};
}();
}
// ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] )
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (fun /*, thisp */) {
if (this === void 0 || this === null) {
throw TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function") {
throw TypeError();
}
var thisp = arguments[1],
i;
for (i = 0; i < len; i++) {
if (i in t) {
fun.call(thisp, t[i], i, t);
}
}
};
}
// ES5 15.3.4.5 Function.prototype.bind ( thisArg [, arg1 [, arg2, ... ]] )
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
if (!Function.prototype.bind) {
Function.prototype.bind = function (o) {
if (typeof this !== 'function') {
throw TypeError("function");
}
var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
bound = function bound() {
return self.apply(this instanceof nop ? this : o, args.concat(slice.call(arguments)));
};
function nop() {}
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
}
/*global document */
/**
* define document.querySelector & document.querySelectorAll for IE7
*
* A not very fast but small hack. The approach is taken from
* http://weblogs.asp.net/bleroy/archive/2009/08/31/queryselectorall-on-old-ie-versions-something-that-doesn-t-work.aspx
*
*/
(function () {
if (document.querySelectorAll || document.querySelector) {
return;
}
if (!document.createStyleSheet) return;
var style = document.createStyleSheet(),
select = function select(selector, maxCount) {
var all = document.all,
l = all.length,
i,
resultSet = [];
style.addRule(selector, "foo:bar");
for (i = 0; i < l; i += 1) {
if (all[i].currentStyle.foo === "bar") {
resultSet.push(all[i]);
if (resultSet.length > maxCount) {
break;
}
}
}
style.removeRule(0);
return resultSet;
};
document.querySelectorAll = function (selector) {
return select(selector, Infinity);
};
document.querySelector = function (selector) {
return select(selector, 1)[0] || null;
};
})();
if (!String.prototype.trim) {
(function () {
String.prototype.trim = function () {
return this.replace(re_trim, '');
};
})();
}
if (!window.JSON) {
window.JSON = {
parse: function parse(sJSON) {
return new Function('', 'return ' + sJSON)();
},
stringify: function () {
var r = /["]/g,
_f;
return _f = function f(vContent) {
var result, i, j;
switch (result = typeof vContent === 'undefined' ? 'undefined' : _typeof(vContent)) {
case 'string':
return '"' + vContent.replace(r, '\\"') + '"';
case 'number':
case 'boolean':
return vContent.toString();
case 'undefined':
return 'undefined';
case 'function':
return '""';
case 'object':
if (!vContent) return 'null';
result = '';
if (vContent.splice) {
for (i = 0, j = vContent.length; i < j; i++) {
result += ',' + _f(vContent[i]);
}return '[' + result.substr(1) + ']';
} else {
for (i in vContent) {
if (vContent.hasOwnProperty(i) && vContent[i] !== undefined && typeof vContent[i] != 'function') result += ',"' + i + '":' + _f(vContent[i]);
}return '{' + result.substr(1) + '}';
}
}
};
}()
};
}
// splice ie8 <= polyfill
(function () {
if (!document.documentMode || document.documentMode >= 9) return false;
var _splice = Array.prototype.splice;
Array.prototype.splice = function () {
var args = Array.prototype.slice.call(arguments);
if (typeof args[1] === "undefined") args[1] = this.length - args[0];
return _splice.apply(this, args);
};
})();
/**
* Shim for "fixing" IE's lack of support (IE < 9) for applying slice
* on host objects like NamedNodeMap, NodeList, and HTMLCollection
* (technically, since host objects have been implementation-dependent,
* at least before ES6, IE hasn't needed to work this way).
* Also works on strings, fixes IE < 9 to allow an explicit undefined
* for the 2nd argument (as in Firefox), and prevents errors when
* called on other DOM objects.
*/
(function () {
'use strict';
var _slice = Array.prototype.slice;
try {
// Can't be used with DOM elements in IE < 9
_slice.call(document.documentElement);
} catch (e) {
// Fails in IE < 9
// This will work for genuine arrays, array-like objects,
// NamedNodeMap (attributes, entities, notations),
// NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
// and will not fail on other DOM objects (as do DOM elements in IE < 9)
Array.prototype.slice = function (begin, end) {
// IE < 9 gets unhappy with an undefined end argument
end = typeof end !== 'undefined' ? end : this.length;
// For native Array objects, we use the native slice function
if (Object.prototype.toString.call(this) === '[object Array]') {
return _slice.call(this, begin, end);
}
// For array like object we handle it ourselves.
var i,
cloned = [],
size,
len = this.length;
// Handle negative value for "begin"
var start = begin || 0;
start = start >= 0 ? start : Math.max(0, len + start);
// Handle negative value for "end"
var upTo = typeof end == 'number' ? Math.min(end, len) : len;
if (end < 0) {
upTo = len + end;
}
// Actual expected size of the slice
size = upTo - start;
if (size > 0) {
cloned = new Array(size);
if (this.charAt) {
for (i = 0; i < size; i++) {
cloned[i] = this.charAt(start + i);
}
} else {
for (i = 0; i < size; i++) {
cloned[i] = this[start + i];
}
}
}
return cloned;
};
}
})();
// Console-polyfill. MIT license. https://github.com/paulmillr/console-polyfill
// Make it safe to do console.log() always.
(function (con) {
var prop, method;
var empty = {};
var dummy = function dummy() {};
var properties = 'memory'.split(',');
var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
while (prop = properties.pop()) {
con[prop] = con[prop] || empty;
}while (method = methods.pop()) {
con[method] = con[method] || dummy;
}
})(window.console || {}); // Using `this` for web workers.
// Modernizr style test
if (!(window.webkitMatchMedia || window.mozMatchMedia || window.oMatchMedia || window.msMatchMedia || window.matchMedia)) {
var root = document.getElementsByTagName('html')[0];
root.className += ' no-matchmedia';
}
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
window.matchMedia || (window.matchMedia = function () {
"use strict";
// For browsers that support matchMedium api such as IE 9 and webkit
var styleMedia = window.styleMedia || window.media;
// For those that don't support matchMedium
if (!styleMedia) {
var style = document.createElement('style'),
script = document.getElementsByTagName('script')[0],
info = null;
style.type = 'text/css';
style.id = 'matchmediajs-test';
script.parentNode.insertBefore(style, script);
// 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
info = 'getComputedStyle' in window && window.getComputedStyle(style, null) || style.currentStyle;
styleMedia = {
matchMedium: function matchMedium(media) {
var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }';
// 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
if (style.styleSheet) {
style.styleSheet.cssText = text;
} else {
style.textContent = text;
}
// Test if media query is true or false
return info.width === '1px';
}
};
}
return function (media) {
return {
matches: styleMedia.matchMedium(media || 'all'),
media: media || 'all'
};
};
}());
/*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */
(function () {
// Bail out for browsers that have addListener support
if (window.matchMedia && window.matchMedia('all').addListener) {
return false;
}
var localMatchMedia = window.matchMedia,
hasMediaQueries = localMatchMedia('only all').matches,
isListening = false,
timeoutID = 0,
// setTimeout for debouncing 'handleChange'
queries = [],
// Contains each 'mql' and associated 'listeners' if 'addListener' is used
handleChange = function handleChange(evt) {
// Debounce
clearTimeout(timeoutID);
timeoutID = setTimeout(function () {
for (var i = 0, il = queries.length; i < il; i++) {
var mql = queries[i].mql,
listeners = queries[i].listeners || [],
matches = localMatchMedia(mql.media).matches;
// Update mql.matches value and call listeners
// Fire listeners only if transitioning to or from matched state
if (matches !== mql.matches) {
mql.matches = matches;
for (var j = 0, jl = listeners.length; j < jl; j++) {
listeners[j].call(window, mql);
}
}
}
}, 30);
};
window.matchMedia = function (media) {
var mql = localMatchMedia(media),
listeners = [],
index = 0;
mql.addListener = function (listener) {
// Changes would not occur to css media type so return now (Affects IE <= 8)
if (!hasMediaQueries) {
return;
}
// Set up 'resize' listener for browsers that support CSS3 media queries (Not for IE <= 8)
// There should only ever be 1 resize listener running for performance
if (!isListening) {
isListening = true;
window.addEventListener('resize', handleChange, true);
}
// Push object only if it has not been pushed already
if (index === 0) {
index = queries.push({
mql: mql,
listeners: listeners
});
}
listeners.push(listener);
};
mql.removeListener = function (listener) {
for (var i = 0, il = listeners.length; i < il; i++) {
if (listeners[i] === listener) {
listeners.splice(i, 1);
}
}
};
return mql;
};
})();
// extend innerWidth ..
var html = document.getElementsByTagName('html')[0];
var body = document.getElementsByTagName('body')[0];
/*
if (!window.innerWidth) window.innerWidth = html.clientWidth;
if (!window.innerHeight) window.innerHeight = html.clientHeight;
if (!window.scrollX) window.scrollX = window.pageXOffset || html.scrollLeft;
if (!window.scrollY) window.scrollY = window.pageYOffset || html.scrollTop;
*/
}).call(window);
/**
* Refer to this by {@link ax5}.
* @namespace ax5.ui
*/
/**
* @class ax5.ui.root
* @classdesc ax5 ui class
* @author tom@axisj.com
* @example
* ```
* var myui = new ax5.ui.root();
* ```
*/
ax5.ui = function () {
function axUi() {
this.config = {};
this.name = "root";
/**
* 클래스의 속성 정의 메소드 속성 확장후에 내부에 init 함수를 호출합니다.
* @method ax5.ui.root.setConfig
* @param {Object} config - 클래스 속성값
* @param {Boolean} [callInit=true] - init 함수 호출 여부
* @returns {ax5.ui.axUi}
* @example
* ```
* var myui = new ax5.ui.root();
* myui.setConfig({
* id:"abcd"
* });
* ```
*/
this.setConfig = function (cfg, callInit) {
jQuery.extend(true, this.config, cfg);
if (typeof callInit == "undefined" || callInit === true) {
this.init();
}
return this;
};
this.init = function () {
console.log(this.config);
};
this.bindWindowResize = function (callBack) {
setTimeout(function () {
jQuery(window).resize(function () {
if (this.bindWindowResize__) clearTimeout(this.bindWindowResize__);
this.bindWindowResize__ = setTimeout(function () {
callBack.call(this);
}.bind(this), 10);
}.bind(this));
}.bind(this), 100);
};
this.stopEvent = function (e) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble = true;
return false;
};
this.toString = function () {
return this.name + '@' + this.version;
};
// instance init
this.main = function () {}.apply(this, arguments);
}
/**
* @method ax5.ui.addClass
* @param {Object} config
* @param {String} config.className - name of Class
* @param {Object} [config.classStore=ax5.ui] - 클래스가 저장될 경로
* @param {Function} [config.superClass=ax5.ui.root]
* @param {Function} cls - Class Function
*/
function addClass(config, cls) {
if (!config || !config.className) throw 'invalid call';
var classStore = config.classStore ? config.classStore : ax5.ui;
if (!classStore) throw 'invalid classStore';
// make ui definition variable
ax5.def[config.className] = {
version: ax5.info.version
};
var factory = function factory(cls, arg) {
switch (arg.length) {
case 0:
return new cls();
break;
case 1:
return new cls(arg[0]);
break;
case 2:
return new cls(arg[0], arg[1]);
break;
case 3:
return new cls(arg[0], arg[1], arg[2]);
break;
}
};
var initInstance = function initInstance(name, version, instance) {
instance.name = name;
instance.version = version;
instance.instanceId = ax5.getGuid();
return instance;
};
var initPrototype = function initPrototype(cls) {
var superClass = config.superClass ? config.superClass : ax5.ui.root;
if (!ax5.util.isFunction(superClass)) throw 'invalid superClass';
superClass.call(this); // 부모호출
cls.prototype = new superClass(); // 상속
};
var wrapper = function wrapper() {
if (!this || !(this instanceof wrapper)) throw 'invalid call';
var instance = factory(cls, arguments);
return initInstance(config.className, config.version || "", instance);
};
initPrototype.call(this, cls);
classStore[config.className] = wrapper;
}
return {
root: axUi,
addClass: addClass
};
}();
/*!
* mustache.js - Logic-less {{mustache}} templates with JavaScript
* http://github.com/janl/mustache.js
* https://github.com/thomasJang/mustache.js -- imporove some variables
*/
(function defineMustache(global, factory) {
factory(global.mustache = {});
})(window.ax5, function mustacheFactory(mustache) {
var objectToString = Object.prototype.toString;
var isArray = Array.isArray || function isArrayPolyfill(object) {
return objectToString.call(object) === '[object Array]';
};
function isFunction(object) {
return typeof object === 'function';
}
/**
* More correct typeof string handling array
* which normally returns typeof 'object'
*/
function typeStr(obj) {
return isArray(obj) ? 'array' : typeof obj === 'undefined' ? 'undefined' : _typeof(obj);
}
function escapeRegExp(string) {
return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
}
/**
* Null safe way of checking whether or not an object,
* including its prototype, has a given property
*/
function hasProperty(obj, propName) {
return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && propName in obj;
}
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
// See https://github.com/janl/mustache.js/issues/189
var regExpTest = RegExp.prototype.test;
function testRegExp(re, string) {
return regExpTest.call(re, string);
}
var nonSpaceRe = /\S/;
function isWhitespace(string) {
return !testRegExp(nonSpaceRe, string);
}
var entityMap = {
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/'
};
function escapeHtml(string) {
return String(string).replace(/[&<>"'\/]/g, function fromEntityMap(s) {
return entityMap[s];
});
}
var whiteRe = /\s*/;
var spaceRe = /\s+/;
var equalsRe = /\s*=/;
var curlyRe = /\s*\}/;
var tagRe = /#|\^|\/|>|\{|&|=|!/;
/**
* Breaks up the given `template` string into a tree of tokens. If the `tags`
* argument is given here it must be an array with two string values: the
* opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
* course, the default is to use mustaches (i.e. mustache.tags).
*
* A token is an array with at least 4 elements. The first element is the
* mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
* did not contain a symbol (i.e. {{myValue}}) this element is "name". For
* all text that appears outside a symbol this element is "text".
*
* The second element of a token is its "value". For mustache tags this is
* whatever else was inside the tag besides the opening symbol. For text tokens
* this is the text itself.
*
* The third and fourth elements of the token are the start and end indices,
* respectively, of the token in the original template.
*
* Tokens that are the root node of a subtree contain two more elements: 1) an
* array of tokens in the subtree and 2) the index in the original template at
* which the closing tag for that section begins.
*/
function parseTemplate(template, tags) {
if (!template) return [];
var sections = []; // Stack to hold section tokens
var tokens = []; // Buffer to hold the tokens
var spaces = []; // Indices of whitespace tokens on the current line
var hasTag = false; // Is there a {{tag}} on the current line?
var nonSpace = false; // Is there a non-space char on the current line?
// Strips all whitespace tokens array for the current line
// if there was a {{#tag}} on it and otherwise only space.
function stripSpace() {
if (hasTag && !nonSpace) {
while (spaces.length) {
delete tokens[spaces.pop()];
}
} else {
spaces = [];
}
hasTag = false;
nonSpace = false;
}
var openingTagRe, closingTagRe, closingCurlyRe;
function compileTags(tagsToCompile) {
if (typeof tagsToCompile === 'string') tagsToCompile = tagsToCompile.split(spaceRe, 2);
if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) throw new Error('Invalid tags: ' + tagsToCompile);
openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
}
compileTags(tags || mustache.tags);
var scanner = new Scanner(template);
var start, type, value, chr, token, openSection;
while (!scanner.eos()) {
start = scanner.pos;
// Match any text between tags.
value = scanner.scanUntil(openingTagRe);
if (value) {
for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
chr = value.charAt(i);
if (isWhitespace(chr)) {
spaces.push(tokens.length);
} else {
nonSpace = true;
}
tokens.push(['text', chr, start, start + 1]);
start += 1;
// Check for whitespace on the current line.
if (chr === '\n') stripSpace();
}
}
// Match the opening tag.
if (!scanner.scan(openingTagRe)) break;
hasTag = true;
// Get the tag type.
type = scanner.scan(tagRe) || 'name';
scanner.scan(whiteRe);
// Get the tag value.
if (type === '=') {
value = scanner.scanUntil(equalsRe);
scanner.scan(equalsRe);
scanner.scanUntil(closingTagRe);
} else if (type === '{') {
value = scanner.scanUntil(closingCurlyRe);
scanner.scan(curlyRe);
scanner.scanUntil(closingTagRe);
type = '&';
} else {
value = scanner.scanUntil(closingTagRe);
}
// Match the closing tag.
if (!scanner.scan(closingTagRe)) throw new Error('Unclosed tag at ' + scanner.pos);
token = [type, value, start, scanner.pos];
tokens.push(token);
if (type === '#' || type === '^') {
sections.push(token);
} else if (type === '/') {
// Check section nesting.
openSection = sections.pop();
if (!openSection) throw new Error('Unopened section "' + value + '" at ' + start);
if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
} else if (type === 'name' || type === '{' || type === '&') {
nonSpace = true;
} else if (type === '=') {
// Set the tags for the next time around.
compileTags(value);
}
}
// Make sure there are no open sections when we're done.
openSection = sections.pop();
if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
return nestTokens(squashTokens(tokens));
}
/**
* Combines the values of consecutive text tokens in the given `tokens` array
* to a single token.
*/
function squashTokens(tokens) {
var squashedTokens = [];
var token, lastToken;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
token = tokens[i];
if (token) {
if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
lastToken[1] += token[1];
lastToken[3] = token[3];
} else {
squashedTokens.push(token);
lastToken = token;
}
}
}
return squashedTokens;
}
/**
* Forms the given array of `tokens` into a nested tree structure where
* tokens that represent a section have two additional items: 1) an array of
* all tokens that appear in that section and 2) the index in the original
* template that represents the end of that section.
*/
function nestTokens(tokens) {
var nestedTokens = [];
var collector = nestedTokens;
var sections = [];
var token, section;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
token = tokens[i];
switch (token[0]) {
case '#':
case '^':
collector.push(token);
sections.push(token);
collector = token[4] = [];
break;
case '/':
section = sections.pop();
section[5] = token[2];
collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
break;
default:
collector.push(token);
}
}
return nestedTokens;
}
/**
* A simple string scanner that is used by the template parser to find
* tokens in template strings.
*/
function Scanner(string) {
this.string = string;
this.tail = string;
this.pos = 0;
}
/**
* Returns `true` if the tail is empty (end of string).
*/
Scanner.prototype.eos = function eos() {
return this.tail === '';
};
/**
* Tries to match the given regular expression at the current position.
* Returns the matched text if it can match, the empty string otherwise.
*/
Scanner.prototype.scan = function scan(re) {
var match = this.tail.match(re);
if (!match || match.index !== 0) return '';
var string = match[0];
this.tail = this.tail.substring(string.length);
this.pos += string.length;
return string;
};
/**
* Skips all text until the given regular expression can be matched. Returns
* the skipped string, which is the entire tail if no match can be made.
*/
Scanner.prototype.scanUntil = function scanUntil(re) {
var index = this.tail.search(re),
match;
switch (index) {
case -1:
match = this.tail;
this.tail = '';
break;
case 0:
match = '';
break;
default:
match = this.tail.substring(0, index);
this.tail = this.tail.substring(index);
}
this.pos += match.length;
return match;
};
/**
* Represents a rendering context by wrapping a view object and
* maintaining a reference to the parent context.
*/
function Context(view, parentContext) {
this.view = view;
this.cache = {
'.': this.view,
'@each': function each() {
var returns = [];
for (var k in this) {
returns.push({ '@key': k, '@value': this[k] });
}
return returns;
}
};
this.parent = parentContext;
}
/**
* Creates a new context using the given view with this context
* as the parent.
*/
Context.prototype.push = function push(view) {
return new Context(view, this);
};
/**
* Returns the value of the given name in this context, traversing
* up the context hierarchy if the value is absent in this context's view.
*/
Context.prototype.lookup = function lookup(name) {
var cache = this.cache;
var value;
if (cache.hasOwnProperty(name)) {
value = cache[name];
} else {
var context = this,
names,
index,
lookupHit = false;
while (context) {
if (name.indexOf('.') > 0) {
value = context.view;
names = name.split('.');
index = 0;
/**
* Using the dot notion path in `name`, we descend through the
* nested objects.
*
* To be certain that the lookup has been successful, we have to
* check if the last object in the path actually has the property
* we are looking for. We store the result in `lookupHit`.
*
* This is specially necessary for when the value has been set to
* `undefined` and we want to avoid looking up parent contexts.
**/
while (value != null && index < names.length) {
if (index === names.length - 1) lookupHit = hasProperty(value, names[index]);
value = value[names[index++]];
}
} else {
value = context.view[name];
lookupHit = hasProperty(context.view, name);
}
if (lookupHit) break;
context = context.parent;
}
cache[name] = value;
}
if (isFunction(value)) value = value.call(this.view);
return value;
};
/**
* A Writer knows how to take a stream of tokens and render them to a
* string, given a context. It also maintains a cache of templates to
* avoid the need to parse the same template twice.
*/
function Writer() {
this.cache = {};
}
/**
* Clears all cached templates in this writer.
*/
Writer.prototype.clearCache = function clearCache() {
this.cache = {};
};
/**
* Parses and caches the given `template` and returns the array of tokens
* that is generated from the parse.
*/
Writer.prototype.parse = function parse(template, tags) {
var cache = this.cache;
var tokens = cache[template];
if (tokens == null) tokens = cache[template] = parseTemplate(template, tags);
return tokens;
};
/**
* High-level method that is used to render the given `template` with
* the given `view`.
*
* The optional `partials` argument may be an object that contains the
* names and templates of partials that are used in the template. It may
* also be a function that is used to load partial templates on the fly
* that takes a single argument: the name of the partial.
*/
Writer.prototype.render = function render(template, view, partials) {
var tokens = this.parse(template);
var context = view instanceof Context ? view : new Context(view);
return this.renderTokens(tokens, context, partials, template);
};
/**
* Low-level method that renders the given array of `tokens` using
* the given `context` and `partials`.
*
* Note: The `originalTemplate` is only ever used to extract the portion
* of the original template that was contained in a higher-order section.
* If the template doesn't use higher-order sections, this argument may
* be omitted.
*/
Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate) {
var buffer = '';
var token, symbol, value;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
value = undefined;
token = tokens[i];
symbol = token[0];
if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);else if (symbol === '&') value = this.unescapedValue(token, context);else if (symbol === 'name') value = this.escapedValue(token, context);else if (symbol === 'text') value = this.rawValue(token);
if (value !== undefined) buffer += value;
}
return buffer;
};
Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate) {
var self = this;
var buffer = '';
var value = context.lookup(token[1]);
// This function is used to render an arbitrary template
// in the current context by higher-order sections.
function subRender(template) {
return self.render(template, context, partials);
}
if (!value) return;
if (isArray(value)) {
for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
if (value[j]) {
if (_typeof(value[j]) === 'object') {
value[j]['@i'] = j;
value[j]['@first'] = j === 0;
}
buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
}
}
} else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' || typeof value === 'string' || typeof value === 'number') {
buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
} else if (isFunction(value)) {
if (typeof originalTemplate !== 'string') throw new Error('Cannot use higher-order sections without the original template');
// Extract the portion of the original template that the section contains.
value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
if (value != null) buffer += value;
} else {
buffer += this.renderTokens(token[4], context, partials, originalTemplate);
}
return buffer;
};
Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate) {
var value = context.lookup(token[1]);
// Use JavaScript's definition of falsy. Include empty arrays.
// See https://github.com/janl/mustache.js/issues/186
if (!value || isArray(value) && value.length === 0) return this.renderTokens(token[4], context, partials, originalTemplate);
};
Writer.prototype.renderPartial = function renderPartial(token, context, partials) {
if (!partials) return;
var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
if (value != null) return this.renderTokens(this.parse(value), context, partials, value);
};
Writer.prototype.unescapedValue = function unescapedValue(token, context) {
var value = context.lookup(token[1]);
if (value != null) return value;
};
Writer.prototype.escapedValue = function escapedValue(token, context) {
var value = context.lookup(token[1]);
if (value != null) return mustache.escape(value);
};
Writer.prototype.rawValue = function rawValue(token) {
return token[1];
};
mustache.name = 'mustache.js';
mustache.version = '2.1.3';
mustache.tags = ['{{', '}}'];
// All high-level mustache.* functions use this writer.
var defaultWriter = new Writer();
/**
* Clears all cached templates in the default writer.
*/
mustache.clearCache = function clearCache() {
return defaultWriter.clearCache();
};
/**
* Parses and caches the given template in the default writer and returns the
* array of tokens it contains. Doing this ahead of time avoids the need to
* parse templates on the fly as they are rendered.
*/
mustache.parse = function parse(template, tags) {
return defaultWriter.parse(template, tags);
};
/**
* Renders the `template` with the given `view` and `partials` using the
* default writer.
*/
mustache.render = function render(template, view, partials) {
if (typeof template !== 'string') {
throw new TypeError('Invalid template! Template should be a "string" ' + 'but "' + typeStr(template) + '" was given as the first ' + 'argument for mustache#render(template, view, partials)');
}
return defaultWriter.render(template, view, partials);
};
// This is here for backwards compatibility with 0.4.x.,
/*eslint-disable */ // eslint wants camel cased function name
mustache.to_html = function to_html(template, view, partials, send) {
/*eslint-enable*/
var result = mustache.render(template, view, partials);
if (isFunction(send)) {
send(result);
} else {
return result;
}
};
// Export the escaping function so that the user may override it.
// See https://github.com/janl/mustache.js/issues/244
mustache.escape = escapeHtml;
// Export these mainly for testing, but also for advanced usage.
mustache.Scanner = Scanner;
mustache.Context = Context;
mustache.Writer = Writer;
});