");
+
+//IE는 iframe에 추가할 엘리먼트를 생성하려고 할 때는 document를 반드시 지정해야 한다.(1.4.6 부터 지원)
+var els = $("
" , iframe.contentWindow.document);
+//위와 같을 경우 div태그가 iframe.contentWindow.document기준으로 생김.
+
+ */
+jindo.$ = function(sID/*, id1, id2*/) {
+ var ret = [], arg = arguments, nArgLeng = arg.length, lastArgument = arg[nArgLeng-1],doc = document,el = null;
+ var reg = /^<([a-z]+|h[1-5])>$/i;
+ var reg2 = /^<([a-z]+|h[1-5])(\s+[^>]+)?>/i;
+ if (nArgLeng > 1 && typeof lastArgument != "string" && lastArgument.body) {
+ /*
+
+마지막 인자가 document일때.
+
+ */
+ arg = Array.prototype.slice.apply(arg,[0,nArgLeng-1]);
+ doc = lastArgument;
+ }
+
+ for(var i=0; i < nArgLeng; i++) {
+ el = arg[i];
+ if (typeof el == "string") {
+ el = el.replace(/^\s+|\s+$/g, "");
+
+ if (el.indexOf("<")>-1) {
+ if (reg.test(el)) {
+ el = doc.createElement(RegExp.$1);
+ }else if (reg2.test(el)) {
+ var p = { thead:'table', tbody:'table', tr:'tbody', td:'tr', dt:'dl', dd:'dl', li:'ul', legend:'fieldset',option:"select" };
+ var tag = RegExp.$1.toLowerCase();
+
+ var ele = jindo._createEle(p[tag],el,doc);
+ for (var i=0,leng = ele.length; i < leng ; i++) {
+ ret.push(ele[i]);
+ };
+ el = null;
+
+ }
+ }else {
+ el = doc.getElementById(el);
+ }
+ }
+ if (el) ret[ret.length] = el;
+ }
+ return ret.length>1?ret:(ret[0] || null);
+}
+
+jindo._createEle = function(sParentTag,sHTML,oDoc,bWantParent){
+ var sId = 'R' + new Date().getTime() + parseInt(Math.random() * 100000,10);
+
+ var oDummy = oDoc.createElement("div");
+ switch (sParentTag) {
+ case 'select':
+ case 'table':
+ case 'dl':
+ case 'ul':
+ case 'fieldset':
+ oDummy.innerHTML = '<' + sParentTag + ' class="' + sId + '">' + sHTML + '' + sParentTag + '>';
+ break;
+ case 'thead':
+ case 'tbody':
+ case 'col':
+ oDummy.innerHTML = '
<' + sParentTag + ' class="' + sId + '">' + sHTML + '' + sParentTag + '>
';
+ break;
+ case 'tr':
+ oDummy.innerHTML = '
';
+ break;
+ default:
+ oDummy.innerHTML = '
' + sHTML + '
';
+ break;
+ }
+ var oFound;
+ for (oFound = oDummy.firstChild; oFound; oFound = oFound.firstChild){
+ if (oFound.className==sId) break;
+ }
+
+ return bWantParent? oFound : oFound.childNodes;
+}
+
+/**
+
+ * @class $Class() 객체는 Jindo 프레임워크를 사용하여 객체 지향 프로그래밍 방식으로 애플리케이션을 구현할 수 있도록 지원한다.
+ * @extends core
+ * @description 클래스($Class() 객체)를 생성한다. 파라미터로 클래스화할 객체를 입력한다. 해당 객체에 $init 이름으로 메서드를 등록하면 클래스 인스턴스를 생성하는 생성자 함수를 정의할 수 있다. 또한 $static 키워드를 사용하면 인스턴스를 생성하지 않아도 사용할 수 있는 메서드를 등록할 수 있다.
+ * @param {Object} oDef 클래스를 정의하는 객체. 클래스의 생성자, 속성, 메서드 등을 정의한다.
+ * @return {$Class} 생성된 클래스($Class() 객체).
+ * @example
+var CClass = $Class({
+ prop : null,
+ $init : function() {
+ this.prop = $Ajax();
+ ...
+ },
+ $static : {
+ static_method : function(){ return 1;}
+ }
+});
+
+var c1 = new CClass();
+var c2 = new CClass();
+// c1과 c2는 서로 다른 $Ajax 객체를 각각 가진다.
+
+CClass.static_method(); // 1
+
+ */
+
+
+jindo.$Class = function(oDef) {
+ function typeClass() {
+ var t = this;
+ var a = [];
+
+ var superFunc = function(m, superClass, func) {
+
+ if(m!='constructor' && func.toString().indexOf("$super")>-1 ){
+
+ var funcArg = func.toString().replace(/function\s*\(([^\)]*)[\w\W]*/g,"$1").split(",");
+ // var funcStr = func.toString().replace(/function\s*\(.*\)\s*\{/,"").replace(/this\.\$super/g,"this.$super.$super");
+ var funcStr = func.toString().replace(/function[^{]*{/,"").replace(/(\w|\.?)(this\.\$super|this)/g,function(m,m2,m3){
+ if(!m2){
+ return m3+".$super"
+ }
+ return m;
+ });
+ funcStr = funcStr.substr(0,funcStr.length-1);
+ func = superClass[m] = eval("false||function("+funcArg.join(",")+"){"+funcStr+"}");
+ }
+
+ return function() {
+ var f = this.$this[m];
+ var t = this.$this;
+ var r = (t[m] = func).apply(t, arguments);
+ t[m] = f;
+
+ return r;
+ };
+ }
+
+ while(typeof t._$superClass != "undefined") {
+
+ t.$super = new Object;
+ t.$super.$this = this;
+
+ for(var x in t._$superClass.prototype) {
+
+ if (t._$superClass.prototype.hasOwnProperty(x)){
+ if (typeof this[x] == "undefined" && x !="$init") this[x] = t._$superClass.prototype[x];
+ if (x!='constructor' && x!='_$superClass' && typeof t._$superClass.prototype[x] == "function") {
+ t.$super[x] = superFunc(x, t._$superClass, t._$superClass.prototype[x]);
+ } else {
+
+ t.$super[x] = t._$superClass.prototype[x];
+ }
+ }
+ }
+
+ 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){
+ if (oDef.hasOwnProperty(x)) {
+ x=="$static"||i++;
+ }
+ }
+ for(x in oDef.$static){
+ if (oDef.$static.hasOwnProperty(x)) {
+ typeClass[x] = oDef.$static[x];
+ }
+ }
+
+ if (!i) return oDef.$static;
+ delete oDef.$static;
+ }
+
+ // if (typeof oDef.$destroy == "undefined") {
+ // oDef.$destroy = function(){
+ // if(this.$super&&(arguments.callee==this.$super.$destroy)){this.$super.$destroy();}
+ // }
+ // } else {
+ // oDef.$destroy = eval("false||"+oDef.$destroy.toString().replace(/\}$/,"console.log(this.$super);console.log(arguments.callee!=this.$super.$destroy);if(this.$super&&(arguments.callee==this.$destroy)){this.$super.$destroy();}}"));
+ // }
+ //
+ typeClass.prototype = oDef;
+ typeClass.prototype.constructor = typeClass;
+ typeClass.extend = jindo.$Class.extend;
+
+ return typeClass;
+ }
+
+/**
+
+ * @description extend() 메서드는 특정 클래스($Class() 객체)를 상속한다. 상속할 부모 클래스(Super Class)를 지정한다.
+ * @name $Class#extend
+ * @type $Class
+ * @function
+ * @param {$Class} superClass 상속할 부모 클래스($Class() 객체).
+ * @return {$Class} 상속된 클래스($Class() 객체).
+ * @example
+var ClassExt = $Class(classDefinition);
+ClassExt.extend(superClass);
+// ClassExt는 SuperClass를 상속받는다.
+
+ */
+jindo.$Class.extend = function(superClass) {
+ // superClass._$has_super = true;
+ if (typeof superClass == "undefined" || superClass === null || !superClass.extend) {
+ throw new Error("extend시 슈퍼 클래스는 Class여야 합니다.");
+ }
+
+ this.prototype._$superClass = superClass;
+
+
+ // inherit static methods of parent
+ for(var x in superClass) {
+ if (superClass.hasOwnProperty(x)) {
+ if (x == "prototype") continue;
+ this[x] = superClass[x];
+ }
+ }
+ return this;
+};
+
+/**
+
+ @description $super 속성은 부모 클래스의 메서드에 접근할 때 사용한다. 하위 클래스는 this.$super.method 로 상위 클래스의 메서드에 접근할 수 있으나, this.$super.$super.method 와 같이 한 단계 이상의 상위 클래스는 접근할 수 없다. 또한 부모 클래스와 자식 클래스가 같은 이름의 메서드를 가지고 있고 $super로 그 메서드를 호출하면, 자식 클래스의 메서드를 사용한다.
+ @name $Class#$super
+ @type $Class
+ @example
+ var Parent = $Class ({
+ a: 100,
+ b: 200,
+ c: 300,
+ sum2: function () {
+ var init = this.sum();
+ return init;
+ },
+ sum: function () {
+ return this.a + this.b
+ }
+ });
+
+ var Child = $Class ({
+ a: 10,
+ b: 20,
+ sum2 : function () {
+ var init = this.sum();
+ return init;
+ },
+ sum: function () {
+ return this.b;
+ }
+ }).extend (Parent);
+
+ var oChild = new Child();
+ var oParent = new Parent();
+
+ oChild.sum(); // 20
+ oChild.sum2(); // 20
+ oChild.$super.sum(); // 30 -> 부모 클래스의 100(a)과 200(b)대신 자식 클래스의 10(a)과 20(b)을 더한다.
+ oChild.$super.sum2(); // 20 -> 부모 클래스의 sum2 메서드에서 부모 클래스의 sum()이 아닌 자식 클래스의 sum()을 호출한다.
+
+*/
+
/**
+
+ * @fileOverview CSS 셀렉터를 사용한 엘리먼트 선택 엔진
+ * @name cssquery.js
+ * @author Hooriza
+
+ */
+
+/**
+
+ * @class
+ * @description $$() 함수(cssquery)는 CSS 선택자(CSS Selector)를 사용하여 객체를 탐색한다. $$() 함수 대신 cssquery() 함수를 사용해도 된다. CSS 선택자로 사용할 수 있는 패턴은 표준 패턴과 비표준 패턴이 있다. 표준 패턴은 CSS Level3 명세서에 있는 패턴을 지원한다. 선택자의 패턴에 대한 설명은 다음 표와 See Also 항목을 참고한다.
+
+ 요소, ID, 클래스 선택자
+
+
+ 패턴
+ 설명
+
+
+
+
+ *
+ 모든 요소.
+
+
+
+
+ HTML Tagname
+ 지정된 HTML 태그 요소.
+
+
+
+
+ #id
+ ID가 지정된 요소.
+
+
+
+
+ .classname
+ 클래스가 지정된 요소.
+
+
+
+
+
+
+
+ 속성 선택자
+
+
+ 패턴
+ 설명
+
+
+
+
+ [type]
+ 지정된 속성을 갖고 있는 요소.
+
+
+
+
+ [type=value]
+ 속성과 값이 일치하는 요소.
+
+
+
+
+ [type^=value]
+ 속성의 값이 특정 값으로 시작하는 요소.
+
+
+
+
+ [type$=value]
+ 속성의 값이 특정 값으로 끝나는 요소.
+
+
+
+
+ [type~=value]
+ 속성 값에 공백으로 구분된 여러 개의 값이 존재하는 경우, 각각의 값 중 한가지 값을 갖는 요소.
+
+
+
+
+ [type*=value]
+ 속성 값 중에 일치하는 값이 있는 요소.
+
+
+
+
+ [type!=value]
+ 값이 지정된 값과 일치하지 않는 요소.
+
+
+
+
+ [@type]
+ cssquery 전용으로 사용하는 선택자로서 요소의 속성이 아닌 요소의 스타일 속성을 사용한다. CSS 속성 선택자의 특성을 모두 적용해 사용할 수 있다.
+
+
+
+
+
+
+
+ 가상 클래스 선택자
+
+
+ 패턴
+ 설명
+
+
+
+
+ :nth-child(n)
+ n번째 자식인지 여부로 해당 요소를 선택한다.
+
+
+
+
+ :nth-last-child(n)
+ nth-child와 동일하나, 뒤에서부터 요소를 선택한다.
+
+
+
+
+ :last-child
+ 마지막 자식인지 여부로 요소를 선택한다.
+
+
+
+
+ :nth-of-type(n)
+ n번째로 발견된 요소를 선택한다.
+
+ 위와 같은 DOM이 있을 때, $$("span:nth-child(1)")은 <span> 요소가 firstChild인 요소는 없기 때문에 결과 값을 반환하지 않는다 하지만 $$("span:nth-of-type(1)")는 <span> 요소 중에서 첫 번째 <span> 요소인 <span>2</span>를 얻어오게 된다. nth-child와 마찬가지로 짝수/홀수 등의 수식을 사용할 수 있다.
+
+
+
+ :first-of-type
+ 같은 태그 이름을 갖는 형제 요소 중에서 첫 번째 요소를 선택한다. nth-of-type(1)과 같은 결과 값을 반환한다.
+
+
+ :nth-last-of-type
+ nth-of-type과 동일하나, 뒤에서부터 요소를 선택한다.
+
+
+ :last-of-type
+ 같은 태그 이름을 갖는 형제 요소 중에서 마지막 요소를 선택한다. nth-last-of-type(1)과 같은 결과 값을 반환한다.
+
+
+ :contains
+ 텍스트 노드에 특정 문자열을 포함하고 있는지 여부로 해당 요소를 선택한다.
+
+
+
+
+ :only-child
+ 형제가 없는 요소를 선택한다.
+
+ 위의 DOM에서 $$("div:only-child")만 반환 값이 있고, $$("p:only-child") 또는 $$("span:only-child")는 반환 값이 없다. 즉, 형제 노드가 없는 <div> 요소만 선택된다.
+
+
+
+ :empty
+ 비어있는 요소를 선택한다.
+
+
+
+
+ :not
+ 선택자의 조건과 반대인 요소를 선택한다.
+
+
+
+
+
+
+
+ 콤비네이터 선택자
+
+
+ 패턴
+ 설명
+
+
+
+
+ 공백 (space)
+ 하위의 모든 요소를 의미한다.
+
+
+
+
+ >
+ 자식 노드에 속하는 모든 요소를 의미한다.
+
+
+
+
+ +
+ 지정한 요소의 바로 다음 형제 노드에 속하는 모든 요소를 의미한다.
+
+
+
+
+ ~
+ + 패턴과 동일하나, 바로 다음 형제 노드뿐만 아니라 지정된 노드 이후에 속하는 모든 요소를 의미한다.
+
+
+
+
+ !
+ cssquery 전용으로, 콤비네이터의 반대 방향으로 탐색을 시작해 요소를 검색한다.
+
+
+
+
+
+ * @param {String} sSelector CSS 선택자. CSS 선택자로 사용할 수 있는 패턴은 표준 패턴과 비표준 패턴이 있다. 표준 패턴은 CSS Level3 명세서에 있는 패턴을 지원한다.
+ * @param {Element} [elBaseElement] 탐색 대상이 되는 DOM 요소. 지정한 요소의 하위 노드에서만 객체를 탐색한다. 생략될 경우 문서를 대상으로 찾는다.
+ * @return {Array} 조건에 해당하는 요소를 배열 형태로 반환한다.
+ * @see $Document#queryAll
+ * @see
CSS Level3 명세서 - W3C
+ * @example
+ // 문서에서 IMG 태그를 찾는다.
+ var imgs = $$('IMG');
+
+ // div 요소 하위에서 IMG 태그를 찾는다.
+ var imgsInDiv = $$('IMG', $('div'));
+
+ // 문서에서 IMG 태그 중 가장 첫 요소를 찾는다.
+ var firstImg = $$.getSingle('IMG');
+
+ */
+jindo.$$ = jindo.cssquery = (function() {
+ /*
+
+querySelector 설정.
+
+ */
+ var sVersion = '3.0';
+
+ var debugOption = { repeat : 1 };
+
+ /*
+
+빠른 처리를 위해 노드마다 유일키 값 셋팅
+
+ */
+ var UID = 1;
+
+ var cost = 0;
+ var validUID = {};
+
+ var bSupportByClassName = document.getElementsByClassName ? true : false;
+ var safeHTML = false;
+
+ var getUID4HTML = function(oEl) {
+
+ var nUID = safeHTML ? (oEl._cssquery_UID && oEl._cssquery_UID[0]) : oEl._cssquery_UID;
+ if (nUID && validUID[nUID] == oEl) return nUID;
+
+ nUID = UID++;
+ oEl._cssquery_UID = safeHTML ? [ nUID ] : nUID;
+
+ validUID[nUID] = oEl;
+ return nUID;
+
+ };
+
+ var getUID4XML = function(oEl) {
+
+ var oAttr = oEl.getAttribute('_cssquery_UID');
+ var nUID = safeHTML ? (oAttr && oAttr[0]) : oAttr;
+
+ if (!nUID) {
+ nUID = UID++;
+ oEl.setAttribute('_cssquery_UID', safeHTML ? [ nUID ] : nUID);
+ }
+
+ return nUID;
+
+ };
+
+ var getUID = getUID4HTML;
+
+ var uniqid = function(sPrefix) {
+ return (sPrefix || '') + new Date().getTime() + parseInt(Math.random() * 100000000,10);
+ };
+
+ function getElementsByClass(searchClass,node,tag) {
+ var classElements = new Array();
+ if ( node == null )
+ node = document;
+ if ( tag == null )
+ tag = '*';
+ var els = node.getElementsByTagName(tag);
+ var elsLen = els.length;
+ var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
+ for (i = 0, j = 0; i < elsLen; i++) {
+ if ( pattern.test(els[i].className) ) {
+ classElements[j] = els[i];
+ j++;
+ }
+ }
+ return classElements;
+ }
+
+ var getChilds_dontShrink = function(oEl, sTagName, sClassName) {
+ if (bSupportByClassName && sClassName) {
+ if(oEl.getElementsByClassName)
+ return oEl.getElementsByClassName(sClassName);
+ if(oEl.querySelectorAll)
+ return oEl.querySelectorAll(sClassName);
+ return getElementsByClass(sClassName, oEl, sTagName);
+ }else if (sTagName == '*') {
+ return oEl.all || oEl.getElementsByTagName(sTagName);
+ }
+ return oEl.getElementsByTagName(sTagName);
+ };
+
+ var clearKeys = function() {
+ backupKeys._keys = {};
+ };
+
+ var oDocument_dontShrink = document;
+
+ var bXMLDocument = false;
+
+ /*
+
+따옴표, [] 등 파싱에 문제가 될 수 있는 부분 replace 시켜놓기
+
+ */
+ var backupKeys = function(sQuery) {
+
+ var oKeys = backupKeys._keys;
+
+ /*
+
+작은 따옴표 걷어내기
+
+ */
+ sQuery = sQuery.replace(/'(\\'|[^'])*'/g, function(sAll) {
+ var uid = uniqid('QUOT');
+ oKeys[uid] = sAll;
+ return uid;
+ });
+
+ /*
+
+큰 따옴표 걷어내기
+
+ */
+ sQuery = sQuery.replace(/"(\\"|[^"])*"/g, function(sAll) {
+ var uid = uniqid('QUOT');
+ oKeys[uid] = sAll;
+ return uid;
+ });
+
+ /*
+
+[ ] 형태 걷어내기
+
+ */
+ sQuery = sQuery.replace(/\[(.*?)\]/g, function(sAll, sBody) {
+ if (sBody.indexOf('ATTR') == 0) return sAll;
+ var uid = '[' + uniqid('ATTR') + ']';
+ oKeys[uid] = sAll;
+ return uid;
+ });
+
+ /*
+
+( ) 형태 걷어내기
+
+ */
+ var bChanged;
+
+ do {
+
+ bChanged = false;
+
+ sQuery = sQuery.replace(/\(((\\\)|[^)|^(])*)\)/g, function(sAll, sBody) {
+ if (sBody.indexOf('BRCE') == 0) return sAll;
+ var uid = '_' + uniqid('BRCE');
+ oKeys[uid] = sAll;
+ bChanged = true;
+ return uid;
+ });
+
+ } while(bChanged);
+
+ return sQuery;
+
+ };
+
+ /*
+
+replace 시켜놓은 부분 복구하기
+
+ */
+ var restoreKeys = function(sQuery, bOnlyAttrBrace) {
+
+ var oKeys = backupKeys._keys;
+
+ var bChanged;
+ var rRegex = bOnlyAttrBrace ? /(\[ATTR[0-9]+\])/g : /(QUOT[0-9]+|\[ATTR[0-9]+\])/g;
+
+ do {
+
+ bChanged = false;
+
+ sQuery = sQuery.replace(rRegex, function(sKey) {
+
+ if (oKeys[sKey]) {
+ bChanged = true;
+ return oKeys[sKey];
+ }
+
+ return sKey;
+
+ });
+
+ } while(bChanged);
+
+ /*
+
+( ) 는 한꺼풀만 벗겨내기
+
+ */
+ sQuery = sQuery.replace(/_BRCE[0-9]+/g, function(sKey) {
+ return oKeys[sKey] ? oKeys[sKey] : sKey;
+ });
+
+ return sQuery;
+
+ };
+
+ /*
+
+replace 시켜놓은 문자열에서 Quot 을 제외하고 리턴
+
+ */
+ var restoreString = function(sKey) {
+
+ var oKeys = backupKeys._keys;
+ var sOrg = oKeys[sKey];
+
+ if (!sOrg) return sKey;
+ return eval(sOrg);
+
+ };
+
+ var wrapQuot = function(sStr) {
+ return '"' + sStr.replace(/"/g, '\\"') + '"';
+ };
+
+ var getStyleKey = function(sKey) {
+
+ if (/^@/.test(sKey)) return sKey.substr(1);
+ return null;
+
+ };
+
+ var getCSS = function(oEl, sKey) {
+
+ if (oEl.currentStyle) {
+
+ if (sKey == "float") sKey = "styleFloat";
+ return oEl.currentStyle[sKey] || oEl.style[sKey];
+
+ } else if (window.getComputedStyle) {
+
+ return oDocument_dontShrink.defaultView.getComputedStyle(oEl, null).getPropertyValue(sKey.replace(/([A-Z])/g,"-$1").toLowerCase()) || oEl.style[sKey];
+
+ }
+
+ if (sKey == "float" && /MSIE/.test(window.navigator.userAgent)) sKey = "styleFloat";
+ return oEl.style[sKey];
+
+ };
+
+ var oCamels = {
+ 'accesskey' : 'accessKey',
+ 'cellspacing' : 'cellSpacing',
+ 'cellpadding' : 'cellPadding',
+ 'class' : 'className',
+ 'colspan' : 'colSpan',
+ 'for' : 'htmlFor',
+ 'maxlength' : 'maxLength',
+ 'readonly' : 'readOnly',
+ 'rowspan' : 'rowSpan',
+ 'tabindex' : 'tabIndex',
+ 'valign' : 'vAlign'
+ };
+
+ var getDefineCode = function(sKey) {
+
+ var sVal;
+ var sStyleKey;
+
+ if (bXMLDocument) {
+
+ sVal = 'oEl.getAttribute("' + sKey + '",2)';
+
+ } else {
+
+ if (sStyleKey = getStyleKey(sKey)) {
+
+ sKey = '$$' + sStyleKey;
+ sVal = 'getCSS(oEl, "' + sStyleKey + '")';
+
+ } else {
+
+ switch (sKey) {
+ case 'checked':
+ sVal = 'oEl.checked + ""';
+ break;
+
+ case 'disabled':
+ sVal = 'oEl.disabled + ""';
+ break;
+
+ case 'enabled':
+ sVal = '!oEl.disabled + ""';
+ break;
+
+ case 'readonly':
+ sVal = 'oEl.readOnly + ""';
+ break;
+
+ case 'selected':
+ sVal = 'oEl.selected + ""';
+ break;
+
+ default:
+ if (oCamels[sKey]) {
+ sVal = 'oEl.' + oCamels[sKey];
+ } else {
+ sVal = 'oEl.getAttribute("' + sKey + '",2)';
+ }
+ }
+
+ }
+
+ }
+
+ return '_' + sKey + ' = ' + sVal;
+ };
+
+ var getReturnCode = function(oExpr) {
+
+ var sStyleKey = getStyleKey(oExpr.key);
+
+ var sVar = '_' + (sStyleKey ? '$$' + sStyleKey : oExpr.key);
+ var sVal = oExpr.val ? wrapQuot(oExpr.val) : '';
+
+ switch (oExpr.op) {
+ case '~=':
+ return '(' + sVar + ' && (" " + ' + sVar + ' + " ").indexOf(" " + ' + sVal + ' + " ") > -1)';
+ case '^=':
+ return '(' + sVar + ' && ' + sVar + '.indexOf(' + sVal + ') == 0)';
+ case '$=':
+ return '(' + sVar + ' && ' + sVar + '.substr(' + sVar + '.length - ' + oExpr.val.length + ') == ' + sVal + ')';
+ case '*=':
+ return '(' + sVar + ' && ' + sVar + '.indexOf(' + sVal + ') > -1)';
+ case '!=':
+ return '(' + sVar + ' != ' + sVal + ')';
+ case '=':
+ return '(' + sVar + ' == ' + sVal + ')';
+ }
+
+ return '(' + sVar + ')';
+
+ };
+
+ var getNodeIndex = function(oEl) {
+ var nUID = getUID(oEl);
+ var nIndex = oNodeIndexes[nUID] || 0;
+
+ /*
+
+노드 인덱스를 구할 수 없으면
+
+ */
+ if (nIndex == 0) {
+
+ for (var oSib = (oEl.parentNode || oEl._IE5_parentNode).firstChild; oSib; oSib = oSib.nextSibling) {
+
+ if (oSib.nodeType != 1){
+ continue;
+ }
+ nIndex++;
+
+ setNodeIndex(oSib, nIndex);
+
+ }
+
+ nIndex = oNodeIndexes[nUID];
+
+ }
+
+ return nIndex;
+
+ };
+
+ /*
+
+몇번째 자식인지 설정하는 부분
+
+ */
+ var oNodeIndexes = {};
+
+ var setNodeIndex = function(oEl, nIndex) {
+ var nUID = getUID(oEl);
+ oNodeIndexes[nUID] = nIndex;
+ };
+
+ var unsetNodeIndexes = function() {
+ setTimeout(function() { oNodeIndexes = {}; }, 0);
+ };
+
+ /*
+
+가상 클래스
+
+ */
+ var oPseudoes_dontShrink = {
+
+ 'contains' : function(oEl, sOption) {
+ return (oEl.innerText || oEl.textContent || '').indexOf(sOption) > -1;
+ },
+
+ 'last-child' : function(oEl, sOption) {
+ for (oEl = oEl.nextSibling; oEl; oEl = oEl.nextSibling){
+ if (oEl.nodeType == 1)
+ return false;
+ }
+
+
+ return true;
+ },
+
+ 'first-child' : function(oEl, sOption) {
+ for (oEl = oEl.previousSibling; oEl; oEl = oEl.previousSibling){
+ if (oEl.nodeType == 1)
+ return false;
+ }
+
+
+ return true;
+ },
+
+ 'only-child' : function(oEl, sOption) {
+ var nChild = 0;
+
+ for (var oChild = (oEl.parentNode || oEl._IE5_parentNode).firstChild; oChild; oChild = oChild.nextSibling) {
+ if (oChild.nodeType == 1) nChild++;
+ if (nChild > 1) return false;
+ }
+
+ return nChild ? true : false;
+ },
+
+ 'empty' : function(oEl, _) {
+ return oEl.firstChild ? false : true;
+ },
+
+ 'nth-child' : function(oEl, nMul, nAdd) {
+ var nIndex = getNodeIndex(oEl);
+ return nIndex % nMul == nAdd;
+ },
+
+ 'nth-last-child' : function(oEl, nMul, nAdd) {
+ var oLast = (oEl.parentNode || oEl._IE5_parentNode).lastChild;
+ for (; oLast; oLast = oLast.previousSibling){
+ if (oLast.nodeType == 1) break;
+ }
+
+
+ var nTotal = getNodeIndex(oLast);
+ var nIndex = getNodeIndex(oEl);
+
+ var nLastIndex = nTotal - nIndex + 1;
+ return nLastIndex % nMul == nAdd;
+ },
+ 'checked' : function(oEl){
+ return !!oEl.checked;
+ },
+ 'selected' : function(oEl){
+ return !!oEl.selected;
+ },
+ 'enabled' : function(oEl){
+ return !oEl.disabled;
+ },
+ 'disabled' : function(oEl){
+ return !!oEl.disabled;
+ }
+ };
+
+ /*
+
+단일 part 의 body 에서 expression 뽑아냄
+
+ */
+ var getExpression = function(sBody) {
+
+ var oRet = { defines : '', returns : 'true' };
+
+ var sBody = restoreKeys(sBody, true);
+
+ var aExprs = [];
+ var aDefineCode = [], aReturnCode = [];
+ var sId, sTagName;
+
+ /*
+
+유사클래스 조건 얻어내기
+
+ */
+ var sBody = sBody.replace(/:([\w-]+)(\(([^)]*)\))?/g, function(_1, sType, _2, sOption) {
+
+ switch (sType) {
+ case 'not':
+ /*
+
+괄호 안에 있는거 재귀파싱하기
+
+ */
+ var oInner = getExpression(sOption);
+
+ var sFuncDefines = oInner.defines;
+ var sFuncReturns = oInner.returnsID + oInner.returnsTAG + oInner.returns;
+
+ aReturnCode.push('!(function() { ' + sFuncDefines + ' return ' + sFuncReturns + ' })()');
+ break;
+
+ case 'nth-child':
+ case 'nth-last-child':
+ sOption = restoreString(sOption);
+
+ if (sOption == 'even'){
+ sOption = '2n';
+ }else if (sOption == 'odd') {
+ sOption = '2n+1';
+ }
+
+ var nMul, nAdd;
+ var matchstr = sOption.match(/([0-9]*)n([+-][0-9]+)*/);
+ if (matchstr) {
+ nMul = matchstr[1] || 1;
+ nAdd = matchstr[2] || 0;
+ } else {
+ nMul = Infinity;
+ nAdd = parseInt(sOption,10);
+ }
+ aReturnCode.push('oPseudoes_dontShrink[' + wrapQuot(sType) + '](oEl, ' + nMul + ', ' + nAdd + ')');
+ break;
+
+ case 'first-of-type':
+ case 'last-of-type':
+ sType = (sType == 'first-of-type' ? 'nth-of-type' : 'nth-last-of-type');
+ sOption = 1;
+
+ case 'nth-of-type':
+ case 'nth-last-of-type':
+ sOption = restoreString(sOption);
+
+ if (sOption == 'even') {
+ sOption = '2n';
+ }else if (sOption == 'odd'){
+ sOption = '2n+1';
+ }
+
+ var nMul, nAdd;
+
+ if (/([0-9]*)n([+-][0-9]+)*/.test(sOption)) {
+ nMul = parseInt(RegExp.$1,10) || 1;
+ nAdd = parseInt(RegExp.$2,20) || 0;
+ } else {
+ nMul = Infinity;
+ nAdd = parseInt(sOption,10);
+ }
+
+ oRet.nth = [ nMul, nAdd, sType ];
+ break;
+
+ default:
+ sOption = sOption ? restoreString(sOption) : '';
+ aReturnCode.push('oPseudoes_dontShrink[' + wrapQuot(sType) + '](oEl, ' + wrapQuot(sOption) + ')');
+ break;
+ }
+
+ return '';
+
+ });
+
+ /*
+
+[key=value] 형태 조건 얻어내기
+
+ */
+ var sBody = sBody.replace(/\[(@?[\w-]+)(([!^~$*]?=)([^\]]*))?\]/g, function(_1, sKey, _2, sOp, sVal) {
+
+ sKey = restoreString(sKey);
+ sVal = restoreString(sVal);
+
+ if (sKey == 'checked' || sKey == 'disabled' || sKey == 'enabled' || sKey == 'readonly' || sKey == 'selected') {
+
+ if (!sVal) {
+ sOp = '=';
+ sVal = 'true';
+ }
+
+ }
+
+ aExprs.push({ key : sKey, op : sOp, val : sVal });
+ return '';
+
+ });
+
+ var sClassName = null;
+
+ /*
+
+클래스 조건 얻어내기
+
+ */
+ var sBody = sBody.replace(/\.([\w-]+)/g, function(_, sClass) {
+ aExprs.push({ key : 'class', op : '~=', val : sClass });
+ if (!sClassName) sClassName = sClass;
+ return '';
+ });
+
+ /*
+
+id 조건 얻어내기
+
+ */
+ var sBody = sBody.replace(/#([\w-]+)/g, function(_, sIdValue) {
+ if (bXMLDocument) {
+ aExprs.push({ key : 'id', op : '=', val : sIdValue });
+ }else{
+ sId = sIdValue;
+ }
+ return '';
+ });
+
+ sTagName = sBody == '*' ? '' : sBody;
+
+ /*
+
+match 함수 코드 만들어 내기
+
+ */
+ var oVars = {};
+
+ for (var i = 0, oExpr; oExpr = aExprs[i]; i++) {
+
+ var sKey = oExpr.key;
+
+ if (!oVars[sKey]) aDefineCode.push(getDefineCode(sKey));
+ /*
+
+유사클래스 조건 검사가 맨 뒤로 가도록 unshift 사용
+
+ */
+ aReturnCode.unshift(getReturnCode(oExpr));
+ oVars[sKey] = true;
+
+ }
+
+ if (aDefineCode.length) oRet.defines = 'var ' + aDefineCode.join(',') + ';';
+ if (aReturnCode.length) oRet.returns = aReturnCode.join('&&');
+
+ oRet.quotID = sId ? wrapQuot(sId) : '';
+ oRet.quotTAG = sTagName ? wrapQuot(bXMLDocument ? sTagName : sTagName.toUpperCase()) : '';
+
+ if (bSupportByClassName) oRet.quotCLASS = sClassName ? wrapQuot(sClassName) : '';
+
+ oRet.returnsID = sId ? 'oEl.id == ' + oRet.quotID + ' && ' : '';
+ oRet.returnsTAG = sTagName && sTagName != '*' ? 'oEl.tagName == ' + oRet.quotTAG + ' && ' : '';
+
+ return oRet;
+
+ };
+
+ /*
+
+쿼리를 연산자 기준으로 잘라냄
+
+ */
+ var splitToParts = function(sQuery) {
+
+ var aParts = [];
+ var sRel = ' ';
+
+ var sBody = sQuery.replace(/(.*?)\s*(!?[+>~ ]|!)\s*/g, function(_, sBody, sRelative) {
+
+ if (sBody) aParts.push({ rel : sRel, body : sBody });
+
+ sRel = sRelative.replace(/\s+$/g, '') || ' ';
+ return '';
+
+ });
+
+ if (sBody) aParts.push({ rel : sRel, body : sBody });
+
+ return aParts;
+
+ };
+
+ var isNth_dontShrink = function(oEl, sTagName, nMul, nAdd, sDirection) {
+
+ var nIndex = 0;
+ for (var oSib = oEl; oSib; oSib = oSib[sDirection]){
+ if (oSib.nodeType == 1 && (!sTagName || sTagName == oSib.tagName))
+ nIndex++;
+ }
+
+
+ return nIndex % nMul == nAdd;
+
+ };
+
+ /*
+
+잘라낸 part 를 함수로 컴파일 하기
+
+ */
+ var compileParts = function(aParts) {
+
+ var aPartExprs = [];
+
+ /*
+
+잘라낸 부분들 조건 만들기
+
+ */
+ for (var i = 0, oPart; oPart = aParts[i]; i++)
+ aPartExprs.push(getExpression(oPart.body));
+
+ //////////////////// BEGIN
+
+ var sFunc = '';
+ var sPushCode = 'aRet.push(oEl); if (oOptions.single) { bStop = true; }';
+
+ for (var i = aParts.length - 1, oPart; oPart = aParts[i]; i--) {
+
+ var oExpr = aPartExprs[i];
+ var sPush = (debugOption.callback ? 'cost++;' : '') + oExpr.defines;
+
+
+ var sReturn = 'if (bStop) {' + (i == 0 ? 'return aRet;' : 'return;') + '}';
+
+ if (oExpr.returns == 'true') {
+ sPush += (sFunc ? sFunc + '(oEl);' : sPushCode) + sReturn;
+ }else{
+ sPush += 'if (' + oExpr.returns + ') {' + (sFunc ? sFunc + '(oEl);' : sPushCode ) + sReturn + '}';
+ }
+
+ var sCheckTag = 'oEl.nodeType != 1';
+ if (oExpr.quotTAG) sCheckTag = 'oEl.tagName != ' + oExpr.quotTAG;
+
+ var sTmpFunc =
+ '(function(oBase' +
+ (i == 0 ? ', oOptions) { var bStop = false; var aRet = [];' : ') {');
+
+ if (oExpr.nth) {
+ sPush =
+ 'if (isNth_dontShrink(oEl, ' +
+ (oExpr.quotTAG ? oExpr.quotTAG : 'false') + ',' +
+ oExpr.nth[0] + ',' +
+ oExpr.nth[1] + ',' +
+ '"' + (oExpr.nth[2] == 'nth-of-type' ? 'previousSibling' : 'nextSibling') + '")) {' + sPush + '}';
+ }
+
+ switch (oPart.rel) {
+ case ' ':
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'var oCandi = oEl;' +
+ 'for (; oCandi; oCandi = (oCandi.parentNode || oCandi._IE5_parentNode)) {' +
+ 'if (oCandi == oBase) break;' +
+ '}' +
+ 'if (!oCandi || ' + sCheckTag + ') return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'var aCandi = getChilds_dontShrink(oBase, ' + (oExpr.quotTAG || '"*"') + ', ' + (oExpr.quotCLASS || 'null') + ');' +
+ 'for (var i = 0, oEl; oEl = aCandi[i]; i++) {' +
+ (oExpr.quotCLASS ? 'if (' + sCheckTag + ') continue;' : '') +
+ sPush +
+ '}';
+
+ }
+
+ break;
+
+ case '>':
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'if ((oEl.parentNode || oEl._IE5_parentNode) != oBase || ' + sCheckTag + ') return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'for (var oEl = oBase.firstChild; oEl; oEl = oEl.nextSibling) {' +
+ 'if (' + sCheckTag + ') { continue; }' +
+ sPush +
+ '}';
+
+ }
+
+ break;
+
+ case '+':
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'var oPrev;' +
+ 'for (oPrev = oEl.previousSibling; oPrev; oPrev = oPrev.previousSibling) { if (oPrev.nodeType == 1) break; }' +
+ 'if (!oPrev || oPrev != oBase || ' + sCheckTag + ') return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'for (var oEl = oBase.nextSibling; oEl; oEl = oEl.nextSibling) { if (oEl.nodeType == 1) break; }' +
+ 'if (!oEl || ' + sCheckTag + ') { return aRet; }' +
+ sPush;
+
+ }
+
+ break;
+
+ case '~':
+
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'var oCandi = oEl;' +
+ 'for (; oCandi; oCandi = oCandi.previousSibling) { if (oCandi == oBase) break; }' +
+ 'if (!oCandi || ' + sCheckTag + ') return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'for (var oEl = oBase.nextSibling; oEl; oEl = oEl.nextSibling) {' +
+ 'if (' + sCheckTag + ') { continue; }' +
+ 'if (!markElement_dontShrink(oEl, ' + i + ')) { break; }' +
+ sPush +
+ '}';
+
+ }
+
+ break;
+
+ case '!' :
+
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'for (; oBase; oBase = (oBase.parentNode || oBase._IE5_parentNode)) { if (oBase == oEl) break; }' +
+ 'if (!oBase || ' + sCheckTag + ') return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'for (var oEl = (oBase.parentNode || oBase._IE5_parentNode); oEl; oEl = (oEl.parentNode || oEl._IE5_parentNode)) {'+
+ 'if (' + sCheckTag + ') { continue; }' +
+ sPush +
+ '}';
+
+ }
+
+ break;
+
+ case '!>' :
+
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'var oRel = (oBase.parentNode || oBase._IE5_parentNode);' +
+ 'if (!oRel || oEl != oRel || (' + sCheckTag + ')) return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'var oEl = (oBase.parentNode || oBase._IE5_parentNode);' +
+ 'if (!oEl || ' + sCheckTag + ') { return aRet; }' +
+ sPush;
+
+ }
+
+ break;
+
+ case '!+' :
+
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'var oRel;' +
+ 'for (oRel = oBase.previousSibling; oRel; oRel = oRel.previousSibling) { if (oRel.nodeType == 1) break; }' +
+ 'if (!oRel || oEl != oRel || (' + sCheckTag + ')) return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'for (oEl = oBase.previousSibling; oEl; oEl = oEl.previousSibling) { if (oEl.nodeType == 1) break; }' +
+ 'if (!oEl || ' + sCheckTag + ') { return aRet; }' +
+ sPush;
+
+ }
+
+ break;
+
+ case '!~' :
+
+ if (oExpr.quotID) {
+
+ sTmpFunc +=
+ 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
+ 'var oRel;' +
+ 'for (oRel = oBase.previousSibling; oRel; oRel = oRel.previousSibling) { ' +
+ 'if (oRel.nodeType != 1) { continue; }' +
+ 'if (oRel == oEl) { break; }' +
+ '}' +
+ 'if (!oRel || (' + sCheckTag + ')) return aRet;' +
+ sPush;
+
+ } else {
+
+ sTmpFunc +=
+ 'for (oEl = oBase.previousSibling; oEl; oEl = oEl.previousSibling) {' +
+ 'if (' + sCheckTag + ') { continue; }' +
+ 'if (!markElement_dontShrink(oEl, ' + i + ')) { break; }' +
+ sPush +
+ '}';
+
+ }
+
+ break;
+ }
+
+ sTmpFunc +=
+ (i == 0 ? 'return aRet;' : '') +
+ '})';
+
+ sFunc = sTmpFunc;
+
+ }
+
+ eval('var fpCompiled = ' + sFunc + ';');
+ return fpCompiled;
+
+ };
+
+ /*
+
+쿼리를 match 함수로 변환
+
+ */
+ var parseQuery = function(sQuery) {
+
+ var sCacheKey = sQuery;
+
+ var fpSelf = arguments.callee;
+ var fpFunction = fpSelf._cache[sCacheKey];
+
+ if (!fpFunction) {
+
+ sQuery = backupKeys(sQuery);
+
+ var aParts = splitToParts(sQuery);
+
+ fpFunction = fpSelf._cache[sCacheKey] = compileParts(aParts);
+ fpFunction.depth = aParts.length;
+
+ }
+
+ return fpFunction;
+
+ };
+
+ parseQuery._cache = {};
+
+ /*
+
+test 쿼리를 match 함수로 변환
+
+ */
+ var parseTestQuery = function(sQuery) {
+
+ var fpSelf = arguments.callee;
+
+ var aSplitQuery = backupKeys(sQuery).split(/\s*,\s*/);
+ var aResult = [];
+
+ var nLen = aSplitQuery.length;
+ var aFunc = [];
+
+ for (var i = 0; i < nLen; i++) {
+
+ aFunc.push((function(sQuery) {
+
+ var sCacheKey = sQuery;
+ var fpFunction = fpSelf._cache[sCacheKey];
+
+ if (!fpFunction) {
+
+ sQuery = backupKeys(sQuery);
+ var oExpr = getExpression(sQuery);
+
+ eval('fpFunction = function(oEl) { ' + oExpr.defines + 'return (' + oExpr.returnsID + oExpr.returnsTAG + oExpr.returns + '); };');
+
+ }
+
+ return fpFunction;
+
+ })(restoreKeys(aSplitQuery[i])));
+
+ }
+ return aFunc;
+
+ };
+
+ parseTestQuery._cache = {};
+
+ var distinct = function(aList) {
+
+ var aDistinct = [];
+ var oDummy = {};
+
+ for (var i = 0, oEl; oEl = aList[i]; i++) {
+
+ var nUID = getUID(oEl);
+ if (oDummy[nUID]) continue;
+
+ aDistinct.push(oEl);
+ oDummy[nUID] = true;
+ }
+
+ return aDistinct;
+
+ };
+
+ var markElement_dontShrink = function(oEl, nDepth) {
+
+ var nUID = getUID(oEl);
+ if (cssquery._marked[nDepth][nUID]) return false;
+
+ cssquery._marked[nDepth][nUID] = true;
+ return true;
+
+ };
+
+ var oResultCache = null;
+ var bUseResultCache = false;
+ var bExtremeMode = false;
+
+ var old_cssquery = function(sQuery, oParent, oOptions) {
+
+ if (typeof sQuery == 'object') {
+
+ var oResult = {};
+
+ for (var k in sQuery){
+ if(sQuery.hasOwnProperty(k))
+ oResult[k] = arguments.callee(sQuery[k], oParent, oOptions);
+ }
+
+ return oResult;
+ }
+
+ cost = 0;
+
+ var executeTime = new Date().getTime();
+ var aRet;
+
+ for (var r = 0, rp = debugOption.repeat; r < rp; r++) {
+
+ aRet = (function(sQuery, oParent, oOptions) {
+
+ if(oOptions){
+ if(!oOptions.oneTimeOffCache){
+ oOptions.oneTimeOffCache = false;
+ }
+ }else{
+ oOptions = {oneTimeOffCache:false};
+ }
+ cssquery.safeHTML(oOptions.oneTimeOffCache);
+
+ if (!oParent) oParent = document;
+
+ /*
+
+ownerDocument 잡아주기
+
+ */
+ oDocument_dontShrink = oParent.ownerDocument || oParent.document || oParent;
+
+ /*
+
+브라우저 버젼이 IE5.5 이하
+
+ */
+ if (/\bMSIE\s([0-9]+(\.[0-9]+)*);/.test(navigator.userAgent) && parseFloat(RegExp.$1) < 6) {
+ try { oDocument_dontShrink.location; } catch(e) { oDocument_dontShrink = document; }
+
+ oDocument_dontShrink.firstChild = oDocument_dontShrink.getElementsByTagName('html')[0];
+ oDocument_dontShrink.firstChild._IE5_parentNode = oDocument_dontShrink;
+ }
+
+ /*
+
+XMLDocument 인지 체크
+
+ */
+ bXMLDocument = (typeof XMLDocument != 'undefined') ? (oDocument_dontShrink.constructor === XMLDocument) : (!oDocument_dontShrink.location);
+ getUID = bXMLDocument ? getUID4XML : getUID4HTML;
+
+ clearKeys();
+
+ /*
+
+쿼리를 쉼표로 나누기
+
+ */
+ var aSplitQuery = backupKeys(sQuery).split(/\s*,\s*/);
+ var aResult = [];
+
+ var nLen = aSplitQuery.length;
+
+ for (var i = 0; i < nLen; i++)
+ aSplitQuery[i] = restoreKeys(aSplitQuery[i]);
+
+ /*
+
+쉼표로 나눠진 쿼리 루프
+
+ */
+ for (var i = 0; i < nLen; i++) {
+
+ var sSingleQuery = aSplitQuery[i];
+ var aSingleQueryResult = null;
+
+ var sResultCacheKey = sSingleQuery + (oOptions.single ? '_single' : '');
+
+ /*
+
+결과 캐쉬 뒤짐
+
+ */
+ var aCache = bUseResultCache ? oResultCache[sResultCacheKey] : null;
+ if (aCache) {
+
+ /*
+
+캐싱되어 있는게 있으면 parent 가 같은건지 검사한후 aSingleQueryResult 에 대입
+
+ */
+ for (var j = 0, oCache; oCache = aCache[j]; j++) {
+ if (oCache.parent == oParent) {
+ aSingleQueryResult = oCache.result;
+ break;
+ }
+ }
+
+ }
+
+ if (!aSingleQueryResult) {
+
+ var fpFunction = parseQuery(sSingleQuery);
+ // alert(fpFunction);
+
+ cssquery._marked = [];
+ for (var j = 0, nDepth = fpFunction.depth; j < nDepth; j++)
+ cssquery._marked.push({});
+
+ // console.log(fpFunction.toSource());
+ aSingleQueryResult = distinct(fpFunction(oParent, oOptions));
+
+ /*
+
+결과 캐쉬를 사용중이면 캐쉬에 저장
+
+ */
+ if (bUseResultCache&&!oOptions.oneTimeOffCache) {
+ if (!(oResultCache[sResultCacheKey] instanceof Array)) oResultCache[sResultCacheKey] = [];
+ oResultCache[sResultCacheKey].push({ parent : oParent, result : aSingleQueryResult });
+ }
+
+ }
+
+ aResult = aResult.concat(aSingleQueryResult);
+
+ }
+ unsetNodeIndexes();
+
+ return aResult;
+
+ })(sQuery, oParent, oOptions);
+
+ }
+
+ executeTime = new Date().getTime() - executeTime;
+
+ if (debugOption.callback) debugOption.callback(sQuery, cost, executeTime);
+
+ return aRet;
+
+ };
+ var cssquery;
+ if (document.querySelectorAll) {
+ function _isNonStandardQueryButNotException(sQuery){
+ return /\[\s*(?:checked|selected|disabled)/.test(sQuery)
+ }
+ function _commaRevise (sQuery,sChange) {
+ return sQuery.replace(/\,/gi,sChange);
+ }
+
+ var protoSlice = Array.prototype.slice;
+
+ var _toArray = function(aArray){
+ return protoSlice.apply(aArray);
+ }
+
+ try{
+ protoSlice.apply(document.documentElement.childNodes);
+ }catch(e){
+ _toArray = function(aArray){
+ var returnArray = [];
+ var leng = aArray.length;
+ for ( var i = 0; i < leng; i++ ) {
+ returnArray.push( aArray[i] );
+ }
+ return returnArray;
+ }
+ }
+ /**
+
+ */
+ cssquery = function(sQuery, oParent, oOptions){
+ oParent = oParent || document ;
+ try{
+ if (_isNonStandardQueryButNotException(sQuery)) {
+ throw Error("None Standard Query");
+ }else{
+ var sReviseQuery = sQuery;
+ var oReviseParent = oParent;
+ if (oParent.nodeType != 9) {
+ if(bExtremeMode){
+ if(!oParent.id) oParent.id = "p"+ new Date().getTime() + parseInt(Math.random() * 100000000,10);
+ }else{
+ throw Error("Parent Element has not ID.or It is not document.or None Extreme Mode.");
+ }
+ sReviseQuery = _commaRevise("#"+oParent.id+" "+sQuery,", #"+oParent.id);
+ oReviseParent = oParent.ownerDocument||oParent.document||document;
+ }
+ if (oOptions&&oOptions.single) {
+ return [oReviseParent.querySelector(sReviseQuery)];
+ }else{
+ return _toArray(oReviseParent.querySelectorAll(sReviseQuery));
+ }
+ }
+ }catch(e){
+ return old_cssquery(sQuery, oParent, oOptions);
+ }
+ }
+ }else{
+ cssquery = old_cssquery;
+ }
+ /**
+
+ * @function
+ * @name $$.test
+ * @description test() 메서드는 특정 요소가 해당 CSS 선택자(CSS Selector)에 부합하는 요소인지 판단하여 Boolean 형태로 반환한다. CSS 선택자에 연결자는 사용할 수 없음에 유의한다. 선택자의 패턴에 대한 설명은 $$() 함수와 See Also 항목을 참고한다.
+ * @param {Element} element 검사하고자 하는 요소
+ * @param {String} sCSSSelector CSS 선택자. CSS 선택자로 사용할 수 있는 패턴은 표준 패턴과 비표준 패턴이 있다. 표준 패턴은 CSS Level3 명세서에 있는 패턴을 지원한다.
+ * @return {Boolean} 조건에 부합하면 true, 부합하지 않으면 false를 반환한다.
+ * @see $$
+ * @see
CSS Level3 명세서 - W3C
+ * @example
+// oEl 이 div 태그 또는 p 태그, 또는 align 속성이 center로 지정된 요소인지 검사한다.
+if (cssquery.test(oEl, 'div, p, [align=center]'))
+alert('해당 조건 만족');
+
+ */
+ cssquery.test = function(oEl, sQuery) {
+
+ clearKeys();
+
+ var aFunc = parseTestQuery(sQuery);
+ for (var i = 0, nLen = aFunc.length; i < nLen; i++){
+ if (aFunc[i](oEl)) return true;
+ }
+
+
+ return false;
+
+ };
+
+ /**
+
+ * @function
+ * @name $$.useCache
+ * @description useCache() 메서드는 $$() 함수(cssquery)를 사용할 때 캐시를 사용할 것인지 설정한다. 캐시를 사용하면 동일한 선택자로 탐색하는 경우 탐색하지 않고 기존 탐색 결과를 반환한다. 따라서 사용자가 변수 캐시를 신경쓰지 않고 편하고 빠르게 사용할 수 있는 장점이 있지만 신뢰성을 위해 DOM 구조가 동적으로 변하지 않을 때만 사용해야 한다.
+ * @param {Boolean} [bFlag] 캐시 사용 여부를 지정한다. 이 파라미터를 생략하면 캐시 사용 상태만 반환한다.
+ * @return {Boolean} 캐시 사용 상태를 반환한다.
+ * @see
$$.clearCache
+
+ */
+ cssquery.useCache = function(bFlag) {
+
+ if (typeof bFlag != 'undefined') {
+ bUseResultCache = bFlag;
+ cssquery.clearCache();
+ }
+
+ return bUseResultCache;
+
+ };
+
+ /**
+
+ * @function
+ * @name $$.clearCache
+ * @description clearCache() 메서드는 $$() 함수(cssquery)에서 캐시를 사용할 때 캐시를 비울 때 사용한다. DOM 구조가 동적으로 바껴 기존의 캐시 데이터가 신뢰성이 없을 때 사용한다.
+ * @return {void}
+ * @see
$$.useCache
+
+ */
+ cssquery.clearCache = function() {
+ oResultCache = {};
+ };
+
+ /**
+
+ * @function
+ * @name $$.getSingle
+ * @description getSingle() 메서드는 CSS 선택자를 사용에서 조건을 만족하는 첫 번째 요소를 가져온다. 반환하는 값은 배열이 아닌 객채 또는 null이다. 조건을 만족하는 요소를 찾으면 바로 탐색 작업을 중단하기 때문에 결과가 하나라는 보장이 있을 때 빠른 속도로 결과를 가져올 수 있다.
+ $$() 함수(cssquery)에서 캐시를 사용할 때 캐시를 비울 때 사용한다. DOM 구조가 동적으로 바껴 기존의 캐시 데이터가 신뢰성이 없을 때 사용한다.
+ * @param {String} sSelector CSS 선택자(CSS Selector). CSS 선택자로 사용할 수 있는 패턴은 표준 패턴과 비표준 패턴이 있다. 표준 패턴은 CSS3 Level3 명세서에 있는 패턴을 지원한다. 선택자의 패턴에 대한 설명은 $$() 함수와 See Also 항목을 참고한다.
+ * @param {Element} [oBaseElement] 탐색 대상이 되는 DOM 요소. 지정한 요소의 하위 노드에서만 객체를 탐색한다. 생략될 경우 문서를 대상으로 찾는다.
+ * @param {Object} [oOption] 옵션 객체에 onTimeOffCache 속성을 true로 설정하면 탐색할 때 캐시를 사용하지 않는다.
+ * @return {Element} 선택된 요소. 결과가 없으면 null을 반환한다.
+ * @see $Document#query
+ * @see
$$.useCache
+ * @see $$
+ * @see
CSS Level3 명세서 - W3C
+
+ */
+ cssquery.getSingle = function(sQuery, oParent, oOptions) {
+
+ return cssquery(sQuery, oParent, { single : true ,oneTimeOffCache:oOptions?(!!oOptions.oneTimeOffCache):false})[0] || null;
+ };
+
+
+ /**
+
+ * @function
+ * @name $$.xpath
+ * @description xpath() 메서드는 XPath 문법을 만족하는 요소를 가져온다. 지원하는 문법이 제한적이므로 특수한 경우에만 사용할 것을 권장한다.
+ * @param {String} sXPath XPath 값.
+ * @param {Element} [elBaseElement] 탐색 대상이 되는 DOM 요소. 지정한 요소의 하위 노드에서만 객체를 탐색한다. 생략될 경우 문서를 대상으로 찾는다.
+ * @return {Array} XPath 문법을 만족하는 요소를 원소로 하는 배열. 결과가 없으면 null을 반환한다.
+ * @see $Document#xpathAll
+ * @see
XPath 문서 - W3C
+
+ */
+ cssquery.xpath = function(sXPath, oParent) {
+
+ var sXPath = sXPath.replace(/\/(\w+)(\[([0-9]+)\])?/g, function(_1, sTag, _2, sTh) {
+ sTh = sTh || '1';
+ return '>' + sTag + ':nth-of-type(' + sTh + ')';
+ });
+
+ return old_cssquery(sXPath, oParent);
+
+ };
+
+ /**
+
+ * @function
+ * @name $$.debug
+ * @description debug() 메서드는 $$() 함수(cssquery)를 사용할 때 성능을 측정하기 위한 기능을 제공하는 함수이다. 파라미터로 입력한 콜백 함수를 사용하여 성능을 측정한다.
+ * @param {Function} fCallback 선택자 실행에 소요된 비용과 시간을 점검하는 함수. 이 파라미터에 함수 대신 false를 입력하면 성능 측정 모드(debug)를 사용하지 않는다. 이 콜백 함수는 파라미터로 query, cost, executeTime을 갖는다.
+
+ query는 실행에 사용된 선택자이다.
+ index는 탐색에 사용된 비용이다(루프 횟수).
+ executeTime 탐색에 소요된 시간이다.
+ * @param {Number} [nRepeat] 하나의 선택자를 반복 수행할 횟수. 인위적으로 실행 속도를 늦추기 위해 사용할 수 있다.
+ * @return {Void}
+ * @example
+cssquery.debug(function(sQuery, nCost, nExecuteTime) {
+ if (nCost > 5000)
+ console.warn('5000이 넘는 비용이? 확인 -> ' + sQuery + '/' + nCost);
+ else if (nExecuteTime > 200)
+ console.warn('0.2초가 넘게 실행을? 확인 -> ' + sQuery + '/' + nExecuteTime);
+}, 20);
+
+....
+
+cssquery.debug(false);
+
+ */
+ cssquery.debug = function(fpCallback, nRepeat) {
+
+ debugOption.callback = fpCallback;
+ debugOption.repeat = nRepeat || 1;
+
+ };
+
+ /**
+
+ * @function
+ * @name $$.safeHTML
+ * @description safeHTML() 메서드는 인터넷 익스플로러에서 innerHTML 속성을 사용할 때 _cssquery_UID 값이 나오지 않게 하는 함수이다. true로 설정하면 탐색하는 노드의 innerHTML 속성에 _cssquery_UID가 나오지 않게 할 수 있지만 탐색 속도는 느려질 수 있다.
+ * @param {Boolean} bFlag _cssquery_UID의 표시 여부를 지정한다. true로 설정하면 _cssquery_UID가 나오지 않는다.
+ * @return {Boolean} _cssquery_UID 표시 여부 상태를 반환한다. _cssquery_UID를 표시하는 상태이면 true를 반환하고 그렇지 않으면 false를 반환한다.
+
+ */
+ cssquery.safeHTML = function(bFlag) {
+
+ var bIE = /MSIE/.test(window.navigator.userAgent);
+
+ if (arguments.length > 0)
+ safeHTML = bFlag && bIE;
+
+ return safeHTML || !bIE;
+
+ };
+
+ /**
+
+ * @field
+ * @name $$.version
+ * @description version 속성은 cssquery의 버전 정보를 담고 있는 문자열이다.
+
+ */
+ cssquery.version = sVersion;
+
+ /**
+
+ * IE에서 validUID,cache를 사용했을때 메모리 닉이 발생하여 삭제하는 모듈 추가.
+
+ */
+ cssquery.release = function() {
+ if(/MSIE/.test(window.navigator.userAgent)){
+
+ delete validUID;
+ validUID = {};
+
+ if(bUseResultCache){
+ cssquery.clearCache();
+ }
+ }
+ };
+ /**
+
+ * cache가 삭제가 되는지 확인하기 위해 필요한 함수
+ * @ignore
+
+ */
+ cssquery._getCacheInfo = function(){
+ return {
+ uidCache : validUID,
+ eleCache : oResultCache
+ }
+ }
+ /**
+
+ * 테스트를 위해 필요한 함수
+ * @ignore
+
+ */
+ cssquery._resetUID = function(){
+ UID = 0
+ }
+ /**
+
+ * querySelector가 있는 브라우져에서 extreme을 실행시키면 querySelector을 사용할수 있는 커버리지가 높아져 전체적으로 속도가 빨리진다.
+ * 하지만 ID가 없는 엘리먼트를 기준 엘리먼트로 넣었을 때 기준 엘리먼트에 임의의 아이디가 들어간다.
+ * @param {Boolean} bExtreme true
+
+ */
+ cssquery.extreme = function(bExtreme){
+ if(arguments.length == 0){
+ bExtreme = true;
+ }
+ bExtremeMode = bExtreme;
+ }
+
+ return cssquery;
+
+})();
+
+
+
/**
+
+ * @fileOverview $Agent() 객체의 생성자 및 메서드를 정의한 파일
+ * @author Kim, Taegon
+
+ */
+
+/**
+
+ * @class $Agent() 객체는 운영체제, 브라우저를 비롯한 사용자 시스템 정보를 제공한다.
+ * @constructor
+ * @description $Agent() 객체를 생성한다. $Agent() 객체는 사용자 시스템의 운영 체제 정보와 브라우저 정보를 제공한다.
+
+ */
+jindo.$Agent = function() {
+ var cl = arguments.callee;
+ var cc = cl._cached;
+
+ if (cc) return cc;
+ if (!(this instanceof cl)) return new cl;
+ if (!cc) cl._cached = this;
+
+ this._navigator = navigator;
+}
+
+/**
+
+ * @description navigator() 메서드는 사용자 브라우저 정보를 담고 있는 객체를 반환한다. 브라우저 정보를 저장하는 객체는 브라우저 이름과 버전을 속성으로 가진다. 브라우저 이름은 영어 소문자로 표시하며, 사용자의 브라우저와 일치하는 브라우저 속성은 true 값을 가진다. 또한, 사용자의 브라우저 이름을 확인할 수 있도록 메서드를 제공한다. 다음은 사용자 브라우저 정보를 담고 있는 객체의 속성과 메서드를 설명한 표이다.
+
+ 브라우저 정보 객체 속성
+
+
+ 이름
+ 타입
+ 설명
+
+
+
+
+ camino
+ Boolean
+ 카미노(Camino) 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ chrome
+ Boolean
+ 구글 크롬(Chrome) 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ firefox
+ Boolean
+ 파이어폭스(Firefox) 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ icab
+ Boolean
+ iCab 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ ie
+ Boolean
+ 인터넷 익스플로러(Internet Explorer) 사용 여부를 불리언 형태로 저장한다.
+
+
+ konqueror
+ Boolean
+ Konqueror 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ mie
+ Boolean
+ 인터넷 익스플로러 모바일(Internet Explorer Mobile) 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ mobile
+ Boolean
+ 모바일 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ mozilla
+ Boolean
+ 모질라(Mozilla) 계열의 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ msafari
+ Boolean
+ Mobile 버전 Safari 사용 여부를 불리언 형태로 저장한다.
+
+
+ nativeVersion
+ Number
+ 인터넷 익스플로러 호환 모드의 브라우저를 사용할 경우 실제 브라우저를 저장한다.
+
+
+ netscape
+ Boolean
+ 넷스케이프(Netscape) 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ omniweb
+ Boolean
+ OmniWeb 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ opera
+ Boolean
+ 오페라(Opera) 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ safari
+ Boolean
+ Safari 브라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+ version
+ Number
+ 사용자가 사용하고 있는 브라우저의 버전 정보를 저장한다. 실수(Float) 형태로 버전 정보를 저장하며 버전 정보가 없으면 -1 값을 가진다.
+
+
+ webkit
+ WebKit 계열 부라우저 사용 여부를 불리언 형태로 저장한다.
+
+
+
+
+ 브라우저 정보 객체 메서드
+
+
+ 이름
+ 반환 타입
+ 설명
+
+
+
+
+ getName()
+ String
+ 사용자가 사용하고 있는 브라우저의 이름을 반환한다. 반환하는 브라우저의 이름은 속성 이름과 동일하다.
+
+
+
+ * @return {Object} 브라우저 정보를 저장하는 객체.
+ * @since 1.4.3 버전부터 mobile,msafari,mopera,mie 사용 가능. 1.4.5 버전부터 ipad에서 mobile은 false를 반환한다.
+ * @example
+oAgent = $Agent().navigator(); // 사용자가 파이어폭스 3를 사용한다고 가정한다.
+
+oAgent.camino // false
+oAgent.firefox // true
+oAgent.konqueror // false
+oAgent.mozilla //true
+oAgent.netscape // false
+oAgent.omniweb //false
+oAgent.opera //false
+oAgent.webkit /false
+oAgent.safari //false
+oAgent.ie //false
+oAgent.chrome //false
+oAgent.icab //false
+oAgent.version //3
+oAgent.nativeVersion //-1 (1.4.2부터 사용 가능, IE8에서 호환 모드 사용시 nativeVersion은 8로 나옴.)
+
+oAgent.getName() // firefox
+
+ */
+
+jindo.$Agent.prototype.navigator = function() {
+ var info = new Object;
+ var ver = -1;
+ var nativeVersion = -1;
+ var u = this._navigator.userAgent;
+ var v = this._navigator.vendor || "";
+
+ function f(s,h){ return ((h||"").indexOf(s) > -1) };
+
+ info.getName = function(){
+ var name = "";
+ for(x in info){
+ if(typeof info[x] == "boolean" && info[x]&&info.hasOwnProperty(x))
+ name = x;
+ }
+ return name;
+ }
+
+ info.webkit = f("WebKit",u);
+ info.opera = (typeof window.opera != "undefined") || f("Opera",u);
+ info.ie = !info.opera && f("MSIE",u);
+ info.chrome = info.webkit && f("Chrome",u);
+ info.safari = info.webkit && !info.chrome && f("Apple",v);
+ info.firefox = f("Firefox",u);
+ info.mozilla = f("Gecko",u) && !info.safari && !info.chrome && !info.firefox;
+ 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);
+
+ info.mobile = (f("Mobile",u)||f("Android",u)||f("Nokia",u)||f("webOS",u)||f("Opera Mini",u)||f("BlackBerry",u)||(f("Windows",u)&&f("PPC",u))||f("Smartphone",u)||f("IEMobile",u))&&!f("iPad",u);
+ info.msafari = (!f("IEMobile",u) && f("Mobile",u))||(f("iPad",u)&&f("Safari",u));
+ info.mopera = f("Opera Mini",u);
+ info.mie = f("PPC",u)||f("Smartphone",u)||f("IEMobile",u);
+
+ try {
+
+ if (info.ie) {
+ ver = u.match(/(?:MSIE) ([0-9.]+)/)[1];
+ if (u.match(/(?:Trident)\/([0-9.]+)/)){
+ var nTridentNum = parseInt(RegExp.$1,10);
+ if(nTridentNum > 3){
+ nativeVersion = nTridentNum + 4;
+ }
+ }
+ } else if (info.safari||info.msafari) {
+
+ ver = parseFloat(u.match(/Safari\/([0-9.]+)/)[1]);
+ if (ver == 100) {
+ ver = 1.1;
+ } else {
+ if(u.match(/Version\/([0-9.]+)/)){
+ ver = RegExp.$1;
+ }else{
+ ver = [1.0,1.2,-1,1.3,2.0,3.0][Math.floor(ver/100)];
+
+ }
+ }
+ } else if(info.mopera){
+ ver = u.match(/(?:Opera\sMini)\/([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.icab) {
+ ver = u.match(/iCab[ \/]([0-9.]+)/)[1];
+ } else if (info.chrome) {
+ ver = u.match(/Chrome[ \/]([0-9.]+)/)[1];
+ }
+
+ info.version = parseFloat(ver);
+ info.nativeVersion = parseFloat(nativeVersion);
+ if (isNaN(info.version)) info.version = -1;
+ } catch(e) {
+ info.version = -1;
+ }
+
+ this.navigator = function() {
+ return info;
+ };
+
+ return info;
+};
+
+/**
+
+ * @description os() 메서드는 사용자 운영체제 정보를 담고 있는 객체를 반환한다. 운영체제 정보를 저장하는 객체는 운영체제 이름을 속성으로 가진다. 운영 체제 속성은 영어 소문자로 표시하며, 사용자의 운영체제와 일치하는 운영체제의 속성은 true 값을 가진다. 또한 사용자의 운영체제 이름을 확인할 수 있도록 메서드를 제공한다. 다음은 사용자 운영체제 정보를 담고 있는 객체의 속성과 메서드를 설명한 표이다.
+
+ 운영체제 정보 객체 속성
+
+
+ 이름
+ 타입
+ 설명
+
+
+
+
+ android
+ Boolean
+ Android 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ blackberry
+ Boolean
+ Blackberry 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ iphone
+ Boolean
+ iPhone 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ linux
+ Boolean
+ Linux운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ mac
+ Boolean
+ Mac운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ mwin
+ Boolean
+ Window Mobile 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ nokia
+ Boolean
+ Nokia 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ vista
+ Boolean
+ Windows Vista 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ webos
+ Boolean
+ webOS 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ win
+ Boolean
+ Windows계열 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ win2000
+ Boolean
+ Windows 2000운영체제 사용 여부 불리언 형태로 저장한다.
+
+
+ win7
+ Boolean
+ Windows 7 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ winxp
+ Boolean
+ Windows XP 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+ xpsp2
+ Boolean
+ Windows XP SP 2 운영체제 사용 여부를 불리언 형태로 저장한다.
+
+
+
+
+ 운영체제 정보 객체 메서드
+
+
+ 이름
+ 반환 타입
+ 설명
+
+
+
+
+ getName()
+ String
+ 사용자가 사용하고 있는 운영체제의 이름을 반환한다. 반환하는 운영체제의 이름은 속성 이름과 동일하다.
+
+
+
+ * @return {Object} 운영체제 정보를 저장하는 객체.
+ * @since 1.4.3 버전부터 iphone,android,nokia,webos,blackberry,mwin 사용 가능. 1.4.5 버전부터 ipad 사용가능.
+ * @example
+oOS = $Agent().os(); // 사용자의 운영체제가 Windows XP라고 가정한다.
+oOS.linux // false
+oOS.mac // false
+oOS.vista // false
+oOS.win // true
+oOS.win2000 // false
+oOS.winxp // true
+oOS.xpsp2 // false
+oOS.win7 // false
+oOS.getName() // winxp
+
+ */
+jindo.$Agent.prototype.os = function() {
+ var info = new Object;
+ var u = this._navigator.userAgent;
+ var p = this._navigator.platform;
+ var f = function(s,h){ return (h.indexOf(s) > -1) };
+
+ info.getName = function(){
+ var name = "";
+ for(x in info){
+
+ if(typeof info[x] == "boolean" && info[x]&&info.hasOwnProperty(x))
+ name = x;
+ }
+ return name;
+ }
+
+ info.win = f("Win",p)
+ info.mac = f("Mac",p);
+ info.linux = f("Linux",p);
+ info.win2000 = info.win && (f("NT 5.0",u) || f("2000",u));
+ info.winxp = info.win && f("NT 5.1",u);
+ info.xpsp2 = info.winxp && f("SV1",u);
+ info.vista = info.win && f("NT 6.0",u);
+ info.win7 = info.win && f("NT 6.1",u);
+ info.ipad = f("iPad",u);
+ info.iphone = f("iPhone",u) && !info.ipad;
+ info.android = f("Android",u);
+ info.nokia = f("Nokia",u);
+ info.webos = f("webOS",u);
+ info.blackberry = f("BlackBerry",u);
+ info.mwin = f("PPC",u)||f("Smartphone",u)||f("IEMobile",u);
+
+
+ this.os = function() {
+ return info;
+ };
+
+ return info;
+};
+
+/**
+
+ * @description flash() 메서드는 사용자의 Flash Player 정보를 담고 있는 객체를 반환한다. Flash Player 정보를 저장하는 객체는 Flash Player 설치 여부와 설치된 Flash Player의 버전 정보를 제공한다. 다음은 Flash Player의 정보를 담고 있는 객체의 속성을 설명한 표이다.
+
+ Flash Player 정보 객체 속성
+
+
+ 이름
+ 타입
+ 설명
+
+
+
+
+ installed
+ Boolean
+ Flash Player 설치 여부를 불리언 형태로 저장한다.
+
+
+ version
+ Number
+ 사용자가 사용하고 있는 Flash Player의 버전 정보를 저장한다. 실수(Float) 형태로 버전 정보를 저장하며, Flash Player가 설치되지 않은 경우 -1을 저장한다.
+
+
+
+ * @return {Object} Flash Player 정보를 저장하는 객체.
+ * @see Flash Player 공식 페이지
+ * @example
+var oFlash = $Agent.flash();
+oFlash.installed // 플래시 플레이어를 설치했다면 true
+oFlash.version // 플래시 플레이어의 버전.
+
+ */
+jindo.$Agent.prototype.flash = function() {
+ var info = new Object;
+ var p = this._navigator.plugins;
+ var m = this._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=10; i > 1; i--) {
+ try {
+ f = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ info.installed = true;
+ info.version = i;
+ break;
+ } catch(e) {}
+ }
+ }
+
+ this.flash = function() {
+ return info;
+ };
+ /*
+
+하위호환을 위해 일단 남겨둔다.
+
+ */
+ this.info = this.flash;
+
+ return info;
+};
+
+/**
+
+ * silverlight() 메서드는 사용자의 실버라이트(Silverlight) 정보를 담고 있는 객체를 반환한다.
+ * @description 실버라이트 정보를 저장하는 객체는 실버라이트 설치 여부와 설치된 실버라이트의 버전 정보를 제공한다. 다음은 실버라이트 정보를 담고 있는 객체의 속성을 설명한 표이다.
+
+ 실버라이트 정보 객체 속성
+
+
+ 이름
+ 타입
+ 설명
+
+
+
+
+ installed
+ Boolean
+ 실버라이트 설치 여부를 불리언 형태로 저장한다.
+
+
+ version
+ Number
+ 사용자가 사용하고 있는 실버라이트의 버전 정보를 저장한다. 실수(Float) 형태로 버전 정보를 저장하며, 실버라이트가 설치되지 않은 경우 -1을 저장한다.
+
+
+
+ * @returns {Object} 실버라이트 정보를 저장하는 객체.
+ * @see 실버라이트 공식 페이지
+ * @example
+var oSilver = $Agent.silverlight();
+oSilver.installed // Silverlight 플레이어를 설치했다면 true
+oSilver.version // Silverlight 플레이어의 버전.
+
+ */
+jindo.$Agent.prototype.silverlight = function() {
+ var info = new Object;
+ var p = this._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;
+ info.version = parseInt(s.description.split(".")[0],10);
+ if (s.description == "1.0.30226.2") info.version = 2;
+ }
+ } else {
+ try {
+ s = new ActiveXObject("AgControl.AgControl");
+ info.installed = true;
+ if(s.isVersionSupported("3.0")){
+ info.version = 3;
+ }else if (s.isVersionSupported("2.0")) {
+ info.version = 2;
+ } else if (s.isVersionSupported("1.0")) {
+ info.version = 1;
+ }
+ } catch(e) {}
+ }
+
+ this.silverlight = function() {
+ return info;
+ };
+
+ return info;
+};
+
+
/**
+
+ * @fileOverview $A() 객체의 생성자 및 메서드를 정의한 파일
+ * @name array.js
+ * @author Kim, Taegon
+
+ */
+
+/**
+
+ * @class $A() 객체는 배열(Array)을 좀 더 편리하게 다룰 수 있도록 메서드를 제공한다. $A() 객체를 생성할 때 원본 배열 객체를 래핑(warpping)하여 생성한다. 여기서 래핑이란 자바스크립트의 함수를 감싸 본래 함수의 기능에 새로운 확장 기능을 추가하는 것을 말한다.
+ * @extends core
+ * @constructor
+ * @description $A() 객체를 생성한다.
+ * @param {Variant} [vArray] 래핑할 배열(Array) 또는 $A() 객체. 생성자의 파라미터를 생략하면 빈 배열을 가진 새로운 $A() 객체를 반환한다.
+ * @example
+var zoo = ["zebra", "giraffe", "bear", "monkey"];
+var waZoo = $A(zoo); // ["zebra", "giraffe", "bear", "monkey"]를 래핑한 $A 객체를 생성하여 반환
+
+ */
+jindo.$A = function(array) {
+ var cl = arguments.callee;
+
+ if (typeof array == "undefined" || array == null) array = [];
+ if (array instanceof cl) return array;
+ if (!(this instanceof cl)) return new cl(array);
+
+ this._array = []
+ if (array.constructor != String) {
+ this._array = [];
+ for(var i=0; i < array.length; i++) {
+ this._array[this._array.length] = array[i];
+ }
+ }
+
+};
+
+/**
+
+* @description toString() 메서드는 내부 배열을 문자열로 변환한다. 자바스크립트의 Array.toString() 메서드를 사용한다.
+ * @return {String} 내부 배열을 변환한 문자열.
+ * @See array.toString() - MDN Docs
+ * @example
+var zoo = ["zebra", "giraffe", "bear", "monkey"];
+$A(zoo).toString();
+// 결과 : zebra,giraffe,bear,monkey
+
+ */
+jindo.$A.prototype.toString = function() {
+ return this._array.toString();
+};
+
+
+/**
+
+ * @description get() 메서드는 파라미터로 지정한 인덱스로 내부 배열의 원소 값을 조회한다.
+ * @param {Number} nIndex 조회할 원소의 인덱스. 인덱스는 0부터 시작한다.
+ * @return {Variant} 배열에서의 해당 인덱스의 원소 값.
+ * @since 1.4.2 부터 지원
+ * @example
+var zoo = ["zebra", "giraffe", "bear", "monkey"];
+var waZoo = $A(zoo);
+
+// 원소 값 조회
+waZoo.get(1); // 결과 : giraffe
+waZoo.get(3); // 결과 : monkey
+
+ */
+jindo.$A.prototype.get = function(nIndex){
+ return this._array[nIndex];
+};
+
+/**
+
+ * @description length() 메서드는 내부 배열 크기를 지정하거나 반환한다.
+ * @param {Number} [nLen] 지정할 배열의 크기. nLen이 기존 배열의 크기보다 크면 추가된 배열의 공간에 vValue 파라미터의 값으로 채운다. nLen 이 기존 배열의 크기보다 작으면 nLen번째 이후의 원소는 제거한다.
+ * @param {Variant} [vValue] 새로운 원소를 추가할 때 사용할 초기 값.
+ * @return {Variant} 이 메서드의 파라미터를 모두 생략하면 현재 내부 배열의 크기(Number)를 반환하고, 파라미터를 지정한 경우에는 내부 배열을 변경한 $A() 객체를 반환한다.
+ * @example
+var zoo = ["zebra", "giraffe", "bear", "monkey"];
+var birds = ["parrot", "sparrow", "dove"];
+
+// 배열의 크기 조회
+$A(zoo).length(); // 결과 : 4
+
+// 배열의 크기 지정 (원소가 삭제되는 경우)
+$A(zoo).length(2);
+// 결과 : ["zebra", "giraffe"]
+
+// 배열의 크기 지정 (원소가 추가되는 경우)
+$A(zoo).length(6, "(Empty)");
+// 결과 : ["zebra", "giraffe", "bear", "monkey", "(Empty)", "(Empty)"]
+
+$A(zoo).length(5, birds);
+// 결과 : ["zebra", "giraffe", "bear", "monkey", ["parrot", "sparrow", "dove"]]
+
+ */
+jindo.$A.prototype.length = function(nLen, oValue) {
+ if (typeof nLen == "number") {
+ var l = this._array.length;
+ this._array.length = nLen;
+
+ if (typeof oValue != "undefined") {
+ for(var i=l; i < nLen; i++) {
+ this._array[i] = oValue;
+ }
+ }
+
+ return this;
+ } else {
+ return this._array.length;
+ }
+};
+
+/**
+
+ * @description has() 메서드는 내부 배열에서 특정 값을 갖는 원소의 유무를 Boolean 형태로 반환한다.
+ * @param {Variant} vValue 검색할 값.
+ * @return {Boolean} 배열에서 매개 변수의 값과 동일한 원소를 찾으면 true를, 찾지 못하면 false를 반환한다.
+ * @see $A#indexOf
+ * @example
+var arr = $A([1,2,3]);
+
+// 값 검색
+arr.has(3); // 결과 : true
+arr.has(4); // 결과 : false
+
+ */
+jindo.$A.prototype.has = function(oValue) {
+ return (this.indexOf(oValue) > -1);
+};
+
+/**
+
+ * @description indexOf() 메서드는 내부 배열에서 특정 값을 갖는 원소를 검색하고 검색된 원소의 인덱스를 반환한다.
+ * @param {Variant} vValue 검색할 값.
+ * @return {Number} 검색된 원소의 인덱스. 인덱스는 0부터 시작한다. 파라미터와 같은 값을 가진 원소를 찾지 못하면 -1을 반환한다.
+ * @see $A#has
+ * @example
+var zoo = ["zebra", "giraffe", "bear"];
+va r waZoo = $A(zoo);
+
+ // 값 검색 후 인덱스 리턴
+ waZoo.indexOf("giraffe"); // 1
+ waZoo.indexOf("monkey"); // -1
+
+ */
+jindo.$A.prototype.indexOf = function(oValue) {
+ if (typeof this._array.indexOf != 'undefined') {
+ jindo.$A.prototype.indexOf = function(oValue) {
+ return this._array.indexOf(oValue);
+ }
+ }else{
+ jindo.$A.prototype.indexOf = function(oValue) {
+ for(var i=0; i < this._array.length; i++) {
+ if (this._array[i] == oValue) return i;
+ }
+ return -1;
+ }
+ }
+
+ return this.indexOf(oValue);
+};
+
+/**
+
+ * @description $value() 메서드는 내부 배열을 반환한다.
+ * @return {Array} 원본 배열
+ * @example
+var waNum = $A([1, 2, 3]);
+waNum.$value(); // 원래의 배열인 [1, 2, 3]이 반환된다.
+
+ */
+jindo.$A.prototype.$value = function() {
+ return this._array;
+};
+
+/**
+
+ * @description push() 메서드는 내부 배열에 하나 이상의 원소를 추가하고 배열의 크기를 반환한다.
+ * @param {Variant} vValue1 추가할 첫 번째 원소의 값.
+ * @param {Variant} […] …
+ * @param {Variant} [vValueN] 추가할 N 번째 원소의 값.
+ * @return {Number} 원소를 추가한 후 배열의 크기.
+ * @see $A#pop
+ * @see $A#shift
+ * @see $A#unshift
+ * @see array.push() - MDN Docs
+ * @example
+var arr = $A([1,2,3]);
+
+// 원소 추가
+arr.push(4); // 결과 : 4 반환, 내부 배열은 [1,2,3,4]로 변경 됨
+arr.push(5,6); // 결과 : 6 반환, 내부 배열은 [1,2,3,4,5,6]로 변경 됨
+
+ */
+jindo.$A.prototype.push = function(oValue1/*, ...*/) {
+ return this._array.push.apply(this._array, Array.prototype.slice.apply(arguments));
+};
+
+/**
+
+ * @description pop() 메서드는 내부 배열의 마지막 원소를 삭제한다.
+ * @return {Variant} 삭제한 원소.
+ * @see $A#push
+ * @see $A#shift
+ * @see $A#unshift
+ * @see array.pop() - MDN Docs
+ * @example
+var arr = $A([1,2,3,4,5]);
+
+arr.pop(); // 결과 : 5 반환, 내부 배열은 [1,2,3,4]로 변경 됨
+
+ */
+jindo.$A.prototype.pop = function() {
+ return this._array.pop();
+};
+
+/**
+
+ * @description shift() 메서드는 내부 배열의 모든 원소를 앞으로 한 칸씩 이동시킨다. 내부 배열의 첫 번째 원소는 삭제된다.
+ * @return {Variant} 삭제한 첫 번째 원소.
+ * @see $A#pop
+ * @see $A#push
+ * @see $A#unshift
+ * @see array.shift() - MDN Docs
+ * @example
+var arr = $A(['Melon','Grape','Apple','Kiwi']);
+
+arr.shift(); // 결과 : 'Melon' 반환, 내부 배열은 ["Grape", "Apple", "Kiwi"]로 변경 됨.
+
+ */
+jindo.$A.prototype.shift = function() {
+ return this._array.shift();
+};
+
+/**
+
+ * @description unshift() 메서드는 내부 배열의 맨 앞에 하나 이상의 원소를 삽입한다.
+ * @param {Variant} vValue1 삽입할 첫 번째 값.
+ * @param {Variant} […] …
+ * @param {Variant} [vValueN] 삽입할 N 번째 값.
+ * @return {Number} 원소를 추가한 후 배열의 크기
+ * @see $A#pop
+ * @see $A#push
+ * @see $A#shift
+ * @see array.unshift() - MDN Docs
+ * @example
+var arr = $A([4,5]);
+
+arr.unshift('c'); // 결과 : 3 반환, 내부 배열은 ["c", 4, 5]로 변경 됨.
+arr.unshift('a', 'b'); // 결과 : 5 반환, 내부 배열은 ["a", "b", "c", 4, 5]로 변경 됨.
+
+ */
+jindo.$A.prototype.unshift = function(oValue1/*, ...*/) {
+ this._array.unshift.apply(this._array, Array.prototype.slice.apply(arguments));
+
+ return this._array.length;
+};
+
+/**
+
+ * @description forEach() 메서드는 내부 배열의 모든 원소를 순회하면서 콜백 함수를 실행한다.
+ * @param {Function} fCallback 배열을 순회하면서 실행할 콜백 함수. 콜백 함수는 파라미터로 value, index, array를 갖는다.
+
+ value는 배열이 가진 원소의 값이다.
+ index는 해당 원소의 인덱스이다.
+ array는 배열 그 자체를 가리킨다.
+
+ * @param {Object} [oThis] 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 this 키워드의 실행 문맥(Execution Context)으로 사용할 객체.
+ * @return {$A} $A() 객체.
+ * @import core.$A[Break, Continue]
+ * @see $A#map
+ * @see $A#filter
+ * @example
+var waZoo = $A(["zebra", "giraffe", "bear", "monkey"]);
+
+waZoo.forEach(function(value, index, array) {
+ document.writeln((index+1) + ". " + value);
+});
+
+// 결과 :
+// 1. zebra
+// 2. giraffe
+// 3. bear
+// 4. monkey
+
+ * @example
+var waArray = $A([1, 2, 3]);
+
+waArray.forEach(function(value, index, array) {
+ array[index] += 10;
+});
+
+document.write(waArray.$value());
+// 결과 : 11, 12, 13 (내부 배열에 10씩 더해짐)
+
+ */
+jindo.$A.prototype.forEach = function(fCallback, oThis) {
+ if (typeof this._array.forEach == "function") {
+ jindo.$A.prototype.forEach = function(fCallback, oThis) {
+ var arr = this._array;
+ var errBreak = this.constructor.Break;
+ var errContinue = this.constructor.Continue;
+
+ function f(v,i,a) {
+ try {
+ fCallback.call(oThis, v, i, a);
+ } catch(e) {
+ if (!(e instanceof errContinue)) throw e;
+ }
+ };
+
+ try {
+ this._array.forEach(f);
+ } catch(e) {
+ if (!(e instanceof errBreak)) throw e;
+ }
+ return this;
+ }
+ }else{
+ jindo.$A.prototype.forEach = function(fCallback, oThis) {
+ var arr = this._array;
+ var errBreak = this.constructor.Break;
+ var errContinue = this.constructor.Continue;
+
+ function f(v,i,a) {
+ try {
+ fCallback.call(oThis, v, i, a);
+ } catch(e) {
+ if (!(e instanceof errContinue)) throw e;
+ }
+ };
+ 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;
+ }
+ }
+ return this.forEach(fCallback, oThis);
+};
+
+/**
+
+ * @description slice() 메서드는 내부 배열의 일부분을 추출한다.
+ * @param {Number} nStart 배열에서 추출할 부분의 시작 원소 인덱스. 인덱스는 0부터 시작한다.
+ * @param {Number} nEnd 배열에서 추출할 부분의 마지막 원소 바로 다음 인덱스.
+ * @return {$A} 내부 배열의 일부를 추출한 새로운 $A() 객체. nStart 값이 0보다 작거나 nStart 값이 nEnd보다 크거나 같으면 빈 배열을 가진 $A() 객체를 반환한다.
+ * @example
+var arr = $A([12, 5, 8, 130, 44]);
+var newArr = arr.slice(1,3);
+// 잘라낸 배열인 [5, 8]를 래핑한 $A 객체를 리턴한다. (원래의 배열은 변화 없음)
+
+ * @example
+var arr = $A([12, 5, 8, 130, 44]);
+var newArr = arr.slice(3,3);
+// []를 래핑한 $A 객체를 리턴한다.
+
+ */
+jindo.$A.prototype.slice = function(nStart, nEnd) {
+ var a = this._array.slice.call(this._array, nStart, nEnd);
+ return jindo.$A(a);
+};
+
+/**
+
+ * @description splice() 메서드는 내부 배열의 일부분을 삭제한다.
+ * @param {Number} nIndex 배열에서 삭제할 부분의 시작 원소 인덱스. 인덱스는 0부터 시작한다.
+ * @param {Number} [nHowMany] 시작 원소부터 삭제할 원소의 개수.
+ * 이 값과 vValue1, ..., vValueN 파라미터를 생략하면 nIndex 번째 원소부터 배열의 마지막 원소까지 삭제한다.
+ * 이 값을 0으로 지정하거나 지정하지 않고 vValue1, ..., vValueN 파라미터에 값을 지정하면 nIndex 번째 위치에 지정한 vValue1, ..., vValueN 값을 추가한다.
+ * @param {Variant} [vValue1] 삭제한 배열에 추가할 첫 번째 값. nIndex 인덱스에 지정한 값이 추가된다.
+ * @param {Variant} […] …
+ * @param {Variant} [vValueN] 삭제한 배열에 추가할 N 번째 값. nIndex + N 인덱스에 지정한 값이 추가된다.
+ * @returns {$A} 삭제한 원소를 래핑하는 새로운 $A() 객체. 삭제한 원소가 없을 경우 빈 배열을 가진 $A() 객체를 반환한다.
+ * @example
+var arr = $A(["angel", "clown", "mandarin", "surgeon"]);
+
+var removed = arr.splice(2, 0, "drum");
+// arr의 내부 배열은 ["angel", "clown", "drum", "mandarin", "surgeon"]로 인덱스 2에 drum이 추가 됨
+// removed의 내부 배열은 []로 삭제된 원소가 없음
+
+removed = arr.splice(3, 1);
+// arr의 내부 배열은 ["angel", "clown", "drum", "surgeon"]로 mandarin이 삭제 됨
+// removed의 내부 배열은 삭제된 원소 ["mandarin"]를 가짐
+
+removed = arr.splice(2, 1, "trumpet", "parrot");
+// arr의 내부 배열은 ["angel", "clown", "trumpet", "parrot", "surgeon"]로 drum이 삭제되고 새로운 원소가 추가 됨
+// removed의 내부 배열은 삭제된 원소 ["drum"]을 가짐
+
+removed = arr.splice(3);
+// arr의 내부 배열은 ["angel", "clown", "trumpet"]로 인덱스 3부터 마지막 원소가 삭제되었음
+// removed의 내부 배열은 삭제된 원소 ["parrot", "surgeon"]을 가짐
+
+ */
+jindo.$A.prototype.splice = function(nIndex, nHowMany/*, oValue1,...*/) {
+ var a = this._array.splice.apply(this._array, Array.prototype.slice.apply(arguments));
+
+ return jindo.$A(a);
+};
+
+/**
+
+ * @description shuffle() 메서드는 배열 원소의 순서를 무작위로 섞는다.
+ * @return {$A} 배열이 섞여진 $A() 객체
+ * @see $A#reverse
+ * @example
+var dice = $A([1,2,3,4,5,6]);
+
+dice.shuffle();
+document.write("You get the number " + dice.get(0));
+// 결과 : 1부터 6까지의 숫자 중 랜덤한 숫자
+
+ */
+jindo.$A.prototype.shuffle = function() {
+ this._array.sort(function(a,b){ return Math.random()>Math.random()?1:-1 });
+
+ return this;
+};
+
+/**
+
+ * @description reverse() 메서드는 배열 원소의 순서를 거꾸로 뒤집는다.
+ * @return {$A} 원소 순서를 뒤집은 $A() 객체
+ * @see $A#shuffle
+ * @example
+var arr = $A([1, 2, 3, 4, 5]);
+
+arr.reverse(); // 결과 : [5, 4, 3, 2, 1]
+
+ */
+jindo.$A.prototype.reverse = function() {
+ this._array.reverse();
+
+ return this;
+};
+
+/**
+
+ * @description empty() 메서드는 배열의 모든 원소를 제거하고, 빈 배열로 만든다.
+ * @return {$A} 배열의 원소가 제거된 $A() 객체
+ * @example
+var arr = $A([1, 2, 3]);
+
+arr.empty(); // 결과 : []
+
+ */
+jindo.$A.prototype.empty = function() {
+ return this.length(0);
+};
+
+/**
+
+ * @description Break() 메서드는 forEach(), filter(), map() 메서드의 루프를 중단한다. 내부적으로는 강제로 예외를 발생시키는 구조이므로, try - catch 영역에서 이 메서드를 실행하면 정상적으로 동작하지 않을 수 있다.
+ * @see $A#Continue
+ * @see $A#forEach
+ * @see $A#filter
+ * @see $A#map
+ * @example
+$A([1,2,3,4,5]).forEach(function(value,index,array) {
+ // 값이 4보다 크면 종료
+ if (value > 4) $A.Break();
+ ...
+});
+
+ */
+jindo.$A.Break = function() {
+ if (!(this instanceof arguments.callee)) throw new arguments.callee;
+};
+
+/**
+
+ * @description Continue() 메서드는 forEach(), filter(), map() 메서드의 루프에서 나머지 명령을 실행하지 않고 다음 루프로 건너뛴다. 내부적으로는 강제로 예외를 발생시키는 구조이므로, try - catch 영역에서 이 메서드를 실행하면 정상적으로 동작하지 않을 수 있다.
+ * @see $A#Break
+ * @see $A#forEach
+ * @see $A#filter
+ * @see $A#map
+ * @example
+$A([1,2,3,4,5]).forEach(function(value,index,array) {
+ // 값이 짝수면 처리를 하지 않음
+ if (value%2 == 0) $A.Continue();
+ ...
+});
+
+ */
+jindo.$A.Continue = function() {
+ if (!(this instanceof arguments.callee)) throw new arguments.callee;
+};
+
+
/**
+
+ * @fileOverview $A() 객체의 확장 메서드를 정의한 파일
+ * @name array.extend.js
+
+ */
+
+/**
+
+ * @description map() 메서드는 배열의 모든 원소를 순회하면서 콜백 함수를 실행하고 콜백 함수의 실행 결과를 배열의 원소에 설정한다.
+ * @param {Function} fCallback 배열을 순회하면서 실행할 콜백 함수. 콜백 함수에서 반환하는 값을 해당 원소의 값으로 재설정한다. 콜백 함수는 파라미터로 value, index, array를 갖는다.
+
+ value는 배열이 가진 원소의 값이다.
+ index는 해당 원소의 인덱스이다.
+ array는 배열 그 자체를 가리킨다.
+
+ * @param {Object} [oThis] 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 this 키워드의 실행 문맥(Execution Context) 사용할 객체.
+ * @return {$A} 콜백 함수의 수행 결과를 반영한 $A() 객체
+ * @see $A#forEach
+ * @see $A#filter
+ * @example
+var waZoo = $A(["zebra", "giraffe", "bear", "monkey"]);
+
+waZoo.map(function(value, index, array) {
+ return (index+1) + ". " + value;
+});
+// 결과 : [1. zebra, 2. giraffe, 3. bear, 4. monkey]
+
+ * @example
+var waArray = $A([1, 2, 3]);
+
+waArray.map(function(value, index, array) {
+ return value + 10;
+});
+
+document.write(waArray.$value());
+// 결과 : 11, 12, 13 (내부 배열에 10씩 더해짐)
+
+ */
+jindo.$A.prototype.map = function(fCallback, oThis) {
+
+
+ if (typeof this._array.map == "function") {
+ jindo.$A.prototype.map = function(fCallback, oThis) {
+ var arr = this._array;
+ var errBreak = this.constructor.Break;
+ var errContinue = this.constructor.Continue;
+
+ function f(v,i,a) {
+ try {
+ return fCallback.call(oThis, v, i, a);
+ } catch(e) {
+ if (e instanceof errContinue){
+ return v;
+ } else{
+ throw e;
+ }
+ }
+ };
+
+ try {
+ this._array = this._array.map(f);
+ } catch(e) {
+ if(!(e instanceof errBreak)) throw e;
+ }
+ return this;
+ }
+ }else{
+ jindo.$A.prototype.map = function(fCallback, oThis) {
+ var arr = this._array;
+ var returnArr = [];
+ var errBreak = this.constructor.Break;
+ var errContinue = this.constructor.Continue;
+
+ function f(v,i,a) {
+ try {
+ return fCallback.call(oThis, v, i, a);
+ } catch(e) {
+ if (e instanceof errContinue){
+ return v;
+ } else{
+ throw e;
+ }
+ }
+ };
+ for(var i=0; i < this._array.length; i++) {
+ try {
+ returnArr[i] = f(arr[i], i, arr);
+ } catch(e) {
+ if (e instanceof errBreak){
+ return this;
+ }else{
+ throw e;
+ }
+ }
+ }
+ this._array = returnArr;
+
+ return this;
+ }
+ }
+ return this.map(fCallback, oThis);
+};
+
+/**
+
+ * @description filter() 메서드는 배열의 모든 원소를 순회하면서 콜백 함수를 실행하고 콜백 함수가 true 값을 반환하는 원소만 모아 새로운 $A() 객체를 반환한다.
+ * @param {Function} fCallback 배열을 순회하면서 실행할 콜백 함수. 콜백 함수는 Boolean 형태로 값을 반환해야 한다. true 값을 반환하는 원소는 새로운 배열의 원소가 된다.
+
+ value는 배열이 가진 원소의 값이다.
+ index는 해당 원소의 인덱스이다.
+ array는 배열 그 자체를 가리킨다.
+
+ * @param {Object} [oThis] 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 this 키워드의 실행 문맥(Execution Context) 사용할 객체.
+ * @return {$A} 콜백 함수의 반환 값이 true인 원소로 이루어진 새로운 $A() 객체
+ * @see $A#forEach
+ * @see $A#map
+ * @example
+var arr = $A([1,2,3,4,5]);
+
+// 필터링 함수
+function filterFunc(value, index, array) {
+ if (value > 2) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+var newArr = arr.filter(filterFunc);
+
+document.write(arr.$value()); // 결과 : [1,2,3,4,5]
+document.write(newArr.$value()); // 결과 : [3,4,5]
+
+ */
+jindo.$A.prototype.filter = function(fCallback, oThis) {
+ if (typeof this._array.filter != "undefined") {
+ jindo.$A.prototype.filter = function(fCallback, oThis) {
+ return jindo.$A(this._array.filter(fCallback, oThis));
+ }
+ }else{
+ jindo.$A.prototype.filter = function(fCallback, oThis) {
+ var ar = [];
+
+ this.forEach(function(v,i,a) {
+ if (fCallback.call(oThis, v, i, a) === true) {
+ ar[ar.length] = v;
+ }
+ });
+
+ return jindo.$A(ar);
+ }
+ }
+ return this.filter(fCallback, oThis);
+};
+
+/**
+
+ * @description every() 메서드는 배열을 순회하면서 배열의 모든 원소가 콜백 함수에 설정한 조건을 만족하는지 검사한다. 모든 원소가 콜백 함수에서 true 값을 반환하면 true 값을 반환하고 그렇지 않으면 false 값을 반환한다. 콜백 함수가 수행 도중 한번이라도 false를 반환하면 바로 false 값을 반환한다.
+ * @param {Function} fCallback 배열을 순회하면서 실행할 콜백 함수. 콜백 함수는 Boolean 형태로 값을 반환해야 한다.
+
+ value는 배열이 가진 원소의 값이다.
+ index는 해당 원소의 인덱스이다.
+ array는 배열 그 자체를 가리킨다.
+
+ * @param {Object} [oThis] 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 this 키워드의 실행 문맥(Execution Context)으로 사용할 객체.
+ * @return {Boolean} 콜백 함수의 반환 값이 모두 true이면 true를 반환하고 그렇지 않으면 false를 반환한다.
+ * @see $A#some
+ * @example
+function isBigEnough(value, index, array) {
+ return (value >= 10);
+ }
+
+var try1 = $A([12, 5, 8, 130, 44]).every(isBigEnough); // 결과 : false
+var try2 = $A([12, 54, 18, 130, 44]).every(isBigEnough); // 결과 : true
+
+ */
+jindo.$A.prototype.every = function(fCallback, oThis) {
+ if (typeof this._array.every != "undefined"){
+ jindo.$A.prototype.every = function(fCallback, oThis) {
+ return this._array.every(fCallback, oThis);
+ }
+ }else{
+ jindo.$A.prototype.every = function(fCallback, oThis) {
+ var result = true;
+
+ this.forEach(function(v, i, a) {
+ if (fCallback.call(oThis, v, i, a) === false) {
+ result = false;
+ jindo.$A.Break();
+ }
+ });
+
+ return result;
+ }
+ }
+ return this.every(fCallback, oThis);
+};
+
+/**
+
+ * @description some() 메서드는 배열을 순회하면서 콜백 함수에 설정한 조건을 만족하는 원소가 있는지 검사한다. 조건을 만족하는 원소가 하나라도 있으면 true 값을 반환하고 그렇지 않으면 false 값을 반환한다. 콜백 함수가 수행 도중 한번이라도 true를 반환하면 바로 true 값을 반환한다.
+ * @param {Function} fCallback 배열을 순회하면서 실행할 콜백 함수. 콜백 함수는 Boolean 형태로 값을 반환해야 한다.
+
+ value는 배열이 가진 원소의 값이다.
+ index는 해당 원소의 인덱스이다.
+ array는 배열 그 자체를 가리킨다.
+
+ * @param {Object} [oThis] 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 this 키워드의 실행 문맥(Execution Context)으로 사용할 객체.
+ * @return {Boolean} 콜백 함수의 반환 값이 모두 false이면 false를 반환하고 그렇지 않으면 true를 반환한다.
+ * @see $A#every
+ * @example
+function twoDigitNumber(value, index, array) {
+ return (value >= 10 && value < 100);
+}
+
+var try1 = $A([12, 5, 8, 130, 44]).some(twoDigitNumber); // 결과 : true
+var try2 = $A([1, 5, 8, 130, 4]).some(twoDigitNumber); // 결과 : false
+
+ */
+jindo.$A.prototype.some = function(fCallback, oThis) {
+ if (typeof this._array.some != "undefined"){
+ jindo.$A.prototype.some = function(fCallback, oThis) {
+ return this._array.some(fCallback, oThis);
+ }
+ }else{
+ jindo.$A.prototype.some = function(fCallback, oThis) {
+ var result = false;
+ this.forEach(function(v, i, a) {
+ if (fCallback.call(oThis, v, i, a) === true) {
+ result = true;
+ jindo.$A.Break();
+ }
+ });
+ return result;
+ }
+ }
+ return this.some(fCallback, oThis);
+};
+
+/**
+
+ * @description refuse() 메서드는 배열에서 입력한 파라미터와 같은 값을 제외하여 새로운 $A() 객체를 생성한다. 제외할 값을 여러 개 지정할 수 있다.
+ * @param {Variant} vValue1 배열에서 제거할 첫 번째 값.
+ * @param {Variant} […] …
+ * @param {Variant} [vValueN] 배열에서 제거할 N 번째 값.
+ * @return {$A} 배열에서 특정 값을 제외한 새로운 $A() 객체
+ * @example
+var arr = $A([12, 5, 8, 130, 44]);
+
+var newArr1 = arr.refuse(12);
+
+document.write(arr); // 결과 : [12, 5, 8, 130, 44]
+document.write(newArr1); // 결과 : [5, 8, 130, 44]
+
+var newArr2 = newArr1.refuse(8, 44, 130);
+
+document.write(newArr1); // 결과 : [5, 8, 130, 44]
+document.write(newArr2); // 결과 : [5]
+
+ */
+jindo.$A.prototype.refuse = function(oValue1/*, ...*/) {
+ var a = jindo.$A(Array.prototype.slice.apply(arguments));
+ return this.filter(function(v,i) { return !a.has(v) });
+};
+
+/**
+
+ * @description unique() 메서드는 배열에서 중복되는 원소를 삭제한다.
+ * @return {$A} 중복되는 원소를 제거한 $A() 객체
+ * @example
+var arr = $A([10, 3, 2, 5, 4, 3, 7, 4, 11]);
+
+arr.unique(); // 결과 : [10, 3, 2, 5, 4, 7, 11]
+
+ */
+jindo.$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;
+};
+
+
/**
+
+ * @fileOverview $Ajax() 객체의 생성자 및 메서드를 정의한 파일
+ * @name Ajax.js
+ * @author Kim, Taegon
+
+ */
+
+/**
+
+ * @class $Ajax() 객체는 다양한 개발 환경에서 Ajax 요청과 응답을 쉽게 구현하기 위한 메서드를 제공한다.
+ * @extends core
+ * @constructor
+ * @description $Ajax() 객체는 서버와 브라우저 사이의 비동기 통신, 즉 Ajax 통신을 지원한다. $Ajax() 객체는 XHR 객체(XMLHTTPRequest)를 사용한 기본적인 방식과 함께 다른 도메인 사이의 통신을 위한 여러 방식을 제공한다. $Ajax() 객체의 기본적인 초기화 방식은 다음과 같다.
+
+ * @param {String} sUrl Ajax 요청을 보낼 서버의 URL.
+ * @param {Object} oOption $Ajax()에서 사용하는 콜백 함수, 통신 방식 등과 같은 다양한 정보를 정의한다. oOption 객체의 프로퍼티와 사용법에 대한 설명은 다음 표와 같다.
+
+ oOption 객체의 속성
+
+ 속성
+ 타입
+ 설명
+
+
+
+ type
+ String
+
+ Ajax 요청 방식. 생략하면 기본 값은 xhr이다.
+
+ xhr
+ 브라우저에 내장된 XMLHttpRequest 객체를 이용하여 Ajax 요청을 처리한다. text, xml, json 형식의 응답 데이터를 처리할 수 있다. 요청 실패 시 HTTP 응답 코드를 통해 원인 파악이 가능하다. 단, 크로스 도메인(Cross-Domain) 상황에서 사용할 수 없다.
+
+ iframe
+ iframe 요소를 프록시로 사용하여 Ajax 요청을 처리한다. 크로스 도메인 상황에서 사용할 수 있다. iframe 요청 방식은 다음과 같이 동작한다.
+
+ 로컬(요청 하는 쪽)과 원격(요청 받는 쪽)에 모두 프록시용 HTML 파일을 만든다.
+ 로컬 프록시에서 원격 프록시로 데이터를 요청한다.
+ 원격 프록시가 원격 도메인에 XHR 방식으로 다시 Ajax 요청한다.
+ 응답을 받은 원격 프록시에서 로컬 프록시로 데이터를 전달한다.
+ 로컬 프록시에서 최종적으로 콜백 함수(onload)를 호출하여 처리한다.
+
+
+ 로컬 프록시 파일과 원격 프록시 파일은 다음과 같이 작성할 수 있다.
+
+ 원격 프록시 파일 : ajax_remote_callback.html
+ 로컬 프록시 파일 : ajax_local_callback.html
+
+ ※ iframe 요소를 사용한 방식은 인터넷 익스플로러에서 "딱딱"하는 페이지 이동음이 발생할 수 있다(요청당 2회).
+
+ jsonp
+ JSON 형식과 <script> 태그를 사용하여 사용하여 Ajax 요청을 처리한다. 크로스 도메인 상황에서 사용할 수 있다. jsonp 요청 방식은 다음과 같이 동작한다.
+
+ <script> 태그를 동적으로 생성한다. 이때 요청할 원격 페이지를 src 속성으로 입력하여 GET 방식으로 요청을 전송한다.
+ 요청 시에 콜백 함수를 매개 변수로 넘기면, 원격 페이지에서 전달받은 콜백 함수명으로 아래와 같이 응답을 보낸다.
+
+ function_name(...결과 값...)
+
+
+ 응답은 콜백 함수(onload)에서 처리된다.
+
+ ※ GET 방식만 가능하므로, 전송 데이터의 길이는 URL에서 허용하는 길이로 제한된다.
+
+ flash
+ 플래시 객체를 사용하여 Ajax 요청을 처리한다. 크로스 도메인 상황에에서 사용할 수 있다. 이 방식을 사용할 때 원격 서버의 웹 루트 디렉터리에 crossdomain.xml 파일이 존재해야 하며 해당 파일에 접근 권한이 설정되어 있어야 한다. 모든 통신은 플래시 객체를 통하여 주고 받으며 Ajax 요청을 시도하기 전에 반드시 플래시 객체를 초기화해야 한다. $Ajax.SWFRequest.write() 메서드를 사용하여 플래시 객체를 초기화하며 해당 메서드는 <body> 요소 안에 작성한다.
+
+
+
+
+
+ method
+ String
+
+ HTTP 요청 방식으로 post, get, put, delete 방식을 지원한다.
+
+ post
+ post 방식으로 http 요청을 전달한다. 기본 값이다.
+ get
+ get 방식으로 http 요청을 전달한다. type 속성이 "jsonp" 방식으로 지정되면 HTTP 요청 방식은 "get"으로 설정된다.
+ put
+ put 방식으로 http 요청을 전달한다. 1.4.2 부터 사용 가능하다.
+ delete
+ delete 방식으로 http 요청을 전달한다. 1.4.2 부터 사용 가능하다.
+
+
+
+
+ timeout
+ Number
+
+ 요청 타임 아웃 시간(초 단위).
+ 기본 값은 0으로 타임 아웃을 적용하지 않는다. 타임 아웃 시간 안에 요청이 완료되지 않으면 Ajax 요청을 중지한다. 비동기 호출인 경우에만 사용 가능하다.
+
+
+
+ onload
+ Function
+
+ 요청이 완료되면 실행할 콜백 함수.
+ 반드시 지정해야 하며 콜백 함수의 파라미터로 응답 객체인 {@link $Ajax.Response} 객체가 전달된다.
+
+
+
+ onerror
+ Function
+
+ 요청이 실패하면 실행할 콜백 함수.
+ 생략하면 오류가 발생해도 onload 속성에 지정한 콜백 함수를 실행한다.
+
+
+
+ ontimeout
+ Function
+
+ 타임 아웃이 되었을 때 실행할 콜백 함수.
+ 생략하면 타임 아웃 발생해도 아무런 처리를 하지 않는다.
+
+
+
+ proxy
+ String
+
+ 로컬 프록시 파일의 경로.
+ type 속성이 "iframe"일 때 사용하며 반드시 지정해야 한다.
+
+
+
+ jsonp_charset
+ String
+
+ 요청 시 사용할 <script> 인코딩 방식.
+ type 속성이 "jsonp"일 때 사용한다. 생략하면 "utf-8"이 기본값이다(0.4.2 버전부터 지원).
+
+
+
+ callbackid
+ String
+
+ 콜백 함수 이름에 사용할 ID.
+ type 속성이 "jsonp"일 때 사용한다(1.3.0 부터 지원). 생략하면 랜덤한 ID 값이 생성된다.
+ jsonp 방식에서 Ajax 요청할 때 콜백 함수 이름에 랜덤한 ID 값을 덧붙여 만든 콜백 함수 이름을 서버로 전달한다. 이때 랜덤한 값을 ID로 사용하여 넘기므로 요청 URL이 매번 새롭게 생성되어 캐쉬 서버가 아닌 서버로 직접 데이터를 요청하게 된다. 따라서 ID 값을 지정하면 랜덤한 아이디 값으로 콜백 함수 이름을 생성하지 않으므로 캐쉬 서버를 사용하여 그에 대한 히트율을 높이고자 할 때 ID를 지정하여 사용할 수 있다.
+
+
+
+ callbackname
+ String
+
+ 콜백 함수 이름.
+ type 속성이 "jsonp"일 때 사용하며, 서버에 요청할 콜백 함수의 이름을 지정할 수 있다. 기본 값은 "_callback"이다(1.3.8 부터 지원).
+
+
+
+ sendheader
+ Boolean
+
+ 요청 헤더를 전송할지 여부.
+ type 속성이 "flash"일 때 사용하며, 서버에서 접근 권한을 설정하는 crossdomain.xml에 allow-header가 없는 경우에 false 로 설정해야 한다.
+ 플래시 9에서는 allow-header가 false인 경우 get 방식으로만 ajax 통신이 가능하다.
+ 플래시 10에서는 allow-header가 false인 경우 get,post 둘다 ajax 통신이 안된다.
+ allow-header가 설정되어 있지 않다면 반드시 false로 설정해야 한다. 기본 값은 true 이다(1.3.4부터 지원).
+
+
+
+ async
+ Boolean
+
+ 비동기 호출 여부.
+ type 속성이 "xhr"일 때 이 속성 값이 유효하다. 기본 값은 true 이다(1.3.7부터 지원).
+
+
+
+ decode
+ Boolean
+
+ type 속성이 "flash"일 때 사용하며, 요청한 데이터 안에 utf-8 이 아닌 다른 인코딩이 되어 있을때 false 로 지정한다. 기본 값은 true 이다(1.4.0부터 지원).
+
+
+
+ postBody
+ Boolean
+
+ Ajax 요청 시 서버로 전달할 데이터를 Body 요소에 전달할 지의 여부.
+ type 속성이 "xhr"이고 method가 "get"이 아니어야 유효하며 REST 환경에서 사용된다. 기본값은 false 이다(1.4.2부터 지원).
+
+
+
+
+
+ * @see $Ajax.Response
+ * @see Cross Domain Ajax 이해
+ * @example
+// 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
+// (1) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - xhr
+
+// [client.html]
+
+
+
+ Ajax Sample
+
+
+
+
+
+ Get List
+
+
+
+
+
+// [server.php]
+첫번째두번째 세번째 ";
+?>
+
+ * @example
+// 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
+// (2) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - iframe
+
+// [http://local.com/some/client.html]
+
+
+
+ Ajax Sample
+
+
+
+
+
+ Get List
+
+
+
+
+
+// [http://server.com/some/some.php]
+첫번째두번째 세번째 ";
+?>
+
+ * @example
+// 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
+// (3) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - jsonp
+
+// [http://local.com/some/client.html]
+
+
+
+ Ajax Sample
+
+
+
+
+
+ Get List
+
+
+
+
+
+// [http://server.com/some/some.php]
+
+
+ * @example
+// 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
+// (4) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - flash
+
+// [http://local.com/some/client.html]
+
+
+
+ Ajax Sample
+
+
+
+
+
+
+ Get List
+
+
+
+
+
+// [http://server.com/some/some.php]
+첫번째두번째 세번째 ";
+?>
+
+ */
+jindo.$Ajax = function (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._status = 0;
+ this._url = url;
+ this._options = new Object;
+ this._headers = new Object;
+ this._options = {
+ type :"xhr",
+ method :"post",
+ proxy :"",
+ timeout:0,
+ onload :function(req){},
+ onerror :null,
+ ontimeout:function(req){},
+ jsonp_charset : "utf-8",
+ callbackid : "",
+ callbackname : "",
+ sendheader : true,
+ async : true,
+ decode :true,
+ postBody :false
+ };
+ this.option(option);
+
+ /*
+
+테스트를 위해 우선 적용가능한 설정 객체가 존재하면 적용
+
+ */
+ if(jindo.$Ajax.CONFIG){
+ this.option(jindo.$Ajax.CONFIG);
+ }
+
+ 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 "put":
+ case "delete":
+ case "get":
+ case "post":
+ _opt.method = _opt.type;
+ _opt.type = "xhr";
+ case "xhr":
+ this._request = _getXHR();
+ break;
+ case "flash":
+ if(!jindo.$Ajax.SWFRequest) throw Error('Require jindo.$Ajax.SWFRequest');
+ this._request = new jindo.$Ajax.SWFRequest(jindo.$Fn(this.option,this).bind());
+ break;
+ case "jsonp":
+ if(!jindo.$Ajax.JSONPRequest) throw Error('Require jindo.$Ajax.JSONPRequest');
+ _opt.method = "get";
+ this._request = new jindo.$Ajax.JSONPRequest(jindo.$Fn(this.option,this).bind());
+ break;
+ case "iframe":
+ if(!jindo.$Ajax.FrameRequest) throw Error('Require jindo.$Ajax.FrameRequest');
+ this._request = new jindo.$Ajax.FrameRequest(jindo.$Fn(this.option,this).bind());
+ break;
+ }
+};
+
+
+/**
+ * @ignore
+ */
+jindo.$Ajax.prototype._onload = (function(isIE) {
+ if(isIE){
+ return function(){
+ var bSuccess = this._request.readyState == 4 && this._request.status == 200;
+ var oResult;
+ if (this._request.readyState == 4) {
+ try {
+ if (this._request.status != 200 && typeof this._options.onerror == 'function'){
+ if(!this._request.status == 0){
+ this._options.onerror(jindo.$Ajax.Response(this._request));
+ }
+ }else{
+ if(!this._is_abort){
+ oResult = this._options.onload(jindo.$Ajax.Response(this._request));
+ }
+ }
+ }finally{
+ if(typeof this._oncompleted == 'function'){
+ this._oncompleted(bSuccess, oResult);
+ }
+ if (this._options.type == "xhr" ){
+ this.abort();
+ try { delete this._request.onload; } catch(e) { this._request.onload =undefined;}
+ }
+ delete this._request.onreadystatechange;
+
+ }
+ }
+ }
+ }else{
+ return function(){
+ var bSuccess = this._request.readyState == 4 && this._request.status == 200;
+ var oResult;
+ if (this._request.readyState == 4) {
+ try {
+
+ if (this._request.status != 200 && typeof this._options.onerror == 'function'){
+ this._options.onerror(jindo.$Ajax.Response(this._request));
+ }else{
+ oResult = this._options.onload(jindo.$Ajax.Response(this._request));
+ }
+ }finally{
+ this._status--;
+ if(typeof this._oncompleted == 'function'){
+ this._oncompleted(bSuccess, oResult);
+ }
+ }
+ }
+ }
+ }
+})(/MSIE/.test(window.navigator.userAgent));
+
+/**
+
+ * @description request() 메서드는 Ajax 요청을 서버에 전송한다. 요청에 사용할 파라미터는 $Ajax() 객체 생성자에서 설정하거나 option() 메서드를 사용하여 변경할 수 있다. 요청 타입(type)이 "flash"면 이 메소드를 실행하기 전에 body 요소에서 {@link $Ajax.SWFRequest.write}() 메서드를 반드시 실행해야 한다.
+ * @param {Object} oData 서버로 전송할 데이터.
+ * @return {$Ajax} $Ajax() 객체.
+ * @see $Ajax#option
+ * @see $Ajax.SWFRequest.write
+ * @example
+var ajax = $Ajax("http://www.remote.com", {
+ onload : function(res) {
+ // onload 핸들러
+ }
+});
+
+ajax.request( {key1:"value1", key2:"value2"} ); // 서버에 전송할 데이터를 매개변수로 넘긴다.
+
+ */
+jindo.$Ajax.prototype.request = function(oData) {
+ this._status++;
+ var t = this;
+ var req = this._request;
+ var opt = this._options;
+ var data, v,a = [], data = "";
+ var _timer = null;
+ var url = this._url;
+ this._is_abort = false;
+
+ if( opt.postBody && opt.type.toUpperCase()=="XHR" && opt.method.toUpperCase()!="GET"){
+ if(typeof oData == 'string'){
+ data = oData;
+ }else{
+ data = jindo.$Json(oData).toString();
+ }
+ }else if (typeof oData == "undefined" || !oData) {
+ data = null;
+ } else {
+ for(var k in oData) {
+ if(oData.hasOwnProperty(k)){
+ v = oData[k];
+ if (typeof v == "function") v = v();
+
+ if (v instanceof Array || v instanceof jindo.$A) {
+ jindo.$A(v).forEach(function(value,index,array) {
+ a[a.length] = k+"="+encodeURIComponent(value);
+ });
+ } else {
+ a[a.length] = k+"="+encodeURIComponent(v);
+ }
+ }
+ }
+ data = a.join("&");
+ }
+
+ /*
+
+XHR GET 방식 요청인 경우 URL에 파라미터 추가
+
+ */
+ if(data && opt.type.toUpperCase()=="XHR" && opt.method.toUpperCase()=="GET"){
+ if(url.indexOf('?')==-1){
+ url += "?";
+ } else {
+ url += "&";
+ }
+ url += data;
+ data = null;
+ }
+ req.open(opt.method.toUpperCase(), url, opt.async);
+ if(opt.type.toUpperCase()=="XHR"&&opt.method.toUpperCase()=="GET"&&/MSIE/.test(window.navigator.userAgent)){
+ /*
+
+xhr인 경우 IE에서는 GET으로 보낼 때 브라우져에서 자체 cache하여 cache을 안되게 수정.
+
+ */
+ req.setRequestHeader("If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT");
+ }
+ if (opt.sendheader) {
+ if(!this._headers["Content-Type"]){
+ req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
+ }
+ req.setRequestHeader("charset", "utf-8");
+ for (var x in this._headers) {
+ if(this._headers.hasOwnProperty(x)){
+ if (typeof this._headers[x] == "function")
+ continue;
+ req.setRequestHeader(x, String(this._headers[x]));
+ }
+ }
+ }
+ var navi = navigator.userAgent;
+ if(req.addEventListener&&!(navi.indexOf("Opera") > -1)&&!(navi.indexOf("MSIE") > -1)){
+ /*
+
+ * opera 10.60에서 XMLHttpRequest에 addEventListener기 추가되었지만 정상적으로 동작하지 않아 opera는 무조건 dom1방식으로 지원함.
+ * IE9에서도 opera와 같은 문제가 있음.
+
+ */
+ if(this._loadFunc){ req.removeEventListener("load", this._loadFunc, false); }
+ this._loadFunc = function(rq){
+ clearTimeout(_timer);
+ _timer = undefined;
+ t._onload(rq);
+ }
+ req.addEventListener("load", this._loadFunc, false);
+ }else{
+ if (typeof req.onload != "undefined") {
+ req.onload = function(rq){
+ if(req.readyState == 4 && !t._is_abort){
+ clearTimeout(_timer);
+ _timer = undefined;
+ t._onload(rq);
+ }
+ };
+ } else {
+ /*
+
+ * IE6에서는 onreadystatechange가 동기적으로 실행되어 timeout이벤트가 발생안됨.
+ * 그래서 interval로 체크하여 timeout이벤트가 정상적으로 발생되도록 수정. 비동기 방식일때만
+
+ */
+ if(window.navigator.userAgent.match(/(?:MSIE) ([0-9.]+)/)[1]==6&&opt.async){
+ var onreadystatechange = function(rq){
+ if(req.readyState == 4 && !t._is_abort){
+ if(_timer){
+ clearTimeout(_timer);
+ _timer = undefined;
+ }
+ t._onload(rq);
+ clearInterval(t._interval);
+ t._interval = undefined;
+ }
+ };
+ this._interval = setInterval(onreadystatechange,300);
+
+ }else{
+ req.onreadystatechange = function(rq){
+ if(req.readyState == 4){
+ clearTimeout(_timer);
+ _timer = undefined;
+ t._onload(rq);
+ }
+ };
+ }
+ }
+ }
+
+ if (opt.timeout > 0) {
+
+// if(this._interval)clearInterval(this._interval);
+ if(this._timer) clearTimeout(this._timer);
+
+ _timer = setTimeout(function(){
+ t._is_abort = true;
+ if(t._interval){
+ clearInterval(t._interval);
+ t._interval = undefined;
+ }
+ try{ req.abort(); }catch(e){};
+
+ opt.ontimeout(req);
+ if(typeof t._oncompleted == 'function') t._oncompleted(false);
+ }, opt.timeout * 1000 );
+ this._timer = _timer;
+ }
+ /*
+
+ * test을 하기 위한 url
+
+ */
+ this._test_url = url;
+ req.send(data);
+
+ return this;
+};
+
+/**
+
+ * @description isIdle() 메서드는 $Ajax() 객체가 현재 요청 대기 상태인지 확인한다.
+ * @since 1.3.5 부터 사용 가능
+ * @return {Boolean} 현재 대기 중이면 true 를, 그렇지 않으면 false를 리턴한다.
+ * @example
+ var ajax = $Ajax("http://www.remote.com",{
+ onload : function(res){
+ // onload 핸들러
+ }
+});
+
+if(ajax.isIdle()) ajax.request();
+
+ */
+jindo.$Ajax.prototype.isIdle = function(){
+ return this._status==0;
+}
+
+/**
+
+ * @description abort() 메서드는 서버로 전송한 Ajax 요청을 취소한다. Ajax 요청의 응답 시간이 길거나 강제로 Ajax 요청을 취소할 경우 사용한다.
+ * @return {$Ajax} 전송을 취소한 $Ajax() 객체
+ * @example
+var ajax = $Ajax("http://www.remote.com", {
+ timeout : 3,
+ ontimeout : function() {
+ stopRequest();
+ }
+ onload : function(res) {
+ // onload 핸들러
+ }
+}).request( {key1:"value1", key2:"value2"} );
+
+function stopRequest() {
+ ajax.abort();
+}
+
+ */
+jindo.$Ajax.prototype.abort = function() {
+ try {
+ if(this._interval) clearInterval(this._interval);
+ if(this._timer) clearTimeout(this._timer);
+ this._interval = undefined;
+ this._timer = undefined;
+ this._is_abort = true;
+ this._request.abort();
+ }finally{
+ this._status--;
+ }
+
+ return this;
+};
+
+
+/**
+
+ * @description option() 메서드는 $Ajax() 객체의 옵션 객체(oOption) 속성에 정의된 Ajax 요청 옵션에 대한 정보를 가져오거나 혹은 설정한다. Ajax 요청 옵션을 설정하려면 이름과 값을, 혹은 이름과 값을 원소로 가지는 하나의 객체를 파라미터로 입력한다. 이름과 값을 원소로 가지는 객체를 입력하면 하나 이상의 정보를 한 번에 설정할 수 있다.
+ * @param {Variant} vName 옵션 객체의 속성 이름(String) 또는 하나 이상의 속성 값이 정의된 객체(Object).
+
+ 문자열을 파라미터로 입력하면 다음과 같이 동작한다.
+
+ sValue 파라미터를 생략하면 이름에 해당하는 $Ajax의 속성 값을 반환한다.
+ sVlue 파라미터를 설정하면 이름에 해당하는 $Ajax의 속성 값을 sValue 값으로 설정한다.
+
+
+ 객체인 경우에는 속성 이름으로 정보를 찾아 속성의 값으로 설정한다. 객체에 하나 이상의 속성을 지정하면 여러 속성 값을 한 번에 설정할 수 있다.
+
+ * @param {Variant} [vValue] 새로 설정할 옵션 속성의 값. vName 파라미터가 문자열인 경우에만 사용된다.
+ * @return {Variant} 정보의 값을 가져올 때는 문자열(String)을, 값을 설정할 때는 $Ajax() 객체를 반환한다.
+ * @example
+var ajax = $Ajax("http://www.remote.com", {
+ type : "xhr",
+ method : "get",
+ onload : function(res) {
+ // onload 핸들러
+ }
+});
+
+var request_type = ajax.option("type"); // type 인 xhr 을 리턴한다.
+ajax.option("method", "post"); // method 를 post 로 설정한다.
+ajax.option( { timeout : 0, onload : handler_func } ); // timeout 을 으로, onload 를 handler_func 로 설정한다.
+
+ */
+jindo.$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){
+ if(name.hasOwnProperty(x))
+ this._options[x] = name[x]
+ }
+ } catch(e) {};
+
+ return this;
+};
+
+/**
+
+ * @description header() 메서드는 Ajax 요청에서 사용할 HTTP 요청 헤더를 가져오거나 설정한다. 헤더를 설정하려면 헤더의 이름과 값을 각각 파라미터로 입력하거나 헤더의 이름과 값을 원소로 가지는 객체를 파라미터로 입력한다. 객체를 파라미터로 입력하면 하나 이상의 헤더를 한 번에 설정할 수 있다. 헤더에서 특정 속성 값을 가져오려면 속성의 이름을 파라미터로 입력한다.
+ * @param {Variant} vName 헤더 이름(String) 또는 하나 이상의 헤더 값이 정의된 객체(Object).
+
+ 문자열을 파라미터로 입력하면 다음과 같이 동작한다.
+
+ vValue 파라미터를 생략하면 HTTP 요청 헤더에서 문자열과 일치하는 헤더 값을 찾는다.
+ vValue 파라미터를 설정하면 HTTP 요청 헤더에서 문자열과 일치하는 헤더 값을 vValue 값으로 설정한다.
+
+
+ 객체인 경우에는 헤더 이름으로 정보를 찾아 헤더의 값으로 설정한다. 객체에 하나 이상의 헤더 값을 지정하면 여러 헤더 값을 한 번에 설정할 수 있다.
+
+ * @param {Value} [vValue] 설정할 헤더 값. vName 파라미터가 문자열인 경우에만 사용한다.
+ * @return {Variant} 정보의 값을 가져올 때는 문자열(String)을, 값을 설정할 때는 $Ajax() 객체를 반환한다.
+ * @example
+var customheader = ajax.header("myHeader"); // HTTP 요청 헤더에서 myHeader 의 값
+ajax.header( "myHeader", "someValue" ); // HTTP 요청 헤더의 myHeader 를 someValue 로 설정한다.
+ajax.header( { anotherHeader : "someValue2" } ); // HTTP 요청 헤더의 anotherHeader 를 someValue2 로 설정한다.
+
+ */
+jindo.$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) {
+ if (name.hasOwnProperty(x))
+ this._headers[x] = name[x]
+ }
+
+
+ } catch(e) {};
+
+ return this;
+};
+
+/**
+
+ * @class $Ajax.Response 객체를 생성한다. $Ajax.Response 객체는 $Ajax() 객체에서 request() 메서드의 요청 처리 완료한 후 생성된다. $Ajax() 객체를 생성할 때 onload 속성에 설정한 콜백 함수의 파라미터로 $Ajax.Response 객체가 전달된다.
+ * @constructor
+ * @description Ajax 응답 객체를 래핑하여 응답 데이터를 가져오거나 활용하는데 유용한 기능을 제공한다.
+ * @param {Object} oReq 요청 객체
+ * @see $Ajax
+
+ */
+jindo.$Ajax.Response = function(req) {
+ if (this === jindo.$Ajax) return new jindo.$Ajax.Response(req);
+ this._response = req;
+};
+
+/**
+
+ * @description xml() 메서드는 응답을 XML 객체로 반환한다. XHR의 responseXML 속성과 유사하다.
+ * @return {Object} 응답 XML 객체.
+ * @see XMLHttpRequest - MDN Docs
+ * @example
+// some.xml
+
+ 첫번째
+ 두번째
+ 세번째
+
+
+// client.html
+var oAjax = new $Ajax('some.xml', {
+ type : 'xhr',
+ method : 'get',
+ onload : function(res){
+ var elData = cssquery.getSingle('data', res.xml()); // 응답을 XML 객체로 리턴한다
+ $('list').innerHTML = elData.firstChild.nodeValue;
+ },
+}).request();
+
+ */
+jindo.$Ajax.Response.prototype.xml = function() {
+ return this._response.responseXML;
+};
+
+/**
+
+ * @description text() 메서드는 응답을 문자열(String)로 반환한다. XHR의 responseText 와 유사하다.
+ * @return {String} 응답 문자열.
+ * @see XMLHttpRequest - MDN Docs
+ * @example
+// some.php
+첫번째두번째 세번째 ";
+?>
+
+// client.html
+var oAjax = new $Ajax('some.xml', {
+ type : 'xhr',
+ method : 'get',
+ onload : function(res){
+ $('list').innerHTML = res.text(); // 응답을 문자열로 리턴한다
+ },
+}).request();
+
+ */
+jindo.$Ajax.Response.prototype.text = function() {
+ return this._response.responseText;
+};
+
+/**
+
+ * @description status() 메서드는 HTTP 응답 코드를 반환한다. HTTP 응답 코드표를 참고한다.
+ * @return {Number} 응답 코드.
+ * @see HTTP Status codes - W3C
+ * @example
+var oAjax = new $Ajax('some.php', {
+ type : 'xhr',
+ method : 'get',
+ onload : function(res){
+ if(res.status() == 200){ // HTTP 응답 코드를 확인한다.
+ $('list').innerHTML = res.text();
+ }
+ },
+}).request();
+
+ */
+jindo.$Ajax.Response.prototype.status = function() {
+ return this._response.status;
+};
+
+/**
+
+ * @description readyState() 메서드는 응답 상태(readyState)를 반환한다. readyState 속성 값에 대한 설명은 다음 표와 같다.
+
+ readyState 속성 설명
+
+
+ 값
+ 설명
+
+
+
+
+ 0(UNINITIALIZED)
+ 요청이 초기화되지 않은 상태.
+
+
+ 1(LOADING)
+ 요청 옵션을 설정했으나, 요청하지 않은 상태
+
+
+ 2(LOADED)
+ 요청을 보내고 처리 중인 상태. 이 상태에서 응답 헤더를 얻을 수 있다.
+
+
+ 3(INTERACTIVE)
+ 요청이 처리 중이며, 부분적인 응답 데이터를 받은 상태.
+
+
+ 4(COMPLETED)
+ 응답 데이터를 모두 받아 통신을 완료한 상태.
+
+
+
+ * @return {Number} readyState 값.
+ * @see open
+ * @see send
+ * @example
+var oAjax = new $Ajax('some.php', {
+ type : 'xhr',
+ method : 'get',
+ onload : function(res){
+ if(res.readyState() == 4){ // 응답의 readyState 를 확인한다.
+ $('list').innerHTML = res.text();
+ }
+ },
+}).request();
+
+ */
+jindo.$Ajax.Response.prototype.readyState = function() {
+ return this._response.readyState;
+};
+
+/**
+
+ * @description json() 메서드는 응답을 JSON 객체로 반환한다. 응답 문자열을 자동으로 JSON 객체로 변환하여 반환한다. 변환 과정에서 오류가 발생하면 빈 객체를 반환한다.
+ * @return {Object} JSON 객체.
+ * @example
+// some.php
+
+
+// client.html
+var oAjax = new $Ajax('some.php', {
+ type : 'xhr',
+ method : 'get',
+ onload : function(res){
+ var welList = $Element('list').empty();
+ var jsonData = res.json(); // 응답을 JSON 객체로 리턴한다
+
+ for(var i = 0, nLen = jsonData.length; i < nLen; i++){
+ welList.append($("" + jsonData[i] + " "));
+ }
+ },
+}).request();
+
+ */
+jindo.$Ajax.Response.prototype.json = function() {
+ if (this._response.responseJSON) {
+ return this._response.responseJSON;
+ } else if (this._response.responseText) {
+ try {
+ return eval("("+this._response.responseText+")");
+ } catch(e) {
+ return {};
+ }
+ }
+
+ return {};
+};
+
+/**
+
+ * @description header() 메서드는 응답 헤더를 가져온다. 파라미터를 입력하지 않으면 헤더 전체를 반환한다.
+ * @param {String} [sName] 가져올 응답 헤더의 이름.
+ * @return {Variant} 파라미터를 입력했을 경우 해당하는 헤더 값(String)을, 그렇지 않으면 헤더 전체(Object)를 반환한다.
+ * @example
+var oAjax = new $Ajax('some.php', {
+ type : 'xhr',
+ method : 'get',
+ onload : function(res){
+ res.header(); // 응답 헤더 전체를 리턴한다.
+ res.header("Content-Length") // 응답 헤더에서 "Content-Length" 의 값을 리턴한다.
+ },
+}).request();
+
+ */
+jindo.$Ajax.Response.prototype.header = function(name) {
+ if (typeof name == "string") return this._response.getResponseHeader(name);
+ return this._response.getAllResponseHeaders();
+};
+
+
/**
+
+ * @fileOverview $Ajax의 확장 메서드를 정의한 파일
+ * @name Ajax.extend.js
+
+ */
+
+/**
+
+ * @class Ajax 요청 객체의 기본 객체이다.
+ * @description Ajax 요청 타입 별로 Ajax 요청 객체를 생성할 때 Ajax 요청 객체를 생성하기 위한 상위 객체로 사용한다.
+ * @see $Ajax
+
+ */
+jindo.$Ajax.RequestBase = jindo.$Class({
+ _respHeaderString : "",
+ callbackid:"",
+ callbackname:"",
+ responseXML : null,
+ responseJSON : null,
+ responseText : "",
+ status : 404,
+ readyState : 0,
+ $init : function(fpOption){},
+ 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 = "";
+ if(this.option("callbackid")!="") {
+ var idx = 0;
+ do {
+ id = "_" + this.option("callbackid") + "_"+idx;
+ idx++;
+ } while (window.__jindo2_callback[id]);
+ }else{
+ do {
+ id = "_" + Math.floor(Math.random() * 10000);
+ } while (window.__jindo2_callback[id]);
+ }
+
+ if(this.option("callbackname") == ""){
+ this.option("callbackname","_callback");
+ }
+
+ return {callbackname:this.option("callbackname"),id:id,name:"window.__jindo2_callback."+id};
+ }
+});
+
+/**
+
+ * @class Ajax 요청 타입이 jsonp인 요청 객체를 생성하며, $Ajax() 객체에서 Ajax 요청 객체를 생성할 때 사용한다.
+ * @extends $Ajax.RequestBase
+ * @description $Ajax.JSONPRequest 객체를 생성한다. 이때, $Ajax.JSONPRequest 객체는 $Ajax.RequestBase 객체를 상속한다.
+ * @see $Ajax
+ * @see $Ajax.RequestBase
+
+ */
+jindo.$Ajax.JSONPRequest = jindo.$Class({
+ _headers : {},
+ _respHeaders : {},
+ _script : null,
+ _onerror : null,
+ $init : function(fpOption){
+ this.option = fpOption;
+ },
+ _callback : function(data) {
+
+ if (this._onerror) {
+ clearTimeout(this._onerror);
+ this._onerror = null;
+ }
+
+ var self = this;
+
+ 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 = jindo.$("
+