/** * Jindo2 Framework * @version 1.0.5 */ /** * Core object * */ if (typeof window != "undefined" && typeof window.nhn == "undefined") { window.nhn = new Object; } /** * 지정된 id 를 가지는 객체를 반환한다. * argument를 복수개로 지정하면 배열로 객체를 반환하며, * 아이디에 해당하는 객체가 존재하지 않으면 null 을 반환한다. * 또한 "" 과 같은 형식의 문자열을 입력하면 tagName을 가지는 객체를 생성한다. * @id core.$ * @param {String} 객체의 아이디(복수개 가능) * @return element */ function $(sID/*, id1, id2*/) { var ret = new Array; var el = null; var reg = /^<([a-z]+|h[1-5])>$/i; for(var i=0; i < arguments.length; i++) { el = arguments[i]; if (typeof el == "string") { if (reg.test(el)) { el = document.createElement(RegExp.$1); } else { el = document.getElementById(el); } } if (el) ret[ret.length] = el; } return ret.length?((arguments.length>1)?ret:ret[0]):null; } /** * 클래스 타입을 정의한다. 생성자는 $init 으로 정의한다. * @id core.$Class * @param {object} 클래스 정의 object * @return {class} 클래스 타입 */ function $Class(oDef) { function typeClass() { var t = this; var a = []; while(typeof t.$super != "undefined") { t.$super.$this = this; if (typeof t.$super.$init == "function") a[a.length] = t; t = t.$super; } for(var i=a.length-1; i > -1; i--) a[i].$super.$init.apply(a[i].$super, arguments); if (typeof this.$init == "function") this.$init.apply(this,arguments); } if (typeof oDef.$static != "undefined") { var i=0, x; for(x in oDef) x=="$static"||i++; for(x in oDef.$static) typeClass[x] = oDef.$static[x]; if (!i) return oDef.$static; delete oDef.$static; } typeClass.prototype = oDef; typeClass.prototype.constructor = typeClass; typeClass.extend = $Class.extend; return typeClass; } /** * 클래스를 상속한다. * 상속된 클래스에서 this.$super.method 로 상위 메소드에 접근할 수도 있으나, * this.$super.$super.method 와 같이 한 단계 이상의 부모 클래스에는 접근할 수 없다. * @id core.$Class.extend * @import core.$Class * @param {class} 수퍼 클래스 객체 * @return {class} 확장된 클래스 타입 */ $Class.extend = function(superClass) { this.prototype.$super = new Object; var superFunc = function(m, func) { return function() { var r; var f = this.$this[m]; var t = this.$this; t[m] = func; r = t[m].apply(t, arguments); t[m] = f; return r; }; }; for(var x in superClass.prototype) { if (typeof this.prototype[x] == "undefined" && x !="$init") this.prototype[x] = superClass.prototype[x]; if (typeof superClass.prototype[x] == "function") { this.prototype.$super[x] = superFunc(x, superClass.prototype[x]); } else { this.prototype.$super[x] = superClass.prototype[x]; } } // inherit static methods of parent for(var x in superClass) { if (x == "prototype") continue; this[x] = superClass[x]; } return this; }; ///// /** * Agent 객체를 반환한다. Agent 객체는 브라우저와 OS에 대한 정보를 알 수 있도록 한다. * @id core.$Agent */ function $Agent() { var cl = arguments.callee; var cached = cl._cached; if (cl._cached) return cl._cached; if (!(this instanceof cl)) return new cl; if (typeof cl._cached == "undefined") cl._cached = this; } /** * 웹브라우저에 대한 정보 객체를 반환한다. * @id core.$Agent.navigator * @return {TypeNavigatorInfo} 웹브라우저 정보 객체 */ $Agent.prototype.navigator = function() { var info = new Object; var ver = -1; var u = navigator.userAgent; var v = navigator.vendor || ""; function f(s,h){ return ((h||"").indexOf(s) > -1) }; info.opera = (typeof window.opera != "undefined") || f("Opera",u); info.ie = !info.opera && f("MSIE",u); info.chrome = f("Chrome",u); info.safari = !info.chrome && f("Apple",v); info.mozilla = f("Gecko",u) && !info.safari && !info.chrome; info.firefox = f("Firefox",u); info.camino = f("Camino",v); info.netscape = f("Netscape",u); info.omniweb = f("OmniWeb",u); info.icab = f("iCab",v); info.konqueror = f("KDE",v); try { if (info.ie) { ver = u.match(/(?:MSIE) ([0-9.]+)/)[1]; } else if (info.firefox||info.opera||info.omniweb) { ver = u.match(/(?:Firefox|Opera|OmniWeb)\/([0-9.]+)/)[1]; } else if (info.mozilla) { ver = u.match(/rv:([0-9.]+)/)[1]; } else if (info.safari) { ver = parseFloat(u.match(/Safari\/([0-9.]+)/)[1]); if (ver == 100) { ver = 1.1; } else { ver = [1.0,1.2,-1,1.3,2.0,3.0][Math.floor(ver/100)]; } } else if (info.icab) { ver = u.match(/iCab[ \/]([0-9.]+)/)[1]; } else if (info.chrome) { ver = u.match(/Chrome[ \/]([0-9.]+)/)[1]; } info.version = parseFloat(ver); if (isNaN(info.version)) info.version = -1; } catch(e) { info.version = -1; } $Agent.prototype.navigator = function() { return info; }; return info; }; /** * OS에 대한 정보객체를 반환한다. * @id core.$Agent.os * @return {TypeOSInfo} OS 정보 객체 */ $Agent.prototype.os = function() { var info = new Object; var u = navigator.userAgent; var p = navigator.platform; var f = function(s,h){ return (h.indexOf(s) > -1) }; info.win = f("Win",p); info.mac = f("Mac",p); info.linux = f("Linux",p); info.win2000 = info.win && (f("NT 5.0",p) || f("2000",p)); info.winxp = info.win && (f("NT 5.1",p) || f("Win32",p)); info.xpsp2 = info.winxp && (f("SV1",u) || f("MSIE 7",u)); info.vista = f("NT 6.0",p); $Agent.prototype.os = function() { return info; }; return info; }; /** * Flash에 대한 정보객체를 반환한다. * @id core.$Agent.flash * @return {TypeFlashInfo} Flash 정보 객체 */ $Agent.prototype.flash = function() { var info = new Object; var p = navigator.plugins; var m = navigator.mimeTypes; var f = null; info.installed = false; info.version = -1; if (typeof p != "undefined" && p.length) { f = p["Shockwave Flash"]; if (f) { info.installed = true; if (f.description) { info.version = parseFloat(f.description.match(/[0-9.]+/)[0]); } } if (p["Shockwave Flash 2.0"]) { info.installed = true; info.version = 2; } } else if (typeof m != "undefined" && m.length) { f = m["application/x-shockwave-flash"]; info.installed = (f && f.enabledPlugin); } else { for(var i=9; i > 1; i--) { try { f = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i); info.installed = true; info.version = i; break; } catch(e) {} } } $Agent.prototype.info = function() { return info; }; return info; }; /** * SilverLight에 대한 정보객체를 반환한다. * @id core.$Agent.silverlight */ $Agent.prototype.silverlight = function() { var info = new Object; var p = navigator.plugins; var s = null; info.installed = false; info.version = -1; if (typeof p != "undefined" && p.length) { s = p["Silverlight Plug-In"]; if (s) { info.installed = true; } } else { try { s = new ActiveXObject("AgControl.AgControl"); info.installed = true; } catch(e) {} } $Agent.prototype.silverlight = function() { return info; }; return info; }; /** * 주어진 원소를 가진 배열 객체를 만든다. * @id core.$A * @import core.$A.toArray * @param {array} 배열 혹은 배열에 준하는 컬렉션 타입 * @return {$A} */ function $A(array) { var cl = arguments.callee; if (typeof array == "undefined") array = []; if (array instanceof cl) return array; if (!(this instanceof cl)) return new cl(array); this._array = []; for(var i=0; i < array.length; i++) { this._array[this._array.length] = array[i]; } }; $A.prototype.toString = function() { return this._array.toString(); }; /** * 배열의 크기를 반환한다 * @id core.$A.length * @return Number 배열의 크기 * @ */ $A.prototype.length = function(len, elem) { if (typeof len == "number") { var l = this._array.length; this._array.length = len; if (typeof elem != "undefined") { for(var i=l; i < len; i++) { this._array[i] = elem; } } return this; } else { return this._array.length; } }; /** * 주어진 원소가 존재하는지 검사한다. 존재하면 true를, 그렇지 않으면 false를 반환한다 * @id core.$A.has * @param {void} 검색할 값 * @return Boolean * @import core.$A.indexOf */ $A.prototype.has = function(any) { return (this.indexOf(any) > -1); }; /** * 주어진 원소가 배열에 몇 번째 요소로서 존재하는지 반환한다. * 배열의 인덱스는 0부터 시작한다. 해당 원소가 존재하지 않으면 -1 을 반환한다. * @id core.$A.indexOf * @param {void} 검색할 값 * @return {Number} 검색결과 인덱스 번호 */ $A.prototype.indexOf = function(any) { if (typeof this._array.indexOf != 'undefined') return this._array.indexOf(any); for(var i=0; i < this._array.length; i++) { if (this._array[i] == any) return i; } return -1; }; /* * JavaScript 배열 객체를 반환한다 * @id core.$A.$value * @return {Array} JavaScript 배열 객체 */ $A.prototype.$value = function() { return this._array; }; /** * 배열 객체에 엘리먼트를 추가한다. * @id core.$A.push * @param {void} 추가할 엘리먼트(복수개 가능) * @return {Number} 엘리먼트를 추가한 후의 배열 객체 크기 */ $A.prototype.push = function(element1/*, ...*/) { return this._array.push.apply(this._array, $A(arguments).$value()); }; /** * 배열의 마지막 엘리먼트를 제거하고 제거된 엘리먼트를 반환한다. * @id core.$A.pop * @return {void} 제거된 엘리먼트 */ $A.prototype.pop = function() { return this._array.pop(); }; /** * 배열의 첫 엘리먼트를 제거하고 제거된 엘리먼트를 반환한다. * @id core.$A.shift * @return {void} 제거된 엘리먼트 */ $A.prototype.shift = function() { return this._array.shift(); }; /** * 주어진 한 개 이상의 엘리먼트를 배열 앞부분에 삽입하고, 해당 배열의 바뀐 크기를 반환한다. * @id core.$A.unshift * @param {void} 추가할 엘리먼트(복수개 가능) * @return {Nmber} 엘리먼트를 추가한 후의 배열 객체 크기 */ $A.prototype.unshift = function(element1/*, ...*/) { this._array.unshift.apply(this._array, $A(arguments).$value()); return this._array.length; }; /** * 주어진 콜백함수를 배열의 각 요소에 실행한다. * @id core.$A.forEach * @import core.$A[Break, Continue] */ $A.prototype.forEach = function(callback, thisObject) { var arr = this._array; var errBreak = this.constructor.Break; var errContinue = this.constructor.Continue; function f(v,i,a) { try { callback.call(thisObject, v, i, a); } catch(e) { if (!(e instanceof errContinue)) throw e; } }; if (typeof this._array.forEach == "function") { try { this._array.forEach(f); } catch(e) { if (!(e instanceof errBreak)) throw e; } return this; } for(var i=0; i < arr.length; i++) { try { f(arr[i], i, arr); } catch(e) { if (e instanceof errBreak) break; throw e; } } return this; }; /** * 주어진 함수를 현재 객체의 모든 엘리먼트에 적용하고 현재 객체를 반환한다. * @id core.$A.map */ $A.prototype.map = function(callback, thisObject) { var arr = this._array; var errBreak = this.constructor.Break; var errContinue = this.constructor.Continue; function f(v,i,a) { try { return callback.call(thisObject, v, i, a); } catch(e) { if (e instanceof errContinue) return v; else throw e; } }; if (typeof this._array.map == "function") { try { this._array = this._array.map(f); } catch(e) { if(!(e instanceof errBreak)) throw e; } return this; } for(var i=0; i < this._array.length; i++) { try { arr[i] = f(arr[i], i, arr); } catch(e) { if (e instanceof errBreak) break; throw e; } } return this; }; /** * 주어진 콜백 함수를 만족시키는 요소만으로 만들어진 새로운 $A 배열을 반환한다. * 콜백 함수는 Boolean 값을 반환해야 한다. * @id core.$A.filter * @import core.$A.forEach */ $A.prototype.filter = function(callback, thisObject) { var ar = new Array; this.forEach(function(v,i,a) { if (callback.call(thisObject, v, i, a) === true) { ar[ar.length] = v; } }); return $A(ar); }; /** * 모든 배열의 원소가 주어진 콜백 함수를 만족시키는지를 검사한다. * 콜백함수는 Boolean 값을 반환해야 한다. * @id core.$A.every * @import core.$A.forEach */ $A.prototype.every = function(callback, thisObject) { if (typeof this._array.every != "undefined") return this._array.every(callback, thisObject); var result = true; this.forEach(function(v, i, a) { if (callback.call(thisObject, v, i, a) === false) { result = false; $A.Break(); } }); return result; }; /** * 주어진 콜백 함수를 만족시키는 배열의 원소가 존재하는지를 검사한다. * 모든 배열의 요소중에서 하나라도 콜백함수를 만족시키면 이 메소드는 true를 반환한다. * 콜백함수는 Boolean 값을 반환해야 한다. * @id core.$A.every * @import core.$A.forEach */ $A.prototype.some = function(callback, thisObject) { if (typeof this._array.some != "undefined") return this._array.some(callback, thisObject); var result = false; this.forEach(function(v, i, a) { if (callback.call(thisObject, v, i, a) === true) { result = true; $A.Break(); } }); return result; }; /** * 주어진 값을 제외한 새로운 $A배열을 반환한다 * @id core.$A.refuse * @import core.$A.filter */ $A.prototype.refuse = function(value) { var a = $A(arguments); return this.filter(function(v,i) { return !a.has(v) }); }; /** * 주어진 시작 인덱스와 끝 인덱스까지의 배열 요소로 이루어진 새로운 $A 배열을 반환한다. * @id core.$A.slice */ $A.prototype.slice = function(start, end) { var a = this._array.slice.call(this._array, start, end); return $A(a); }; /** * 특정 인덱스로부터 주어진 갯수만큼의 배열을 잘라서 반환한다. * @id core.$A.splice */ $A.prototype.splice = function(index, howMany/*, element*/) { var a = this._array.splice.apply(this._array, arguments); return $A(a); }; /** * 배열의 원소를 무작위적으로 섞는다. * @id core.$A.shuffle */ $A.prototype.shuffle = function() { this._array.sort(function(a,b){ return Math.random()>Math.random()?1:-1 }); return this; }; /** * 배열에서 중복되는 원소를 제거한다. * @id core.$A.unique */ $A.prototype.unique = function() { var a = this._array, b = [], l = a.length; var i, j; // 중복되는 원소 제거 for(i = 0; i < l; i++) { for(j = 0; j < b.length; j++) { if (a[i] == b[j]) break; } if (j >= b.length) b[j] = a[i]; } this._array = b; return this; }; /** * 배열 요소를 거꾸로 정렬한다. * @id core.$A.reverse */ $A.prototype.reverse = function() { this._array.reverse(); return this; }; /** * each, filter, map 메소드에서 반복구문을 중단한다. * @id core.$A.Break */ $A.Break = function() { if (!(this instanceof arguments.callee)) throw new arguments.callee; }; /** * each, filter, map 메소드에서 현재 인덱스의 반복구문을 건너뛴다. * @id core.$A.Continue */ $A.Continue = function() { if (!(this instanceof arguments.callee)) throw new arguments.callee; }; /** * Ajax 객체를 반환한다. * @id core.$Ajax * @import core.$Ajax.option */ function $Ajax(url, option) { var cl = arguments.callee; if (!(this instanceof cl)) return new cl(url, option); function _getXHR() { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (ActiveXObject) { try { return new ActiveXObject('MSXML2.XMLHTTP'); } catch(e) { return new ActiveXObject('Microsoft.XMLHTTP'); } return null; } } var loc = location.toString(); var domain = ''; try { domain = loc.match(/^https?:\/\/([a-z0-9_\-\.]+)/i)[1]; } catch(e) {} this._url = url; this._options = new Object; this._headers = new Object; this._options = { type :"xhr", method :"post", proxy :"", timeout:0, onload :function(){}, ontimeout:function(){}, jsonp_charset : "utf-8" }; this.option(option); var _opt = this._options; _opt.type = _opt.type.toLowerCase(); _opt.method = _opt.method.toLowerCase(); if (typeof window.__jindo2_callback == "undefined") { window.__jindo2_callback = new Array(); } switch (_opt.type) { case "get": case "post": _opt.method = _opt.type; _opt.type = "xhr"; case "xhr": this._request = _getXHR(); break; case "flash": this._request = new $Ajax.SWFRequest(); break; case "jsonp": _opt.method = "get"; this._request = new $Ajax.JSONPRequest(); this._request.charset = _opt.jsonp_charset; break; case "iframe": this._request = new $Ajax.FrameRequest(); this._request._proxy = _opt.proxy; break; } }; /** * 주어진 데이터로 Ajax를 호출한다. * @id core.$Ajax._onload * @param {Function} Ajax 호출이 완료된 후 실행할 함수 */ $Ajax.prototype._onload = function() { if (this._request.readyState == 4) { this._options.onload($Ajax.Response(this._request)); } }; /** * Ajax를 호출한다. * @id core.$Ajax.request * @param {Object} oData 요청시 보낼 데이터 * @param {Function} onComplete 요청이 완료되었을 때 실행할 함수 */ $Ajax.prototype.request = function(oData) { var t = this; var req = this._request; var opt = this._options; var data, v,a = [], data = ""; if (typeof oData == "undefined" || !oData) { data = null; } else { for(var k in oData) { v = oData[k]; if (typeof v == "function") v = v(); a[a.length] = k+"="+encodeURIComponent(v); } data = a.join("&"); } req.open(opt.method.toUpperCase(), this._url, true); req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); // req.setRequestHeader("charset", "utf-8"); for(var x in this._headers) { if (typeof this._headers[x] == "function") continue; req.setRequestHeader(x, String(this._headers[x])); } if (typeof req.onload != "undefined") { req.onload = function(rq){ t._onload(rq) }; } else { req.onreadystatechange = function(rq){ t._onload(rq) }; } req.send(data); return this; }; /** * @id core.$Ajax.abort */ $Ajax.prototype.abort = function() { this._request.abort(); return this; }; /** * 옵션을 가져오거나 설정한다. * 첫번째 전달값의 타입이 Object 이면 값을 설정하고 문자열이면 해당하는 옵션값을 반환한다. * @id core.$Ajax.option * @param {String} name 가지고 오거나 설정할 옵션이름 * @param {void} value 값을 설정할 옵션이름 * @return {void} 설정된 옵션값 혹은 $Ajax 객체 */ $Ajax.prototype.option = function(name, value) { if (typeof name == "undefined") return ""; if (typeof name == "string") { if (typeof value == "undefined") return this._options[name]; this._options[name] = value; return this; } try { for(var x in name) this._options[x] = name[x] } catch(e) {}; return this; }; /** * 헤더를 가져오거나 설정한다. * 첫번째 전달값의 타입이 Object 이면 값을 설정하고 문자열이면 해당하는 헤더값을 반환한다. * @id core.$Ajax.header * @param {String} name 가지고 오거나 설정할 헤더 이름 * @param {void} value 값을 설정할 헤더 값 * @return {void} 설정된 헤더값 혹은 $Ajax 객체 */ $Ajax.prototype.header = function(name, value) { if (typeof name == "undefined") return ""; if (typeof name == "string") { if (typeof value == "undefined") return this._headers[name]; this._headers[name] = value; return this; } try { for(var x in name) this._headers[x] = name[x] } catch(e) {}; return this; }; /** * Ajax 응답 객체 * @id core.$Ajax.Response * @param {Object} req 요청 객체 */ $Ajax.Response = function(req) { if (this === $Ajax) return new $Ajax.Response(req); this._response = req; }; /** * XML 객체를 반환한다. * @id core.$Ajax.Response.xml */ $Ajax.Response.prototype.xml = function() { return this._response.responseXML; }; $Ajax.Response.prototype.text = function() { return this._response.responseText; }; /** * Returns json object * @id core.$Ajax.Response.json */ $Ajax.Response.prototype.json = function() { if (this._response.responseJSON) { return this._response.responseJSON; } else if (this._response.responseText) { try { if (typeof $JSON != "undefined") { return $JSON(this._response.responseText); } else { return eval("("+this._response.responseText+")"); } } catch(e) { return {}; } } return {}; }; /** * 응답헤더를 가져온다. 인자를 전달하지 않으면 모든 헤더를 반환한다. * @id core.$Ajax.Response.header * @param {String} 가져올 응답헤더의 이름 */ $Ajax.Response.prototype.header = function(name) { if (typeof name == "string") return this._response.getResponseHeader(name); return this._response.getAllResponseHeaders(); }; /** * @id core.$Ajax.RequestBase */ $Ajax.RequestBase = $Class({ _headers : {}, _respHeaders : {}, _respHeaderString : "", responseXML : null, responseJSON : null, responseText : "", $init : function(){}, onload : function(){}, abort : function(){}, open : function(){}, send : function(){}, setRequestHeader : function(sName, sValue) { this._headers[sName] = sValue; }, getResponseHeader : function(sName) { return this._respHeaders[sName] || ""; }, getAllResponseHeaders : function() { return this._respHeaderString; }, _getCallbackInfo : function() { var id = ""; do { id = "$"+Math.floor(Math.random()*10000); } while(window.__jindo2_callback[id]); return {id:id,name:"window.__jindo2_callback."+id}; } }); /** * @id core.$Ajax.JSONPRequest */ $Ajax.JSONPRequest = $Class({ charset : "utf-8", _script : null, _callback : function(data) { var self = this; this.readyState = 4; this.responseJSON = data; this.onload(this); setTimeout(function(){ self.abort() }, 10); }, abort : function() { if (this._script) { try { this._script.parentNode.removeChild(this._script) }catch(e){}; } }, open : function(method, url) { this.responseJSON = null; this._url = url; }, send : function(data) { var t = this; var info = this._getCallbackInfo(); var head = document.getElementsByTagName("head")[0]; this._script = $("