From a6873272b309d5ba0d8526d31f5e720552586902 Mon Sep 17 00:00:00 2001 From: taggon Date: Mon, 15 Mar 2010 07:54:01 +0000 Subject: [PATCH 01/74] =?UTF-8?q?#18773194=20exec=5Fxml=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7336 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- common/js/xml_handler.js | 510 ++++++++++++++------------------------- 1 file changed, 184 insertions(+), 326 deletions(-) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index 65f6ae715..57ef9fe0c 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -1,331 +1,10 @@ /** * @file common/js/xml_handler.js - * @author zero - * @brief zbxe내에서 ajax기능을 이용함에 있어 module, act를 잘 사용하기 위한 자바스크립트 + * @brief XE에서 ajax기능을 이용함에 있어 module, act를 잘 사용하기 위한 자바스크립트 **/ // xml handler을 이용하는 user function var show_waiting_message = true; -function exec_xml(module, act, params, callback_func, response_tags, callback_func_arg, fo_obj) { - var oXml = new xml_handler(); - oXml.reset(); - if(typeof(params)!='undefined') { - for(var key in params) { - if(!params.hasOwnProperty(key)) continue; - var val = params[key]; - oXml.addParam(key, val); - } - } - oXml.addParam("module", module); - oXml.addParam("act", act); - if(typeof(xeVid)!='undefined') oXml.addParam('vid', xeVid); - - if(typeof(response_tags)=="undefined" || response_tags.length<1) response_tags = new Array('error','message'); - - oXml.request(xml_response_filter, oXml, callback_func, response_tags, callback_func_arg, fo_obj); -} - -// 결과 처리 후 callback_func에 넘겨줌 -function xml_response_filter(oXml, callback_func, response_tags, callback_func_arg, fo_obj) { - var text = oXml.getResponseText(); - if(oXml.objXmlHttp.readyState!=4) return; - if(text && !/<\/response>$/i.test(text)) { - var waiting_obj = xGetElementById("waitingforserverresponse"); - if(waiting_obj) waiting_obj.style.visibility = "hidden"; - alert(text); - return null; - } - - var xmlDoc = oXml.getResponseXml(); - if(!xmlDoc) return null; - - var waiting_obj = xGetElementById("waitingforserverresponse"); - if(waiting_obj) waiting_obj.style.visibility = "hidden"; - - var ret_obj = oXml.toZMsgObject(xmlDoc, response_tags); - if(ret_obj["error"]!=0) { - alert(ret_obj["message"]); - return null; - } - - if(ret_obj["redirect_url"]) { - location.href=ret_obj["redirect_url"].replace(/&/g,'&'); - return null; - } - - if(!callback_func) return null; - - callback_func(ret_obj, response_tags, callback_func_arg, fo_obj); - - return null; -} - -// xml handler -function xml_handler() { - this.objXmlHttp = null; - this.method_name = null; - this.xml_path = request_uri+"index.php"; - - this.params = new Array(); - - this.reset = xml_handlerReset; - this.getXmlHttp = zGetXmlHttp; - this.request = xml_handlerRequest; - this.setPath = xml_handlerSetPath; - this.addParam = xml_handlerAddParam; - this.getResponseXml = xml_handlerGetResponseXML; - this.getResponseText = xml_handlerGetResponseText; - this.toZMsgObject = xml_handlerToZMsgObject; - this.parseXMLDoc = xml_parseXmlDoc; - - this.objXmlHttp = this.getXmlHttp(); -} - -function zGetXmlHttp() { - if (window.XMLHttpRequest) return new XMLHttpRequest(); - else if (window.ActiveXObject) { - try { - return new ActiveXObject("Msxml2.XMLHTTP"); - } catch (e) { - return new ActiveXObject("Microsoft.XMLHTTP"); - } - } - return null; -} - -function xml_handlerRequest(callBackFunc, xmlObj, callBackFunc2, response_tags, callback_func_arg, fo_obj) { - // ssl action - if(typeof(ssl_actions)!='undefined' && typeof(ssl_actions.length)!='undefined' && typeof(this.params['act'])!='undefined') { - var action = this.params['act']; - for(i=0;i\n" - + "\n" - + "\n" - - for (var key in this.params) { - if(!this.params.hasOwnProperty(key)) continue; - var val = this.params[key]; - rd += "<"+key+">\n"; - } - - rd += "\n" - + "\n"; - - - if(this.objXmlHttp.readyState!=0) { - this.objXmlHttp.abort(); - this.objXmlHttp = this.getXmlHttp(); - } - this.objXmlHttp.onreadystatechange = function () {callBackFunc(xmlObj, callBackFunc2, response_tags, callback_func_arg, fo_obj)}; - - // 모든 xml데이터는 POST방식으로 전송. try-catch문으로 오류 발생시 대처 - try { - this.objXmlHttp.open("POST", this.xml_path, true); - } catch(e) { - alert(e); - return; - } - - // ajax 통신중 대기 메세지 출력 (show_waiting_message값을 false로 세팅시 보이지 않음) - var waiting_obj = xGetElementById("waitingforserverresponse"); - if(show_waiting_message && waiting_obj) { - xInnerHtml(waiting_obj, waiting_message); - - xTop(waiting_obj, xScrollTop()+20); - xLeft(waiting_obj, xScrollLeft()+20); - waiting_obj.style.visibility = "visible"; - } - - this.objXmlHttp.send(rd); -} - -function xml_handlerSetPath(path) { - this.xml_path = "./"+path; -} - - -function xml_handlerReset() { - this.objXmlHttp = this.getXmlHttp(); - this.params = new Array(); -} - -function xml_handlerAddParam(key, val) { - this.params[key] = val; -} - -function xml_handlerGetResponseXML() { - if(this.objXmlHttp && this.objXmlHttp.readyState == 4 && isDef(this.objXmlHttp.responseXML)) { - var xmlDoc = this.objXmlHttp.responseXML; - this.reset(); - return xmlDoc; - } - return null; -} - -function xml_handlerGetResponseText() { - if(this.objXmlHttp && this.objXmlHttp.readyState == 4 && isDef(this.objXmlHttp.responseText)) { - return this.objXmlHttp.responseText; - } - return null; -} - - -function xml_parseXmlDoc(dom) { - - if(!dom) return; - - var jsonStr = xml2json(dom,false,false); - var jsonObj = eval("("+ jsonStr +");"); - return jsonObj.response; -/* - - var ret_obj = new Array(); - - var obj = dom.firstChild; - var preObj; - if(!obj) return; - - while(obj) { - if(obj.nodeType == 1) { - - var name = obj.nodeName; - var value = null; - - if(obj.childNodes.length==1 && obj.firstChild.nodeType != 1) { - - value = obj.firstChild.nodeValue; - } else { - value = this.parseXMLDoc(obj); - } - if(typeof(ret_obj[name])=='undefined') { - ret_obj[name] = value; - } else { - if(ret_obj[name].length>0) { - ret_obj[name][ret_obj[name].length] = value; - } else { - var tmp_value = ret_obj[name]; - ret_obj[name] = new Array(); - ret_obj[name][ret_obj[name].length] = tmp_value; - ret_obj[name][ret_obj[name].length] = value; - } - } - - } - obj = obj.nextSibling; - - } - return ret_obj; -*/ -} - -function xml_handlerToZMsgObject(xmlDoc, tags) { - if(!xmlDoc) return null; - if(!tags) tags = new Array("error","message"); - tags[tags.length] = "redirect_url"; - tags[tags.length] = "act"; - - var parsed_array = this.parseXMLDoc(xmlDoc.getElementsByTagName('response')[0]); - - if(typeof(parsed_array)=='undefined') { - var ret = new Array(); - ret['error'] = -1; - ret['message'] = "Unexpected error occured."; - try{ - if(typeof(xmlDoc.childNodes[0].firstChild.data)!='undefined') ret['message']+="\r\n"+xmlDoc.childNodes[0].firstChild.data; - } catch(e) { - } - return ret; - } - - var obj_ret = new Array(); - for(var i=0; i 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]"; + } + else if (o == null) + json += (name&&":") + "null"; + else if (typeof(o) == "object") { + var arr = []; + for (var m in o) + arr[arr.length] = toJson(o[m], m, ind+"\t"); + json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}"; + } + else if (typeof(o) == "string") + json += (name&&":") + "\"" + o.toString() + "\""; + else + json += (name&&":") + o.toString(); + return json; +} + +(function($){ +/** + * @brief exec_xml + * @author taggon + **/ +$.exec_xml = window.exec_xml = function(module, act, params, callback_func, response_tags, callback_func_arg, fo_obj) { + var xml_path = request_uri+"index.php" + + // {{{ set parameters + params['module'] = module; + params['act'] = act; + + if(typeof(xeVid)!='undefined') params['vid'] = xeVid; + if(typeof(response_tags)=="undefined" || response_tags.length<1) response_tags = ['error','message']; + // }}} set parameters + + // use ssl? + if ($.isArray(ssl_actions) && params['act'] && $.inArray(params['act'], ssl_actions) >= 0) + { + var url = default_url || request_uri; + var port = https_port || 443; + var _ul = $('').attr('href', url)[0]; + var target = 'https://' + _ul.hostname.replace(/:\d+$/, ''); + + if(port != 443) target += ':'+port; + if(_ul.pathname[0] != '/') target += '/'; + + target += ul.pathname; + xml_path = target.replace(/\/$/, '')+'/index.php'; + } + + var _u1 = $('').attr('href', location.href)[0]; + var _u2 = $('').attr('href', xml_path)[0]; + + // 현 url과 ajax call 대상 url의 schema 또는 port가 다르면 직접 form 전송 + if(_u1.protocol != _u2.protocol || _u1.port != _u2.port) return send_by_form(xml_path, params); + + var xml = [], i = 0; + xml[i++] = ''; + xml[i++] = ''; + xml[i++] = ''; + + $.each(params, function(key, val) { + xml[i++] = '<'+key+'>'; + }); + + xml[i++] = ''; + xml[i++] = ''; + + var _xhr = null; + if (_xhr && _xhr.readyState != 0) _xhr.abort(); + + // 전송 성공시 + function onsuccess(data, textStatus, xhr) { + var resp_xml = $(data).find('response')[0], resp_obj, txt='', ret=[], tags={}, json_str=''; + + waiting_obj.css('visibility', 'hidden'); + + if(!resp_xml) { + alert(_xhr.responseText); + return null; + } + + json_str = xml2json(resp_xml, false, false); + resp_obj = (typeof(JSON)=='object' && $.isFunction(JSON.parse))?JSON.parse(json_str):eval('('+json_str+')'); + resp_obj = resp_obj.response; + + if (typeof(resp_obj)=='undefined') { + ret['error'] = -1; + ret['message'] = 'Unexpected error occured.'; + try { + if(typeof(txt=resp_xml.childNodes[0].firstChild.data)!='undefined') ret['message'] += '\r\n'+txt; + } catch(e){}; + return ret; + } + + $.each(response_tags, function(key, val){ tags[val] = true; }); + $.each(resp_obj, function(key, val){ if(tags[key]) ret[key] = val; }); + + if(ret['error'] != 0) { + alert(ret['message'] || 'error!'); + return null; + } + + if(ret['redirect_url']) { + location.href = ret['redirect_url'].replace(/&/g, '&'); + return null; + } + + if($.isFunction(callback_func)) callback_func(ret, response_tags, callback_func_arg, fo_obj); + } + + // 모든 xml데이터는 POST방식으로 전송. try-catch문으로 오류 발생시 대처 + try { + $.ajax({ + url : xml_path, + type : 'POST', + dataType : 'xml', + data : xml.join('\n'), + contentType : 'text/plain', + beforeSend : function(xhr){ _xhr = xhr; }, + success : onsuccess, + error : function(xhr, textStatus) { + waiting_obj.css('visibility', 'hidden'); + alert(textStatus); + } + }); + } catch(e) { + alert(e); + return; + } + + // ajax 통신중 대기 메세지 출력 (show_waiting_message값을 false로 세팅시 보이지 않음) + var waiting_obj = $('#waitingforserverresponse'); + if(show_waiting_message && waiting_obj.length) { + var d = $(document); + waiting_obj.html(waiting_message).css({ + 'top' : (d.scrollTop()+20)+'px', + 'left' : (d.scrollLeft()+20)+'px', + 'visibility' : 'visible' + }); + } +} +function send_by_form(url, params) { + var frame_id = 'xeTmpIframe'; + var form_id = 'xeVirtualForm'; + + if (!$('#'+frame_id).length) { + $(''.replace(/%id%/g, frame_id)).appendTo(document.body); } $('#'+form_id).remove(); - var form = $('
'.replace(/%id%/g, form_id)).attr({ + var form = $('
'.replace(/%id%/g, form_id)).attr({ 'id' : form_id, 'method' : 'post', 'action' : url, From e4e64097f20864bc2083e1c95c5b2a0401527ffa Mon Sep 17 00:00:00 2001 From: haneul Date: Thu, 22 Apr 2010 02:59:13 +0000 Subject: [PATCH 42/74] #18851012 : fixed openid problem (add direct_url, act for default tags) git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7380 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- common/js/xml_handler.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index 2804ec731..21cd6d0bf 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -256,6 +256,8 @@ $.exec_xml = window.exec_xml = function(module, act, params, callback_func, resp } $.each(response_tags, function(key, val){ tags[val] = true; }); + tags["redirect_url"] = true; + tags["act"] = true; $.each(resp_obj, function(key, val){ if(tags[key]) ret[key] = val; }); if(ret['error'] != 0) { From e10b43fcd1b3d64e2a8dda48998ec3751cd54abc Mon Sep 17 00:00:00 2001 From: haneul Date: Thu, 22 Apr 2010 06:41:46 +0000 Subject: [PATCH 43/74] #18852541 : make multilanguage input script use id instead of name git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7381 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- common/js/common.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/js/common.js b/common/js/common.js index a2917675b..eef178ccd 100644 --- a/common/js/common.js +++ b/common/js/common.js @@ -993,7 +993,9 @@ jQuery(function(){ function() { var objText = jQuery(this); - var targetName = objText.attr("name"); + var targetName = objText.attr("id"); + if(typeof(targetName) == "undefined") targetName = objText.attr("name"); + if(typeof(targetName) == "undefined") return; objText.after("
find_langcode"); } ); From 4fee51d1e0499c31a798227356a8ae298fd1fd32 Mon Sep 17 00:00:00 2001 From: supershop Date: Thu, 22 Apr 2010 10:22:09 +0000 Subject: [PATCH 44/74] english translation fixed git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7382 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/module/lang/en.lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/module/lang/en.lang.php b/modules/module/lang/en.lang.php index 909ed95a9..467471006 100644 --- a/modules/module/lang/en.lang.php +++ b/modules/module/lang/en.lang.php @@ -27,7 +27,7 @@ $lang->skin_history = 'Update history'; $lang->module_copy = "Duplicate Module"; $lang->module_selector = "Module Selector"; - $lang->do_selected = "You would..."; + $lang->do_selected = "I want to"; $lang->bundle_setup = "Bundle Setup"; $lang->bundle_addition_setup = "Bundle Additional Setup"; $lang->bundle_grant_setup = "Bundle Permission Setup"; From fc9d40cece3997336c00d40c4837a836d9f63053 Mon Sep 17 00:00:00 2001 From: haneul Date: Fri, 23 Apr 2010 03:11:46 +0000 Subject: [PATCH 45/74] #18851228 : reset page when moving into different category at easyinstall git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7383 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/autoinstall/tpl/leftBox.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/autoinstall/tpl/leftBox.html b/modules/autoinstall/tpl/leftBox.html index 2b720785a..ca4964a71 100644 --- a/modules/autoinstall/tpl/leftBox.html +++ b/modules/autoinstall/tpl/leftBox.html @@ -14,9 +14,9 @@
  • - category_srl == $category_srl)--> class="selected">{$val->title} + category_srl == $category_srl)--> class="selected">{$val->title} - category_srl == $category_srl)--> class="selected">{$val->title} + category_srl == $category_srl)--> class="selected">{$val->title} ({$val->nPackages}) From 871e61ea2ca1f1916f704c029d2fd91c7fff0fda Mon Sep 17 00:00:00 2001 From: taggon Date: Fri, 23 Apr 2010 07:58:58 +0000 Subject: [PATCH 46/74] =?UTF-8?q?exec=5Fxml=20=EB=A9=94=EC=86=8C=EB=93=9C?= =?UTF-8?q?=EC=97=90=20error=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7384 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- common/js/xml_handler.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index 21cd6d0bf..20b5f3ca7 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -261,8 +261,12 @@ $.exec_xml = window.exec_xml = function(module, act, params, callback_func, resp $.each(resp_obj, function(key, val){ if(tags[key]) ret[key] = val; }); if(ret['error'] != 0) { - alert(ret['message'] || 'error!'); - return null; + if ($.isFunction($.exec_xml.onerror)) { + return $.exec_xml.onerror(module, act, ret, callback_func, response_tags, callback_func_arg, fo_obj); + } else { + alert(ret['message'] || 'error!'); + return null; + } } if(ret['redirect_url']) { From 9a54d1b539685baf3a838ea6ecd3eae3c424fde5 Mon Sep 17 00:00:00 2001 From: taggon Date: Fri, 23 Apr 2010 07:59:43 +0000 Subject: [PATCH 47/74] =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7385 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- common/js/xml_handler.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index 20b5f3ca7..1fb3ea551 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -263,10 +263,10 @@ $.exec_xml = window.exec_xml = function(module, act, params, callback_func, resp if(ret['error'] != 0) { if ($.isFunction($.exec_xml.onerror)) { return $.exec_xml.onerror(module, act, ret, callback_func, response_tags, callback_func_arg, fo_obj); - } else { - alert(ret['message'] || 'error!'); - return null; } + + alert(ret['message'] || 'error!'); + return null; } if(ret['redirect_url']) { From be57fcf4a073b530ac99e1825bfb2e2becfc9898 Mon Sep 17 00:00:00 2001 From: haneul Date: Fri, 23 Apr 2010 08:45:29 +0000 Subject: [PATCH 48/74] #18825847 : jquery update to 1.4.2, jquery-ui update to 1.8 git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7386 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- common/js/jquery-1.4.2-full.js | 6244 +++++++++++++++++ common/js/jquery.js | 4520 +----------- .../ui.datepicker/jquery.ui.datepicker-ko.js | 23 + common/js/plugins/ui.datepicker/plugin.load | 3 +- .../plugins/ui.datepicker/ui.datepicker.css | 213 - .../js/plugins/ui.datepicker/ui.datepicker.js | 1806 ----- .../ui/images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../ui/images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../ui/images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../ui/images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../ui/images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../ui/images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../ui/images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../ui/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../ui/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../ui/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../ui/images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../ui/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes common/js/plugins/ui/jquery-ui.css | 480 ++ common/js/plugins/ui/jquery-ui.packed.js | 375 +- common/js/plugins/ui/plugin.load | 3 +- 22 files changed, 7273 insertions(+), 6394 deletions(-) create mode 100644 common/js/jquery-1.4.2-full.js create mode 100644 common/js/plugins/ui.datepicker/jquery.ui.datepicker-ko.js delete mode 100644 common/js/plugins/ui.datepicker/ui.datepicker.css delete mode 100644 common/js/plugins/ui.datepicker/ui.datepicker.js create mode 100644 common/js/plugins/ui/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 common/js/plugins/ui/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 common/js/plugins/ui/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 common/js/plugins/ui/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 common/js/plugins/ui/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 common/js/plugins/ui/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 common/js/plugins/ui/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 common/js/plugins/ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 common/js/plugins/ui/images/ui-icons_222222_256x240.png create mode 100644 common/js/plugins/ui/images/ui-icons_2e83ff_256x240.png create mode 100644 common/js/plugins/ui/images/ui-icons_454545_256x240.png create mode 100644 common/js/plugins/ui/images/ui-icons_888888_256x240.png create mode 100644 common/js/plugins/ui/images/ui-icons_cd0a0a_256x240.png create mode 100644 common/js/plugins/ui/jquery-ui.css diff --git a/common/js/jquery-1.4.2-full.js b/common/js/jquery-1.4.2-full.js new file mode 100644 index 000000000..870d9ccaa --- /dev/null +++ b/common/js/jquery-1.4.2-full.js @@ -0,0 +1,6244 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function( window, undefined ) { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwnProperty = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + indexOf = Array.prototype.indexOf; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + if ( elem ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && /^\w+$/.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.4.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging object literal values or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { + var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src + : jQuery.isArray(copy) ? [] : {}; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // Handle when the DOM is ready + ready: function() { + // Make sure that the DOM is not already loaded + if ( !jQuery.isReady ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + return jQuery.ready(); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return toString.call(obj) === "[object Function]"; + }, + + isArray: function( obj ) { + return toString.call(obj) === "[object Array]"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor + && !hasOwnProperty.call(obj, "constructor") + && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwnProperty.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") + .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + trim: function( text ) { + return (text || "").replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = []; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + if ( !inv !== !callback( elems[ i ], i ) ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) || + /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) || + /(msie) ([\w.]+)/.exec( ua ) || + !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch( error ) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + +// Mutifunctional method to get and set values to a collection +// The value/s can be optionally by executed if its a function +function access( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; +} + +function now() { + return (new Date).getTime(); +} +(function() { + + jQuery.support = {}; + + var root = document.documentElement, + script = document.createElement("script"), + div = document.createElement("div"), + id = "script" + now(); + + div.style.display = "none"; + div.innerHTML = "
    a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: div.getElementsByTagName("input")[0].value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected, + + parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null, + + // Will be defined later + deleteExpando: true, + checkClone: false, + scriptEval: false, + noCloneEvent: true, + boxModel: null + }; + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support.scriptEval = true; + delete window[ id ]; + } + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete script.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + root.removeChild( script ); + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = ""; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"); + div.style.width = div.style.paddingLeft = "1px"; + + document.body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + document.body.removeChild( div ).style.display = 'none'; + + div = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + root = script = div = all = a = null; +})(); + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; +var expando = "jQuery" + now(), uuid = 0, windowData = {}; + +jQuery.extend({ + cache: {}, + + expando:expando, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + "object": true, + "applet": true + }, + + data: function( elem, name, data ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache; + + if ( !id && typeof name === "string" && data === undefined ) { + return null; + } + + // Compute a unique ID for the element + if ( !id ) { + id = ++uuid; + } + + // Avoid generating a new cache unless none exists and we + // want to manipulate it. + if ( typeof name === "object" ) { + elem[ expando ] = id; + thisCache = cache[ id ] = jQuery.extend(true, {}, name); + + } else if ( !cache[ id ] ) { + elem[ expando ] = id; + cache[ id ] = {}; + } + + thisCache = cache[ id ]; + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + return typeof name === "string" ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( thisCache ) { + // Remove the section of cache data + delete thisCache[ name ]; + + // If we've removed all the data, remove the element's cache + if ( jQuery.isEmptyObject(thisCache) ) { + jQuery.removeData( elem ); + } + } + + // Otherwise, we want to remove all of the element's data + } else { + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + // Completely remove the data cache + delete cache[ id ]; + } + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + if ( typeof key === "undefined" && this.length ) { + return jQuery.data( this[0] ); + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + } + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } else { + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() { + jQuery.data( this, key, value ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i, elem ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); +var rclass = /[\n\t]/g, + rspace = /\s+/, + rreturn = /\r/g, + rspecialurl = /href|src|style/, + rtype = /(button|input)/i, + rfocusable = /(button|input|object|select|textarea)/i, + rclickable = /^(a|area)$/i, + rradiocheck = /radio|checkbox/; + +jQuery.fn.extend({ + attr: function( name, value ) { + return access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspace ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", setClass = elem.className; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split(rspace); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, i = 0, self = jQuery(this), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery.data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( value === undefined ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + return (elem.attributes.value || {}).specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Typecast each time if the value is a Function and the appended + // value is therefore different each time. + if ( typeof val === "number" ) { + val += ""; + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't set attributes on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + if ( name in elem && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + elem[ name ] = value; + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + + // elem is actually elem.style ... set the style + // Using attr for specific style information is now deprecated. Use style instead. + return jQuery.style( elem, name, value ); + } +}); +var rnamespaces = /\.(.*)$/, + fcleanup = function( nm ) { + return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { + return "\\" + ch; + }); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery.data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events = elemData.events || {}, + eventHandle = elemData.handle, eventHandle; + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + handleObj.guid = handler.guid; + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)") + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( var j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( var j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[expando] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + jQuery.each( jQuery.cache, function() { + if ( this.events && this.events[type] ) { + jQuery.event.trigger( event, data, this.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery.data( elem, "handle" ); + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var target = event.target, old, + isClick = jQuery.nodeName(target, "a") && type === "click", + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ type ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + type ]; + + if ( old ) { + target[ "on" + type ] = null; + } + + jQuery.event.triggered = true; + target[ type ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( old ) { + target[ "on" + type ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace, events; + + event = arguments[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + var events = jQuery.data(this, "events"), handlers = events[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, arguments ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, body = document.body; + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) { + event.which = event.charCode || event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); + }, + + remove: function( handleObj ) { + var remove = true, + type = handleObj.origType.replace(rnamespaces, ""); + + jQuery.each( jQuery.data(this, "events").live || [], function() { + if ( type === this.origType.replace(rnamespaces, "") ) { + remove = false; + return false; + } + }); + + if ( remove ) { + jQuery.event.remove( this, handleObj.origType, liveHandler ); + } + } + + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( this.setInterval ) { + this.onbeforeunload = eventHandle; + } + + return false; + }, + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +var removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + elem.removeEventListener( type, handle, false ); + } : + function( elem, type, handle ) { + elem.detachEvent( "on" + type, handle ); + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = now(); + + // Mark it as fixed + this[ expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + } + // otherwise set the returnValue property of the original event to false (IE) + e.returnValue = false; + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var formElems = /textarea|input|select/i, + + changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery.data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery.data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + return jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information/focus[in] is not needed anymore + beforeactivate: function( e ) { + var elem = e.target; + jQuery.data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return formElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return formElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + context.each(function(){ + jQuery.event.add( this, liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + }); + + } else { + // unbind live handler + context.unbind( liveConvert( type, selector ), fn ); + } + } + + return this; + } +}); + +function liveHandler( event ) { + var stop, elems = [], selectors = [], args = arguments, + related, match, handleObj, elem, j, i, l, data, + events = jQuery.data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) + if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { + return; + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( match[i].selector === handleObj.selector ) { + elem = match[i].elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) { + stop = false; + break; + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( fn ) { + return fn ? this.bind( name, fn ) : this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + +// Prevent memory leaks in IE +// Window isn't included so as not to unbind existing unload events +// More info: +// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ +if ( window.attachEvent && !window.addEventListener ) { + window.attachEvent("onunload", function() { + for ( var id in jQuery.cache ) { + if ( jQuery.cache[ id ].handle ) { + // Try/Catch is to handle iframes being unloaded, see #4280 + try { + jQuery.event.remove( jQuery.cache[ id ].handle.elem ); + } catch(e) {} + } + } + }); +} +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + var origContext = context = context || document; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context), + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + var ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + var ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + var cur = parts.pop(), pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set, match; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + match: { + ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string"; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return /h\d/i.test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return /input|select|textarea|button/i.test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var i = 0, l = not.length; i < l; i++ ) { + if ( not[i] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){ + return "\\" + (num - 0 + 1); + })); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var i = 0, l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( var i = 0; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.compareDocumentPosition ? -1 : 1; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.sourceIndex ? -1 : 1; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.ownerDocument ? -1 : 1; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +function getText( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date).getTime(); + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +var contains = document.compareDocumentPosition ? function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +var isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = getText; +jQuery.isXMLDoc = isXML; +jQuery.contains = contains; + +return; + +window.Sizzle = Sizzle; + +})(); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + slice = Array.prototype.slice; + +// Implement the identical functionality for filter and not +var winnow = function( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + if ( jQuery.isArray( selectors ) ) { + var ret = [], cur = this[0], match, matches = {}, selector; + + if ( cur && selectors.length ) { + for ( var i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur }); + delete matches[selector]; + } + } + cur = cur.parentNode; + } + } + + return ret; + } + + var pos = jQuery.expr.match.POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + return this.map(function( i, cur ) { + while ( cur && cur.ownerDocument && cur !== context ) { + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) { + return cur; + } + cur = cur.parentNode; + } + return null; + }); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context || this.context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call(arguments).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], cur = elem[dir]; + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g, + rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i, + rtagName = /<([\w:]+)/, + rtbody = /"; + }, + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and From d9e885e0901eb81552b2258d829ed11a9921b24b Mon Sep 17 00:00:00 2001 From: haneul Date: Fri, 23 Apr 2010 11:49:45 +0000 Subject: [PATCH 51/74] do not check change of content git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7389 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/editor/skins/xpresseditor/js/Xpress_Editor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/editor/skins/xpresseditor/js/Xpress_Editor.js b/modules/editor/skins/xpresseditor/js/Xpress_Editor.js index 1a4ab0a9a..1f91fdfdb 100644 --- a/modules/editor/skins/xpresseditor/js/Xpress_Editor.js +++ b/modules/editor/skins/xpresseditor/js/Xpress_Editor.js @@ -2785,8 +2785,8 @@ xe.XE_EditingAreaManager = $.Class({ this.oApp.registerBrowserEvent(this.elEditingAreaSkipUI, "focus", "MSG_EDITING_AREA_SIZE_CHANGED", [], 50); this.oApp.registerBrowserEvent(this.elEditingAreaSkipUI, "blur", "MSG_EDITING_AREA_SIZE_CHANGED", [], 50); - var fOnBeforeUnload = this.fOnBeforeUnload||function(){if(this.getIR() != this.oIRField.value || this.bIsDirty) return this.oApp.$MSG("XE_EditingAreaManager.onExit")}; - $(window).bind("beforeunload", $.fnBind(fOnBeforeUnload, this)); +// var fOnBeforeUnload = this.fOnBeforeUnload||function(){if(this.getIR() != this.oIRField.value || this.bIsDirty) return this.oApp.$MSG("XE_EditingAreaManager.onExit")}; +// $(window).bind("beforeunload", $.fnBind(fOnBeforeUnload, this)); }, $AFTER_MSG_APP_READY : function(){ @@ -6212,4 +6212,4 @@ xe.XE_Table = $.Class({ } }).extend(xe.XE_Table); -})(jQuery); \ No newline at end of file +})(jQuery); From 7cbc63875fb2cc9ebd137a7eba5c896f4ae07e0d Mon Sep 17 00:00:00 2001 From: haneul Date: Sat, 24 Apr 2010 12:46:11 +0000 Subject: [PATCH 52/74] #18856422 : fixed a bug that group info is removed when administrator modifies member_info git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7390 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/member/member.controller.php | 2 +- modules/member/member.model.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/member/member.controller.php b/modules/member/member.controller.php index 98faa4158..faa4c4f53 100644 --- a/modules/member/member.controller.php +++ b/modules/member/member.controller.php @@ -1261,7 +1261,7 @@ if($site_srl) $args->site_srl = $site_srl; $oModel =& getModel('member'); - $groups = $oModel->getMemberGroups($member_srl, $site_srl); + $groups = $oModel->getMemberGroups($member_srl, $site_srl, true); if($groups[$group_srl]) return new Object(); // 추가 diff --git a/modules/member/member.model.php b/modules/member/member.model.php index 9282acc05..997d65c36 100644 --- a/modules/member/member.model.php +++ b/modules/member/member.model.php @@ -287,9 +287,9 @@ /** * @brief member_srl이 속한 group 목록을 가져옴 **/ - function getMemberGroups($member_srl, $site_srl = 0) { + function getMemberGroups($member_srl, $site_srl = 0, $force_reload = false) { static $member_groups = array(); - if(!$member_groups[$member_srl][$site_srl]) { + if(!$member_groups[$member_srl][$site_srl] || $force_reload) { $args->member_srl = $member_srl; $args->site_srl = $site_srl; $output = executeQuery('member.getMemberGroups', $args); From d02f39171b919f6e0cc7538d3dd6ca76658416f4 Mon Sep 17 00:00:00 2001 From: haneul Date: Sat, 24 Apr 2010 14:08:34 +0000 Subject: [PATCH 53/74] #18820891 : add android for smartphone git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7391 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- addons/smartphone/classes/smartphone.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/smartphone/classes/smartphone.class.php b/addons/smartphone/classes/smartphone.class.php index c44db018a..9ac28d955 100644 --- a/addons/smartphone/classes/smartphone.class.php +++ b/addons/smartphone/classes/smartphone.class.php @@ -16,7 +16,7 @@ return false; } - return Context::get('smartphone') || preg_match('/(iPod|iPhone|SCH\-M[0-9]+)/',$_SERVER['HTTP_USER_AGENT']); + return Context::get('smartphone') || preg_match('/(iPod|iPhone|Android|SCH\-M[0-9]+)/',$_SERVER['HTTP_USER_AGENT']); } function haveSmartphoneModule($module) { @@ -80,7 +80,7 @@ } function procSmartPhone($msg = null) { - if(preg_match('/(iPod|iPhone)/',$_SERVER['HTTP_USER_AGENT'])) { + if(preg_match('/(iPod|iPhone|Android)/',$_SERVER['HTTP_USER_AGENT'])) { Context::addHtmlHeader(''); } else if(preg_match('/SCH\-M[0-9]+/',$_SERVER['HTTP_USER_AGENT'])) { Context::addHtmlHeader(''); From 314dbb6ba7f8386ddaa63a6a22b84f4eaa7e0611 Mon Sep 17 00:00:00 2001 From: haneul Date: Sat, 24 Apr 2010 14:15:23 +0000 Subject: [PATCH 54/74] #18820393 : add captcha for signup git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7392 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- addons/captcha/captcha.addon.php | 1 + addons/captcha/conf/info.xml | 52 ++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/addons/captcha/captcha.addon.php b/addons/captcha/captcha.addon.php index be31532d6..b51a2eae5 100644 --- a/addons/captcha/captcha.addon.php +++ b/addons/captcha/captcha.addon.php @@ -21,6 +21,7 @@ $target_acts = array('procBoardInsertDocument','procBoardInsertComment','procIssuetrackerInsertIssue','procIssuetrackerInsertHistory','procTextyleInsertComment'); if($addon_info->apply_find_account=='apply') $target_acts[] = 'procMemberFindAccount'; if($addon_info->apply_resend_auth_mail=='apply') $target_acts[] = 'procMemberResendAuthMail'; + if($addon_info->apply_signup=='apply') $target_acts[] = 'procMemberInsert'; Context::addHtmlHeader(''); diff --git a/addons/captcha/conf/info.xml b/addons/captcha/conf/info.xml index 84fa33804..ddff4abfa 100644 --- a/addons/captcha/conf/info.xml +++ b/addons/captcha/conf/info.xml @@ -34,17 +34,17 @@ 此元件可防止機器人程式的垃圾留言,非註冊用戶在討論板/問題追蹤發表主題或評論時,必須要先選對畫面中所顯示的圖案才能發表。 - 0.1 + 0.2 2009-02-20 - - zero - zero - zero - zero - zero - zero - zero + + XE + XE + XE + XE + XE + XE + XE @@ -184,5 +184,39 @@ Áp dụng + + 회원 가입 적용 + Apply to member signup + 인증 메일 재발송 적용 + 인증 메일 재발송 적용 + Apply to member signup + Apply to member signup + Apply to member signup + 적용으로 하시면 회원가입 기능에도 적용되어 악의적인 봇(또는 프로그램)의 회원가입을 막을 수 있습니다. + 적용으로 하시면 회원가입 기능에도 적용되어 악의적인 봇(또는 프로그램)의 회원가입을 막을 수 있습니다. + 적용으로 하시면 회원가입 기능에도 적용되어 악의적인 봇(또는 프로그램)의 회원가입을 막을 수 있습니다. + If you set this option as apply, CAPTCHA will work for signup action, too. + If you set this option as apply, CAPTCHA will work for signup action, too. + If you set this option as apply, CAPTCHA will work for signup action, too. + If you set this option as apply, CAPTCHA will work for signup action, too. + + 적용하지 않음 + 不启用 + 적용하지 않음 + 적용하지 않음 + Not apply + Not apply + Không áp dụng + + + 적용 + 启用 + 적용 + 적용 + Apply + Apply + Áp dụng + + From 22a41b02e40194c0179520b70651d8a55e081fb6 Mon Sep 17 00:00:00 2001 From: royallin Date: Sun, 25 Apr 2010 03:06:52 +0000 Subject: [PATCH 55/74] update Taiwanese git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7393 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- addons/captcha/conf/info.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/captcha/conf/info.xml b/addons/captcha/conf/info.xml index ddff4abfa..c28903fc3 100644 --- a/addons/captcha/conf/info.xml +++ b/addons/captcha/conf/info.xml @@ -120,7 +120,7 @@ 비밀번호 찾기 적용 应用到查找密码功能 비밀번호 찾기 적용 - 비밀번호 찾기 적용 + 忘記密碼 applying to an action finding account applying to an action finding account Khi lấy lại mật khẩu @@ -135,7 +135,7 @@ 적용하지 않음 不启用 적용하지 않음 - 적용하지 않음 + 關閉 Not apply Not apply Không áp dụng @@ -144,7 +144,7 @@ 적용 启用 적용 - 적용 + 開啟 Apply Apply Áp dụng @@ -154,7 +154,7 @@ 인증 메일 재발송 적용 应用到认证邮件重新发送功能 인증 메일 재발송 적용 - 인증 메일 재발송 적용 + 重寄認證信 apply to an action resending authmail apply to an action resending authmail Khi lấy lại mã kích hoạt @@ -169,7 +169,7 @@ 적용하지 않음 不启用 적용하지 않음 - 적용하지 않음 + 關閉 Not apply Not apply Không áp dụng @@ -178,7 +178,7 @@ 적용 启用 적용 - 적용 + 開啟 Apply Apply Áp dụng From 527545099bfc129b470447197bd0dfe9e3586eec Mon Sep 17 00:00:00 2001 From: ngleader Date: Mon, 26 Apr 2010 09:04:56 +0000 Subject: [PATCH 56/74] =?UTF-8?q?#18858663=20cubrid=20incr=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=EC=8B=9C=20=ED=95=84=EB=93=9C=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7394 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- classes/db/DBCubrid.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/db/DBCubrid.class.php b/classes/db/DBCubrid.class.php index 65f0075e1..4bfc4bf32 100644 --- a/classes/db/DBCubrid.class.php +++ b/classes/db/DBCubrid.class.php @@ -506,7 +506,7 @@ $name = $val['name']; $value = $val['value']; - if(substr($value,-2)!='+1') $check_click_count = false; + if(substr($value,-2)!='+1' || $output->column_type[$name]!='number') $check_click_count = false; for ($i = 0; $i < $key; $i++) { // 한문장에 같은 속성에 대한 중복 설정은 큐브리드에서는 허용치 않음 if ($output->columns[$i]['name'] == $name) break; From 1788b5083bf2cc9cc9ac8221dbbfd6905f1680aa Mon Sep 17 00:00:00 2001 From: haneul Date: Mon, 26 Apr 2010 14:09:14 +0000 Subject: [PATCH 57/74] =?UTF-8?q?#18829511=20:=20handle=20Korean=20Charact?= =?UTF-8?q?er=20in=20MSIE=20(thanks=20to=20=EA=B8=B0=EC=A7=84=EA=B3=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7395 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/file/file.controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/file/file.controller.php b/modules/file/file.controller.php index 65f2299e7..7cf96bd11 100644 --- a/modules/file/file.controller.php +++ b/modules/file/file.controller.php @@ -210,7 +210,7 @@ // 파일 출력 if(strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { - $filename = urlencode($filename); + $filename = rawurlencode($filename); $filename = preg_replace('/\./', '%2e', $filename, substr_count($filename, '.') - 1); } From bc414542bfbbb7573f249b2e668f9af4b8274c47 Mon Sep 17 00:00:00 2001 From: haneul Date: Mon, 26 Apr 2010 14:26:25 +0000 Subject: [PATCH 58/74] =?UTF-8?q?#18754919=20:=20specify=20error=20message?= =?UTF-8?q?=20for=20file=20download=20-=20thanks=20to=20=ED=8C=8C=EC=9D=B4?= =?UTF-8?q?=EB=8D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7396 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/file/file.controller.php | 4 ++-- modules/file/lang/en.lang.php | 1 + modules/file/lang/es.lang.php | 1 + modules/file/lang/fr.lang.php | 1 + modules/file/lang/jp.lang.php | 1 + modules/file/lang/ko.lang.php | 1 + modules/file/lang/ru.lang.php | 1 + modules/file/lang/vi.lang.php | 1 + modules/file/lang/zh-CN.lang.php | 1 + modules/file/lang/zh-TW.lang.php | 1 + 10 files changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/file/file.controller.php b/modules/file/file.controller.php index 7cf96bd11..e5472fbcc 100644 --- a/modules/file/file.controller.php +++ b/modules/file/file.controller.php @@ -174,7 +174,7 @@ } else $file_module_config->allow_outlink = 'Y'; } - if($file_module_config->allow_outlink != 'Y') return $this->stop('msg_not_permitted_download'); + if($file_module_config->allow_outlink != 'Y') return $this->stop('msg_not_allowed_outlink'); } // 파일 다운로드 권한이 있는지 확인 @@ -206,7 +206,7 @@ // trigger 호출 (before) $output = ModuleHandler::triggerCall('file.downloadFile', 'before', $file_obj); - if(!$output->toBool()) return $this->stop('msg_not_permitted_download'); + if(!$output->toBool()) return $this->stop(($output->message)?$output->message:'msg_not_permitted_download'); // 파일 출력 if(strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { diff --git a/modules/file/lang/en.lang.php b/modules/file/lang/en.lang.php index bb9036ad8..cdcb3a6f3 100644 --- a/modules/file/lang/en.lang.php +++ b/modules/file/lang/en.lang.php @@ -52,4 +52,5 @@ 'nick_name' => 'Nickname', 'ipaddress' => 'IP Address', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> diff --git a/modules/file/lang/es.lang.php b/modules/file/lang/es.lang.php index d2074cc96..b378ba4fd 100644 --- a/modules/file/lang/es.lang.php +++ b/modules/file/lang/es.lang.php @@ -49,4 +49,5 @@ 'regdate' => 'La fecha registrada', 'ipaddress' => 'Dirección IP', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> diff --git a/modules/file/lang/fr.lang.php b/modules/file/lang/fr.lang.php index 913ec3a3b..695177b2c 100644 --- a/modules/file/lang/fr.lang.php +++ b/modules/file/lang/fr.lang.php @@ -49,4 +49,5 @@ 'regdate' => 'Enrgistre', 'ipaddress' => 'Adresse IP', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> diff --git a/modules/file/lang/jp.lang.php b/modules/file/lang/jp.lang.php index a451947a5..dc733fc92 100644 --- a/modules/file/lang/jp.lang.php +++ b/modules/file/lang/jp.lang.php @@ -51,4 +51,5 @@ 'regdate' => '登録日', 'ipaddress' => 'IPアドレス', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> diff --git a/modules/file/lang/ko.lang.php b/modules/file/lang/ko.lang.php index 3d55f1a38..14746eb17 100644 --- a/modules/file/lang/ko.lang.php +++ b/modules/file/lang/ko.lang.php @@ -51,4 +51,5 @@ 'regdate' => '등록일', 'ipaddress' => 'IP 주소', ); + $lang->msg_not_allowed_outlink = '외부링크에서 다운로드 할 수 없습니다.'; ?> diff --git a/modules/file/lang/ru.lang.php b/modules/file/lang/ru.lang.php index 63cae3dd5..5fba0b748 100644 --- a/modules/file/lang/ru.lang.php +++ b/modules/file/lang/ru.lang.php @@ -51,4 +51,5 @@ 'regdate' => 'Дата регистрации', 'ipaddress' => 'IP-Адрес', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> diff --git a/modules/file/lang/vi.lang.php b/modules/file/lang/vi.lang.php index 3e32357b3..6f66c09aa 100644 --- a/modules/file/lang/vi.lang.php +++ b/modules/file/lang/vi.lang.php @@ -54,4 +54,5 @@ 'nick_name' => 'Nickname', 'ipaddress' => 'IP', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> diff --git a/modules/file/lang/zh-CN.lang.php b/modules/file/lang/zh-CN.lang.php index 7f2fa43ab..ccbfa9d41 100644 --- a/modules/file/lang/zh-CN.lang.php +++ b/modules/file/lang/zh-CN.lang.php @@ -49,4 +49,5 @@ 'regdate' => '登录日期', 'ipaddress' => 'IP地址', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> diff --git a/modules/file/lang/zh-TW.lang.php b/modules/file/lang/zh-TW.lang.php index 3ee55c732..70c54c28d 100644 --- a/modules/file/lang/zh-TW.lang.php +++ b/modules/file/lang/zh-TW.lang.php @@ -51,4 +51,5 @@ 'regdate' => '登錄日期', 'ipaddress' => 'IP位址', ); + $lang->msg_not_allowed_outlink = 'It is not allowed to download files not from this site.'; ?> From a3c2f4b8fb205d1d0aff6d8163055251d32d4dbd Mon Sep 17 00:00:00 2001 From: haneul Date: Tue, 27 Apr 2010 04:51:03 +0000 Subject: [PATCH 59/74] #18731525 : remove the limitation on module types in point setting page git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7397 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/point/tpl/module_config.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/point/tpl/module_config.html b/modules/point/tpl/module_config.html index ae1f28408..ec66b85d3 100644 --- a/modules/point/tpl/module_config.html +++ b/modules/point/tpl/module_config.html @@ -17,7 +17,6 @@ -
    {$val->browser_title} ({$val->mid})
    @@ -31,7 +30,6 @@ {$config->point_name} - From 258159d0a3de73ec4850063b9ed77451e162e66f Mon Sep 17 00:00:00 2001 From: haneul Date: Tue, 27 Apr 2010 09:48:11 +0000 Subject: [PATCH 60/74] message specification git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7398 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/admin/admin.admin.model.php | 3 ++- modules/admin/lang/en.lang.php | 1 + modules/admin/lang/es.lang.php | 1 + modules/admin/lang/fr.lang.php | 1 + modules/admin/lang/jp.lang.php | 1 + modules/admin/lang/ko.lang.php | 1 + modules/admin/lang/ru.lang.php | 1 + modules/admin/lang/vi.lang.php | 1 + modules/admin/lang/zh-CN.lang.php | 1 + modules/admin/lang/zh-TW.lang.php | 1 + 10 files changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/admin/admin.admin.model.php b/modules/admin/admin.admin.model.php index df1a77202..7269a14e2 100644 --- a/modules/admin/admin.admin.model.php +++ b/modules/admin/admin.admin.model.php @@ -19,7 +19,8 @@ $sftp = ssh2_sftp($connection); $curpwd = "ssh2.sftp://$sftp".$this->pwd; - $dh = opendir($curpwd); + $dh = @opendir($curpwd); + if(!$dh) return new Object(-1, 'msg_ftp_invalid_path'); $list = array(); while(($file = readdir($dh)) !== false) { if(is_dir($curpwd.$file)) diff --git a/modules/admin/lang/en.lang.php b/modules/admin/lang/en.lang.php index a110e6a70..ab68d6605 100644 --- a/modules/admin/lang/en.lang.php +++ b/modules/admin/lang/en.lang.php @@ -81,4 +81,5 @@ $lang->sftp = "Use SFTP"; $lang->ftp_get_list = "Get List"; $lang->ftp_remove_info = 'Remove FTP Info.'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> diff --git a/modules/admin/lang/es.lang.php b/modules/admin/lang/es.lang.php index 52d223e67..6b0dd8011 100644 --- a/modules/admin/lang/es.lang.php +++ b/modules/admin/lang/es.lang.php @@ -83,4 +83,5 @@ $lang->sftp = "Use SFTP"; $lang->ftp_get_list = "Get List"; $lang->ftp_remove_info = 'Remove FTP Info.'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> diff --git a/modules/admin/lang/fr.lang.php b/modules/admin/lang/fr.lang.php index a2c057634..ed62986c2 100644 --- a/modules/admin/lang/fr.lang.php +++ b/modules/admin/lang/fr.lang.php @@ -82,4 +82,5 @@ $lang->sftp = "Use SFTP"; $lang->ftp_get_list = "Get List"; $lang->ftp_remove_info = 'Remove FTP Info.'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> diff --git a/modules/admin/lang/jp.lang.php b/modules/admin/lang/jp.lang.php index 877db6107..c3f59e90a 100644 --- a/modules/admin/lang/jp.lang.php +++ b/modules/admin/lang/jp.lang.php @@ -81,4 +81,5 @@ $lang->sftp = "Use SFTP"; $lang->ftp_get_list = "Get List"; $lang->ftp_remove_info = 'Remove FTP Info.'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> diff --git a/modules/admin/lang/ko.lang.php b/modules/admin/lang/ko.lang.php index 731aa660e..de1a11923 100644 --- a/modules/admin/lang/ko.lang.php +++ b/modules/admin/lang/ko.lang.php @@ -81,4 +81,5 @@ $lang->sftp = 'SFTP 사용'; $lang->ftp_get_list = '목록 가져오기'; $lang->ftp_remove_info = 'FTP 정보 삭제'; + $lang->msg_ftp_invalid_path = 'FTP Path를 읽을 수 없습니다.'; ?> diff --git a/modules/admin/lang/ru.lang.php b/modules/admin/lang/ru.lang.php index 9b5854063..0e0e7b21f 100644 --- a/modules/admin/lang/ru.lang.php +++ b/modules/admin/lang/ru.lang.php @@ -80,4 +80,5 @@ $lang->sftp = 'Use SFTP'; $lang->ftp_get_list = 'Get List'; $lang->ftp_remove_info = 'Remove FTP Info'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> diff --git a/modules/admin/lang/vi.lang.php b/modules/admin/lang/vi.lang.php index 7805bd5af..0b54d4c5d 100644 --- a/modules/admin/lang/vi.lang.php +++ b/modules/admin/lang/vi.lang.php @@ -83,4 +83,5 @@ $lang->sftp = "Use SFTP"; $lang->ftp_get_list = "Get List"; $lang->ftp_remove_info = 'Remove FTP Info.'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> diff --git a/modules/admin/lang/zh-CN.lang.php b/modules/admin/lang/zh-CN.lang.php index e21ae8ced..509a90897 100644 --- a/modules/admin/lang/zh-CN.lang.php +++ b/modules/admin/lang/zh-CN.lang.php @@ -81,4 +81,5 @@ $lang->sftp = "Use SFTP"; $lang->ftp_get_list = "Get List"; $lang->ftp_remove_info = 'Remove FTP Info.'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> diff --git a/modules/admin/lang/zh-TW.lang.php b/modules/admin/lang/zh-TW.lang.php index 2195009a6..9bc6b0d52 100644 --- a/modules/admin/lang/zh-TW.lang.php +++ b/modules/admin/lang/zh-TW.lang.php @@ -81,4 +81,5 @@ $lang->sftp = "使用 SFTP"; $lang->ftp_get_list = "取得列表"; $lang->ftp_remove_info = '移除 FTP 資料'; + $lang->msg_ftp_invalid_path = 'Failed to read the specified FTP Path.'; ?> From 10a9cbf34769a00303d72e112034dd201f3b6e10 Mon Sep 17 00:00:00 2001 From: haneul Date: Tue, 27 Apr 2010 10:05:58 +0000 Subject: [PATCH 61/74] #18859373 : module uninstall git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7399 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- .../autoinstall.admin.controller.php | 55 +++- .../autoinstall/autoinstall.admin.view.php | 81 ++++- modules/autoinstall/autoinstall.lib.php | 290 ++++++++++++++---- modules/autoinstall/autoinstall.model.php | 49 ++- modules/autoinstall/conf/info.xml | 4 +- modules/autoinstall/conf/module.xml | 2 + modules/autoinstall/lang/en.lang.php | 2 + modules/autoinstall/lang/jp.lang.php | 2 + modules/autoinstall/lang/ko.lang.php | 2 + modules/autoinstall/lang/ru.lang.php | 2 + modules/autoinstall/lang/vi.lang.php | 2 + modules/autoinstall/lang/zh-CN.lang.php | 2 + modules/autoinstall/lang/zh-TW.lang.php | 2 + .../queries/getInstalledPackages.xml | 9 +- modules/autoinstall/tpl/css/autoinstall.css | 2 +- .../tpl/filter/uninstall_package.xml | 10 + modules/autoinstall/tpl/js/autoinstall.js | 8 + modules/autoinstall/tpl/list.html | 17 +- modules/autoinstall/tpl/uninstall.html | 14 + 19 files changed, 480 insertions(+), 75 deletions(-) create mode 100644 modules/autoinstall/tpl/filter/uninstall_package.xml create mode 100644 modules/autoinstall/tpl/uninstall.html diff --git a/modules/autoinstall/autoinstall.admin.controller.php b/modules/autoinstall/autoinstall.admin.controller.php index 33ca2e3c4..dddc75c9c 100644 --- a/modules/autoinstall/autoinstall.admin.controller.php +++ b/modules/autoinstall/autoinstall.admin.controller.php @@ -57,16 +57,14 @@ continue; } - if($package->path == ".") - { - $type = "core"; + $type = $oModel->getTypeFromPath($package->path); + if($type == "core") + { $version = __ZBXE_VERSION__; - } + } else { - $path_array = explode("/", $package->path); - $target_name = array_pop($path_array); - $type = substr(array_pop($path_array), 0, -1); + $config_file = null; switch($type) { case "module": @@ -86,10 +84,8 @@ $config_file = "/info.xml"; $type = "component"; break; - - default: - continue; } + if(!$config_file) continue; $xml = new XmlParser(); $xmlDoc = $xml->loadXmlFile($real_path.$config_file); if(!$xmlDoc) continue; @@ -136,7 +132,7 @@ { $oModuleInstaller = new SFTPModuleInstaller($package); } - else if(function_exists(ftp_connect)) + else if(false && function_exists(ftp_connect)) { $oModuleInstaller = new PHPFTPModuleInstaller($package); } @@ -196,5 +192,42 @@ executeQuery("autoinstall.insertCategory", $args); } } + + function procAutoinstallAdminUninstallPackage() + { + $package_srl = Context::get('package_srl'); + $oModel =& getModel('autoinstall'); + $package = $oModel->getPackage($package_srl); + $path = $package->path; + + if(!$_SESSION['ftp_password']) + { + $ftp_password = Context::get('ftp_password'); + } + else + { + $ftp_password = $_SESSION['ftp_password']; + } + $ftp_info = Context::getFTPInfo(); + + if($ftp_info->sftp && $ftp_info->sftp == 'Y') + { + $oModuleInstaller = new SFTPModuleInstaller($package); + } + else if(function_exists(ftp_connect)) + { + $oModuleInstaller = new PHPFTPModuleInstaller($package); + } + else + { + $oModuleInstaller = new FTPModuleInstaller($package); + } + + $oModuleInstaller->setPassword($ftp_password); + $output = $oModuleInstaller->uninstall(); + if(!$output->toBool()) return $output; + + $this->setMessage('success_deleted'); + } } ?> diff --git a/modules/autoinstall/autoinstall.admin.view.php b/modules/autoinstall/autoinstall.admin.view.php index e6e23d751..719941a3a 100644 --- a/modules/autoinstall/autoinstall.admin.view.php +++ b/modules/autoinstall/autoinstall.admin.view.php @@ -9,6 +9,7 @@ class autoinstallAdminView extends autoinstall { var $categories; + var $ftp_set = false; function init() { $template_path = sprintf("%stpl/",$this->module_path); @@ -18,6 +19,8 @@ $ftp_info = Context::getFTPInfo(); if(!$ftp_info->ftp_root_path) Context::set('show_ftp_note', true); + else $this->ftp_set = true; + $this->dispCategory(); $oModel = &getModel('autoinstall'); @@ -39,7 +42,7 @@ { if(!is_array($items)) $items = array($items); $item_list = array(); - $targets = array('category_srl', 'package_srl', 'item_screenshot_url', 'package_voted', 'package_voter', 'package_description', 'package_downloaded', 'item_regdate', 'title', 'item_version', 'package_star'); + $targets = array('category_srl', 'package_srl', 'item_screenshot_url', 'package_voted', 'package_voter', 'package_description', 'package_downloaded', 'item_regdate', 'title', 'item_version', 'package_star', 'depfrom'); $targetpackages = array(); foreach($items as $item) { @@ -48,7 +51,7 @@ $oModel = &getModel('autoinstall'); if($package == null) $packages = $oModel->getInstalledPackages(array_keys($targetpackages)); - + $depto = array(); foreach($items as $item) { $v = $this->rearrange($item, $targets); @@ -56,10 +59,52 @@ { $v->current_version = $packages[$v->package_srl]->current_version; $v->need_update = $packages[$v->package_srl]->need_update; + $v->type = $oModel->getTypeFromPath($packages[$v->package_srl]->path); + if($this->ftp_set && $v->depfrom) { + $depfrom = explode("," , $v->depfrom); + foreach($depfrom as $package_srl) + { + $depto[$package_srl][] = $v->package_srl; + } + } + if($v->type == "core") $v->avail_remove = false; + else if($v->type == "module") { + $v->avail_remove = $oModel->checkRemovable($packages[$v->package_srl]->path); + } + else $v->avail_remove = true; } $item_list[$v->package_srl] = $v; } + if(count($depto) > 0) + { + $installed = $oModel->getInstalledPackages(implode(",", array_keys($depto))); + foreach($installed as $key=>$val) + { + $path = $val->path; + $type = $oModel->getTypeFromPath($path); + if(!$type || $type == "core") continue; + $config_file = $oModel->getConfigFilePath($type); + if(!$config_file) continue; + + $xml = new XmlParser(); + $xmlDoc = $xml->loadXmlFile(FileHandler::getRealPath($path).$config_file); + if(!$xmlDoc) continue; + if($type == "drcomponent") $type = "component"; + $title = $xmlDoc->{$type}->title->body; + $installed[$key]->title = $title; + } + Context::set('installed', $installed); + foreach($installed as $key=>$val) + { + foreach($depto[$key] as $package_srl) + { + $item_list[$package_srl]->avail_remove = false; + $item_list[$package_srl]->deps[] = $key; + } + } + } + return $item_list; } @@ -235,5 +280,37 @@ $this->categories = &$oModel->getCategoryList(); Context::set('categories', $this->categories); } + + function dispAutoinstallAdminUninstall() + { + $package_srl = Context::get('package_srl'); + if(!$package_srl) return $this->dispAutoinstallAdminIndex(); + $oModel =& getModel('autoinstall'); + $installedPackage = $oModel->getInstalledPackage($package_srl); + if(!$installedPackage) return $this->dispAutoinstallAdminInstalledPackages(); + + if(!$_SESSION['ftp_password']) + { + Context::set('need_password', true); + } + $installedPackage = $oModel->getPackage($package_srl); + $path = $installedPackage->path; + $type = $oModel->getTypeFromPath($path); + if(!$type || $type == "core") $this->stop("msg_invalid_request"); + $config_file = $oModel->getConfigFilePath($type); + if(!$config_file) $this->stop("msg_invalid_request"); + + $xml = new XmlParser(); + $xmlDoc = $xml->loadXmlFile(FileHandler::getRealPath($path).$config_file); + if(!$xmlDoc) $this->stop("msg_invalid_request"); + if($type == "drcomponent") $type = "component"; + $title = $xmlDoc->{$type}->title->body; + $installedPackage->title = $title; + $installedPackage->type = $type; + Context::set('package', $installedPackage); + + $this->setTemplateFile('uninstall'); + Context::addJsFilter($this->module_path.'tpl/filter', 'uninstall_package.xml'); + } } ?> diff --git a/modules/autoinstall/autoinstall.lib.php b/modules/autoinstall/autoinstall.lib.php index dc729ed98..abedcfc9a 100644 --- a/modules/autoinstall/autoinstall.lib.php +++ b/modules/autoinstall/autoinstall.lib.php @@ -10,6 +10,23 @@ var $download_path; var $ftp_password; + function uninstall() + { + $oModel =& getModel('autoinstall'); + $type = $oModel->getTypeFromPath($this->package->path); + if($type == "module") { + $output = $this->uninstallModule(); + if(!$output->toBool()) return $output; + } + + $output = $this->_connect(); + if(!$output->toBool()) return $output; + + $output = $this->_removeDir($this->package->path); + $this->_close(); + return $output; + } + function setPassword($ftp_password) { $this->ftp_password = $ftp_password; @@ -41,11 +58,38 @@ FileHandler::writeFile($this->download_file, $buff); } - function installModule() - { + function uninstallModule() + { $path_array = explode("/", $this->package->path); $target_name = array_pop($path_array); - $type = substr(array_pop($path_array), 0, -1); + $oModule =& getModule($target_name, "class"); + if(!$oModule) return new Object(-1, 'msg_invalid_request'); + if(!method_exists($oModule, "moduleUninstall")) return new Object(-1, 'msg_invalid_request'); + + $output = $oModule->moduleUninstall(); + if(!$output->toBool()) return $output; + + $schema_dir = sprintf('%s/schemas/', $this->package->path); + $schema_files = FileHandler::readDir($schema_dir); + $oDB =& DB::getInstance(); + foreach($schema_files as $file) + { + $filename_arr = explode(".", $file); + $filename = array_shift($filename_arr); + $oDB->dropTable($filename); + } + return new Object(); + } + + function installModule() + { + $path = $this->package->path; + if($path != ".") { + $path_array = explode("/", $path); + $target_name = array_pop($path_array); + $type = substr(array_pop($path_array), 0, -1); + } + if($type == "module") { $oModuleModel = &getModel('module'); @@ -97,38 +141,100 @@ return $file_list; } + function _removeDir($path) { + $real_path = FileHandler::getRealPath($path); + $oDir = dir($path); + $files = array(); + while($file = $oDir->read()) { + if($file == "." || $file == "..") continue; + $files[] = $file; + } + + foreach($files as $file) + { + $file_path = $path."/".$file; + if(is_dir(FileHandler::getRealPath($file_path))) + { + $output = $this->_removeDir($file_path); + if(!$output->toBool()) return $output; + } + else + { + $output = $this->_removeFile($file_path); + if(!$output->toBool()) return $output; + } + } + $output = $this->_removeDir_real($path); + return $output; + } + } class SFTPModuleInstaller extends ModuleInstaller { + var $ftp_info = null; + var $connection = null; + var $sftp = null; + function SFTPModuleInstaller(&$package) { $this->package =& $package; + $this->ftp_info = Context::getFTPInfo(); } - function _copyDir(&$file_list){ - if(!$this->ftp_password) return new Object(-1,'msg_ftp_password_input'); - - $ftp_info = Context::getFTPInfo(); - if(!$ftp_info->ftp_user || !$ftp_info->sftp || $ftp_info->sftp != 'Y') return new Object(-1,'msg_ftp_invalid_auth_info'); + function _connect() { + if(!$this->ftp_info->ftp_user || !$this->ftp_info->sftp || $this->ftp_info->sftp != 'Y') return new Object(-1,'msg_ftp_invalid_auth_info'); - if($ftp_info->ftp_host) + if($this->ftp_info->ftp_host) { - $ftp_host = $ftp_info->ftp_host; + $ftp_host = $this->ftp_info->ftp_host; } else { $ftp_host = "127.0.0.1"; } - $connection = ssh2_connect($ftp_host, $ftp_info->ftp_port); - if(!ssh2_auth_password($connection, $ftp_info->ftp_user, $this->ftp_password)) + $this->connection = ssh2_connect($ftp_host, $this->ftp_info->ftp_port); + if(!ssh2_auth_password($this->connection, $this->ftp_info->ftp_user, $this->ftp_password)) { return new Object(-1,'msg_ftp_invalid_auth_info'); } $_SESSION['ftp_password'] = $this->ftp_password; + $this->sftp = ssh2_sftp($this->connection); + return new Object(); + } - $sftp = ssh2_sftp($connection); + function _close() { + } - $target_dir = $ftp_info->ftp_root_path.$this->target_path; + function _removeFile($path) + { + if(substr($path, 0, 2) == "./") $path = substr($path, 2); + $target_path = $this->ftp_info->ftp_root_path.$path; + + if(!@ssh2_sftp_unlink($this->sftp, $target_path)) + { + return new Object(-1, "failed to delete file ".$path); + } + return new Object(); + } + + function _removeDir_real($path) + { + if(substr($path, 0, 2) == "./") $path = substr($path, 2); + $target_path = $this->ftp_info->ftp_root_path.$path; + + if(!@ssh2_sftp_rmdir($this->sftp, $target_path)) + { + return new Object(-1, "failed to delete directory ".$path); + } + return new Object(); + } + + function _copyDir(&$file_list){ + if(!$this->ftp_password) return new Object(-1,'msg_ftp_password_input'); + + $output = $this->_connect(); + if(!$output->toBool()) return $output; + $target_dir = $this->ftp_info->ftp_root_path.$this->target_path; foreach($file_list as $k => $file){ $org_file = $file; @@ -141,10 +247,10 @@ if(!file_exists(FileHandler::getRealPath($real_path))) { - ssh2_sftp_mkdir($sftp, $pathname, 0755, true); + ssh2_sftp_mkdir($this->sftp, $pathname, 0755, true); } - ssh2_scp_send($connection, FileHandler::getRealPath($this->download_path."/".$org_file), $target_dir."/".$file); + ssh2_scp_send($this->connection, FileHandler::getRealPath($this->download_path."/".$org_file), $target_dir."/".$file); } return new Object(); } @@ -152,38 +258,79 @@ class PHPFTPModuleInstaller extends ModuleInstaller { + var $ftp_info = null; + var $connection = null; + function PHPFTPModuleInstaller(&$package) { $this->package =& $package; + $this->ftp_info = Context::getFTPInfo(); } - function _copyDir(&$file_list) { - if(!$this->ftp_password) return new Object(-1,'msg_ftp_password_input'); - - $ftp_info = Context::getFTPInfo(); - if($ftp_info->ftp_host) + function _connect() + { + if($this->ftp_info->ftp_host) { - $ftp_host = $ftp_info->ftp_host; + $ftp_host = $this->ftp_info->ftp_host; } else { $ftp_host = "127.0.0.1"; } - $connection = ftp_connect($ftp_host, $ftp_info->ftp_port); - if(!$connection) return new Object(-1, 'msg_ftp_not_connected'); - $login_result = @ftp_login($connection, $ftp_info->ftp_user, $this->ftp_password); + $this->connection = ftp_connect($ftp_host, $this->ftp_info->ftp_port); + if(!$this->connection) return new Object(-1, 'msg_ftp_not_connected'); + + $login_result = @ftp_login($this->connection, $this->ftp_info->ftp_user, $this->ftp_password); if(!$login_result) { + $this->_close(); return new Object(-1,'msg_ftp_invalid_auth_info'); } - $_SESSION['ftp_password'] = $this->ftp_password; - if($ftp_info->ftp_pasv != "N") - { - ftp_pasv($connection, true); - } - $target_dir = $ftp_info->ftp_root_path.$this->target_path; + $_SESSION['ftp_password'] = $this->ftp_password; + if($this->ftp_info->ftp_pasv != "N") + { + ftp_pasv($this->connection, true); + } + return new Object(); + } + + function _removeFile($path) + { + if(substr($path, 0, 2) == "./") $path = substr($path, 2); + $target_path = $this->ftp_info->ftp_root_path.$path; + + if(!@ftp_delete($this->connection, $target_path)) + { + return new Object(-1, "failed to delete file ".$path); + } + return new Object(); + } + + function _removeDir_real($path) + { + if(substr($path, 0, 2) == "./") $path = substr($path, 2); + $target_path = $this->ftp_info->ftp_root_path.$path; + + if(!@ftp_rmdir($this->connection, $target_path)) + { + return new Object(-1, "failed to delete directory ".$path); + } + return new Object(); + } + + + function _close() { + ftp_close($this->connection); + } + + function _copyDir(&$file_list) { + if(!$this->ftp_password) return new Object(-1,'msg_ftp_password_input'); + + $output = $this->_connect(); + if(!$output->toBool()) return $output; + $target_dir = $this->ftp_info->ftp_root_path.$this->target_path; foreach($file_list as $k => $file){ $org_file = $file; @@ -195,7 +342,7 @@ $path_list = explode('/', dirname($this->target_path."/".$file)); $real_path = "./"; - $ftp_path = $ftp_info->ftp_root_path; + $ftp_path = $this->ftp_info->ftp_root_path; for($i=0;$iconnection, $ftp_path)) { return new Object(-1, "msg_make_directory_failed"); } @@ -212,14 +359,14 @@ if(!stristr(PHP_OS, 'win')) { if (function_exists('ftp_chmod')) { - if(!ftp_chmod($connection, 0755, $ftp_path)) + if(!ftp_chmod($this->connection, 0755, $ftp_path)) { return new Object(-1, "msg_permission_adjust_failed"); } } else { - if(!ftp_site($connection, "CHMOD 755 ".$ftp_path)) + if(!ftp_site($this->connection, "CHMOD 755 ".$ftp_path)) { return new Object(-1, "msg_permission_adjust_failed"); } @@ -227,49 +374,85 @@ } } } - if(!ftp_put($connection, $target_dir .'/'. $file, FileHandler::getRealPath($this->download_path."/".$org_file), FTP_BINARY)) + if(!ftp_put($this->connection, $target_dir .'/'. $file, FileHandler::getRealPath($this->download_path."/".$org_file), FTP_BINARY)) { return new Object(-1, "msg_ftp_upload_failed"); } } - ftp_close($connection); + $this->_close(); return new Object(); } } class FTPModuleInstaller extends ModuleInstaller { + var $oFtp = null; + var $ftp_info = null; + function FTPModuleInstaller(&$package) { $this->package =& $package; + $this->ftp_info = Context::getFTPInfo(); } - function _copyDir(&$file_list){ - $ftp_info = Context::getFTPInfo(); - if(!$this->ftp_password) return new Object(-1,'msg_ftp_password_input'); - - require_once(_XE_PATH_.'libs/ftp.class.php'); - - if($ftp_info->ftp_host) + function _connect() { + if($this->ftp_info->ftp_host) { - $ftp_host = $ftp_info->ftp_host; + $ftp_host = $this->ftp_info->ftp_host; } else { $ftp_host = "127.0.0.1"; } - $oFtp = new ftp(); - if(!$oFtp->ftp_connect($ftp_host, $ftp_info->ftp_port)) return new Object(-1,'msg_ftp_not_connected'); - if(!$oFtp->ftp_login($ftp_info->ftp_user, $this->ftp_password)) { - $oFtp->ftp_quit(); + $this->oFtp = new ftp(); + if(!$this->oFtp->ftp_connect($ftp_host, $this->ftp_info->ftp_port)) return new Object(-1,'msg_ftp_not_connected'); + if(!$this->oFtp->ftp_login($this->ftp_info->ftp_user, $this->ftp_password)) { + $this->_close(); return new Object(-1,'msg_ftp_invalid_auth_info'); } $_SESSION['ftp_password'] = $this->ftp_password; + return new Object(); + } - $_list = $oFtp->ftp_rawlist($ftp_info->ftp_root_path); + function _removeFile($path) + { + if(substr($path, 0, 2) == "./") $path = substr($path, 2); + $target_path = $this->ftp_info->ftp_root_path.$path; - $target_dir = $ftp_info->ftp_root_path.$this->target_path; + if(!$this->oFtp->ftp_delete($target_path)) + { + return new Object(-1, "failed to delete file ".$path); + } + return new Object(); + } + + function _removeDir_real($path) + { + if(substr($path, 0, 2) == "./") $path = substr($path, 2); + $target_path = $this->ftp_info->ftp_root_path.$path; + + if(!$this->oFtp->ftp_rmdir($target_path)) + { + return new Object(-1, "failed to delete directory ".$path); + } + return new Object(); + } + + function _close() { + $this->oFtp->ftp_quit(); + } + + function _copyDir(&$file_list){ + if(!$this->ftp_password) return new Object(-1,'msg_ftp_password_input'); + + require_once(_XE_PATH_.'libs/ftp.class.php'); + + $output = $this->_connect(); + if(!$output->toBool()) return $output; + + $oFtp =& $this->oFtp; + $target_dir = $this->ftp_info->ftp_root_path.$this->target_path; foreach($file_list as $k => $file){ $org_file = $file; @@ -281,7 +464,7 @@ $path_list = explode('/', dirname($this->target_path."/".$file)); $real_path = "./"; - $ftp_path = $ftp_info->ftp_root_path; + $ftp_path = $this->ftp_info->ftp_root_path; for($i=0;$iftp_put($target_dir .'/'. $file, FileHandler::getRealPath($this->download_path."/".$org_file)); } - $oFtp->ftp_quit(); + + $this->_close(); return new Object(); } diff --git a/modules/autoinstall/autoinstall.model.php b/modules/autoinstall/autoinstall.model.php index ddd75db62..bd836a45c 100644 --- a/modules/autoinstall/autoinstall.model.php +++ b/modules/autoinstall/autoinstall.model.php @@ -108,8 +108,8 @@ return array_shift($output->data); } - function getInstalledPackages(&$package_list) { - $args->package_list = &$package_list; + function getInstalledPackages($package_list) { + $args->package_list = $package_list; $output = executeQueryArray("autoinstall.getInstalledPackages", $args); $result = array(); if(!$output->data) return $result; @@ -133,5 +133,50 @@ return $output; } + function getTypeFromPath($path) + { + if(!$path) return null; + if($path == ".") return "core"; + $path_array = explode("/", $path); + $target_name = array_pop($path_array); + $type = substr(array_pop($path_array), 0, -1); + return $type; + } + + function getConfigFilePath($type) + { + $config_file = null; + switch($type) + { + case "module": + case "addon": + case "layout": + case "widget": + $config_file = "/conf/info.xml"; + break; + case "component": + $config_file = "/info.xml"; + break; + case "skin": + case "widgetstyle": + $config_file = "/skin.xml"; + break; + case "drcomponent": + $config_file = "/info.xml"; + break; + } + return $config_file; + } + + function checkRemovable($path) + { + $path_array = explode("/", $path); + $target_name = array_pop($path_array); + $oModule =& getModule($target_name, "class"); + if(!$oModule) return false; + if(method_exists($oModule, "moduleUninstall")) return true; + else return false; + } + } ?> diff --git a/modules/autoinstall/conf/info.xml b/modules/autoinstall/conf/info.xml index 3be4f24ef..f3c28fa4d 100644 --- a/modules/autoinstall/conf/info.xml +++ b/modules/autoinstall/conf/info.xml @@ -1,7 +1,7 @@ 쉬운 설치 - One Click Installer + EasyInstaller Cài đặt tự động 自動安裝 在线安装 @@ -12,7 +12,7 @@ 可以藉由此模組安裝、更新程式包括模組、面板、版面等。 很方便的在管理页面一键安装XE相关模块(模块/皮肤/布局/控件/控件样式等)。 管理者モードにてクリックだけで、モジュール/スキン/レイアウト/ウィジェット/ウィジェットスタイルのインストールを可能にするモジュールです。 - 0.2 + 0.3 2009-11-11 system diff --git a/modules/autoinstall/conf/module.xml b/modules/autoinstall/conf/module.xml index e43224438..f2b2b7b26 100644 --- a/modules/autoinstall/conf/module.xml +++ b/modules/autoinstall/conf/module.xml @@ -2,6 +2,8 @@ + + diff --git a/modules/autoinstall/lang/en.lang.php b/modules/autoinstall/lang/en.lang.php index 4410f41fc..6edc8fe90 100644 --- a/modules/autoinstall/lang/en.lang.php +++ b/modules/autoinstall/lang/en.lang.php @@ -30,4 +30,6 @@ $lang->cmd_download = "Download"; $lang->view_installed_packages = "Installed Packages"; $lang->msg_ftp_password_input = "Please input FTP password."; + $lang->dependant_list = "이 패키지에 의존하는 패키지 목록"; + $lang->description_uninstall = "패키지를 삭제합니다. 모듈의 경우 모든 데이터가 사라집니다."; ?> diff --git a/modules/autoinstall/lang/jp.lang.php b/modules/autoinstall/lang/jp.lang.php index b22567405..7e41ef822 100644 --- a/modules/autoinstall/lang/jp.lang.php +++ b/modules/autoinstall/lang/jp.lang.php @@ -30,4 +30,6 @@ $lang->cmd_download = "ダウンロード"; $lang->view_installed_packages = "Installed Packages"; $lang->msg_ftp_password_input = "Please input FTP password."; + $lang->dependant_list = "이 패키지에 의존하는 패키지 목록"; + $lang->description_uninstall = "패키지를 삭제합니다. 모듈의 경우 모든 데이터가 사라집니다."; ?> diff --git a/modules/autoinstall/lang/ko.lang.php b/modules/autoinstall/lang/ko.lang.php index 9d9363565..5e2a2db75 100644 --- a/modules/autoinstall/lang/ko.lang.php +++ b/modules/autoinstall/lang/ko.lang.php @@ -30,4 +30,6 @@ $lang->cmd_download = "다운로드"; $lang->view_installed_packages = "설치된 패키지"; $lang->msg_ftp_password_input = "FTP 비밀번호를 입력해주세요"; + $lang->dependant_list = "이 패키지에 의존하는 패키지 목록"; + $lang->description_uninstall = "패키지를 삭제합니다. 모듈의 경우 모든 데이터가 사라집니다."; ?> diff --git a/modules/autoinstall/lang/ru.lang.php b/modules/autoinstall/lang/ru.lang.php index 850d02037..b5114a422 100644 --- a/modules/autoinstall/lang/ru.lang.php +++ b/modules/autoinstall/lang/ru.lang.php @@ -30,4 +30,6 @@ $lang->cmd_download = 'Download'; $lang->view_installed_packages = 'Installed Packages'; $lang->msg_ftp_password_input = 'Please input FTP password'; + $lang->dependant_list = " Ű ϴ Ű "; + $lang->description_uninstall = "Ű մϴ. Ͱ ϴ."; ?> diff --git a/modules/autoinstall/lang/vi.lang.php b/modules/autoinstall/lang/vi.lang.php index bbbd63ebb..301636a54 100644 --- a/modules/autoinstall/lang/vi.lang.php +++ b/modules/autoinstall/lang/vi.lang.php @@ -30,4 +30,6 @@ $lang->cmd_download = "Download"; $lang->view_installed_packages = "Installed Packages"; $lang->msg_ftp_password_input = "Please input FTP password."; + $lang->dependant_list = "이 패키지에 의존하는 패키지 목록"; + $lang->description_uninstall = "패키지를 삭제합니다. 모듈의 경우 모든 데이터가 사라집니다."; ?> diff --git a/modules/autoinstall/lang/zh-CN.lang.php b/modules/autoinstall/lang/zh-CN.lang.php index a8a9dbee8..9aa92385a 100644 --- a/modules/autoinstall/lang/zh-CN.lang.php +++ b/modules/autoinstall/lang/zh-CN.lang.php @@ -30,4 +30,6 @@ $lang->cmd_download = "Download"; $lang->view_installed_packages = "Installed Packages"; $lang->msg_ftp_password_input = "Please input FTP password."; + $lang->dependant_list = "이 패키지에 의존하는 패키지 목록"; + $lang->description_uninstall = "패키지를 삭제합니다. 모듈의 경우 모든 데이터가 사라집니다."; ?> diff --git a/modules/autoinstall/lang/zh-TW.lang.php b/modules/autoinstall/lang/zh-TW.lang.php index d2f902967..03abf06a4 100644 --- a/modules/autoinstall/lang/zh-TW.lang.php +++ b/modules/autoinstall/lang/zh-TW.lang.php @@ -30,4 +30,6 @@ $lang->cmd_download = "下載"; $lang->view_installed_packages = "已安裝套裝軟體"; $lang->msg_ftp_password_input = "請輸入 FTP 密碼"; + $lang->dependant_list = "이 패키지에 의존하는 패키지 목록"; + $lang->description_uninstall = "패키지를 삭제합니다. 모듈의 경우 모든 데이터가 사라집니다."; ?> diff --git a/modules/autoinstall/queries/getInstalledPackages.xml b/modules/autoinstall/queries/getInstalledPackages.xml index da8512403..5b66fc879 100644 --- a/modules/autoinstall/queries/getInstalledPackages.xml +++ b/modules/autoinstall/queries/getInstalledPackages.xml @@ -1,11 +1,14 @@ - +
    +
    - + + - + + diff --git a/modules/autoinstall/tpl/css/autoinstall.css b/modules/autoinstall/tpl/css/autoinstall.css index 5280d98b6..492b9772c 100644 --- a/modules/autoinstall/tpl/css/autoinstall.css +++ b/modules/autoinstall/tpl/css/autoinstall.css @@ -38,7 +38,7 @@ .updateList td .title{ position:relative;} .updateList td .title h3 { padding:0; margin:0 0 5px 0; font-size:12px;} .updateList td .title a {text-decoration:none; color:#333 !important; } -.updateList td .title .button{ position:absolute; top:0; right:0;} +.updateList td .title .buttons{ position:absolute; top:0; right:0;} .updateList td .info p{ margin:0 0 5px 0; line-height:1.5;} .updateList td .info p.desc{ margin:0 100px 10px 0;} .updateList td .info p.meta{ font-size:11px;} diff --git a/modules/autoinstall/tpl/filter/uninstall_package.xml b/modules/autoinstall/tpl/filter/uninstall_package.xml new file mode 100644 index 000000000..6df9b6f8e --- /dev/null +++ b/modules/autoinstall/tpl/filter/uninstall_package.xml @@ -0,0 +1,10 @@ + +
    + + + + + + +
    + diff --git a/modules/autoinstall/tpl/js/autoinstall.js b/modules/autoinstall/tpl/js/autoinstall.js index 10534b04d..863927c9d 100644 --- a/modules/autoinstall/tpl/js/autoinstall.js +++ b/modules/autoinstall/tpl/js/autoinstall.js @@ -31,3 +31,11 @@ function completeInstall(ret_obj) { exec_xml('autoinstall', 'procAutoinstallAdminUpdateinfo', params, completeUpdateNoMsg); } +function completeUninstall(ret_obj) { + alert(ret_obj['message']); + if(ret_obj['error'] != 0) return; + var params = new Array(); + exec_xml('autoinstall', 'procAutoinstallAdminUpdateinfo', params, completeUpdateNoMsg); +} + + diff --git a/modules/autoinstall/tpl/list.html b/modules/autoinstall/tpl/list.html index 6b97a8af1..a7c2343b3 100644 --- a/modules/autoinstall/tpl/list.html +++ b/modules/autoinstall/tpl/list.html @@ -37,12 +37,27 @@ {htmlspecialchars($val->title)} ver. {htmlspecialchars($val->item_version)} - {$lang->current_version} : {$val->current_version} +

    {$lang->current_version} : {$val->current_version} + +
    + {$lang->dependant_list} : + + {$installed[$package_srl]->title}. + + +

    + +
    diff --git a/modules/autoinstall/tpl/uninstall.html b/modules/autoinstall/tpl/uninstall.html new file mode 100644 index 000000000..1ed2bb27c --- /dev/null +++ b/modules/autoinstall/tpl/uninstall.html @@ -0,0 +1,14 @@ + + + +
    +

    {$package->title} [{$package->type}] - {$package->path}

    +

    {$lang->description_uninstall}

    +
    + + +

    + + + +
    From eb2c09f36ed9101c8023a9244391ebc1de5170b8 Mon Sep 17 00:00:00 2001 From: haneul Date: Tue, 27 Apr 2010 10:06:26 +0000 Subject: [PATCH 62/74] remove test code git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7400 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/autoinstall/autoinstall.admin.controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/autoinstall/autoinstall.admin.controller.php b/modules/autoinstall/autoinstall.admin.controller.php index dddc75c9c..382a48b59 100644 --- a/modules/autoinstall/autoinstall.admin.controller.php +++ b/modules/autoinstall/autoinstall.admin.controller.php @@ -132,7 +132,7 @@ { $oModuleInstaller = new SFTPModuleInstaller($package); } - else if(false && function_exists(ftp_connect)) + else if(function_exists(ftp_connect)) { $oModuleInstaller = new PHPFTPModuleInstaller($package); } From f4ec255afa3fb4e2edfc111947280bcd7f359cb4 Mon Sep 17 00:00:00 2001 From: haneul Date: Wed, 28 Apr 2010 08:37:51 +0000 Subject: [PATCH 63/74] #18701077 : fixed a bug that redirect error when a module of virtual sites is set as default module git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7401 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/module/module.model.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/module/module.model.php b/modules/module/module.model.php index df5602383..fe3d7a758 100644 --- a/modules/module/module.model.php +++ b/modules/module/module.model.php @@ -83,7 +83,9 @@ $path = preg_replace('/\/$/','',$url_info['path']); $sites_args->domain = sprintf('%s%s%s', $hostname, $url_info['port']&&$url_info['port']!=80?':'.$url_info['port']:'',$path); $output = executeQuery('module.getSiteInfoByDomain', $sites_args); - } else { + } + if(!$output || !$output->data) + { if(!$vid) $vid = $mid; if($vid) { $vid_args->domain = $vid; @@ -127,7 +129,6 @@ $output = executeQuery('module.getSiteInfo', $args); } } - $module_info = $output->data; if(!$module_info->module_srl) return $module_info; if(is_array($module_info) && $module_info->data[0]) $module_info = $module_info[0]; From 7a0f0d64eac492356ecfd696cf9e68c2bf916f90 Mon Sep 17 00:00:00 2001 From: haneul Date: Wed, 28 Apr 2010 10:11:34 +0000 Subject: [PATCH 64/74] #18702288 : fixed bugs in permission of editor component git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7402 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/editor/editor.controller.php | 10 ++++++- modules/editor/editor.model.php | 41 ++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/modules/editor/editor.controller.php b/modules/editor/editor.controller.php index 7e4843990..0d66ffaa8 100644 --- a/modules/editor/editor.controller.php +++ b/modules/editor/editor.controller.php @@ -359,7 +359,15 @@ if($component->extra_vars) { $extra_vars = unserialize($component->extra_vars); + if($extra_vars->target_group) { + $xml_info->target_group = $extra_vars->target_group; + } + if($extra_vars->mid_list && count($extra_vars->mid_list)) + { + $xml_info->mid_list = $extra_vars->mid_list; + } + /* // 사용권한이 있으면 권한 체크 if($extra_vars->target_group) { // 사용권한이 체크되어 있는데 로그인이 되어 있지 않으면 무조건 사용 중지 @@ -382,7 +390,7 @@ // 대상 모듈이 있으면 체크 if($extra_vars->mid_list && count($extra_vars->mid_list) && Context::get('mid')) { if(!in_array(Context::get('mid'), $extra_vars->mid_list)) continue; - } + }*/ // 에디터 컴포넌트의 설정 정보를 체크 if($xml_info->extra_vars) { diff --git a/modules/editor/editor.model.php b/modules/editor/editor.model.php index b24c9f96e..cd233cc33 100644 --- a/modules/editor/editor.model.php +++ b/modules/editor/editor.model.php @@ -556,14 +556,23 @@ * @brief component 목록을 return (DB정보 보함) **/ function getComponentList($filter_enabled = true, $site_srl=0) { - $cache_file = $this->getCacheFile($filter_enabled, $site_srl); + $cache_file = $this->getCacheFile(false, $site_srl); if(!file_exists($cache_file)) { $oEditorController = &getController('editor'); - $oEditorController->makeCache($filter_enabled, $site_srl); + $oEditorController->makeCache(false, $site_srl); } if(!file_exists($cache_file)) return; @include($cache_file); + $logged_info = Context::get('logged_info'); + if($logged_info && is_array($logged_info->group_list)) + { + $group_list = array_keys($logged_info->group_list); + } + else + { + $group_list = array(); + } if(count($component_list)) { foreach($component_list as $key => $val) { @@ -572,6 +581,34 @@ FileHandler::removeFile($cache_file); return $this->getComponentList($filter_enabled, $site_srl); } + if($val->enabled == "N") { + unset($component_list->{$key}); + continue; + } + if($logged_info->is_admin == "Y" || $logged_info->is_site_admin == "Y") continue; + if($val->target_group) + { + if(!$logged_info) { + $val->enabled = "N"; + } + else { + $is_granted = false; + foreach($group_list as $group_srl) + { + if(in_array($group_srl, $val->target_group)) $is_granted = true; + } + if(!$is_granted) $val->enabled = "N"; + } + } + if($val->enabled != "N" && $val->mid_list) + { + $mid = Context::get('mid'); + if(!in_array($mid, $val->mid_list)) $val->enabled = "N"; + } + if($val->enabled == "N") { + unset($component_list->{$key}); + continue; + } } } From 2bb707dd0809fb0d853a4cefec99ea761b1364d5 Mon Sep 17 00:00:00 2001 From: haneul Date: Wed, 28 Apr 2010 14:46:27 +0000 Subject: [PATCH 65/74] #18793978 : add voted, blamed point in the module setting git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7403 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/point/tpl/point_module_config.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/point/tpl/point_module_config.html b/modules/point/tpl/point_module_config.html index 43bbea74e..50bbb92f4 100644 --- a/modules/point/tpl/point_module_config.html +++ b/modules/point/tpl/point_module_config.html @@ -26,6 +26,14 @@
    + + + + + + + + - + - +
    {$lang->point_read_document}
    {$module_config['point_name']}
    {$lang->point_voted}
    {$config->point_name}
    {$lang->point_blamed}
    {$config->point_name}
    From 79fcb6e5414c44037af763dfc6d0d21756d7dd93 Mon Sep 17 00:00:00 2001 From: haneul Date: Wed, 28 Apr 2010 14:48:46 +0000 Subject: [PATCH 66/74] point_name git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7404 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/point/tpl/point_module_config.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/point/tpl/point_module_config.html b/modules/point/tpl/point_module_config.html index 50bbb92f4..030c18b0f 100644 --- a/modules/point/tpl/point_module_config.html +++ b/modules/point/tpl/point_module_config.html @@ -28,11 +28,11 @@
    {$lang->point_voted}
    {$config->point_name} {$module_config['point_name']}
    {$lang->point_blamed}
    {$config->point_name} {$module_config['point_name']}
    From 4b4e01b81dc6a7a9afcb6af49a7dda171943e047 Mon Sep 17 00:00:00 2001 From: haneul Date: Wed, 28 Apr 2010 15:01:53 +0000 Subject: [PATCH 67/74] #18822693 : add document_srl, member_srl, module_srl for triggered delete of comment git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7405 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/comment/queries/getAllComments.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/comment/queries/getAllComments.xml b/modules/comment/queries/getAllComments.xml index 14d0d1a35..b220598a3 100644 --- a/modules/comment/queries/getAllComments.xml +++ b/modules/comment/queries/getAllComments.xml @@ -4,6 +4,9 @@ + + + From b8910c3d2df9ae890b7d00f26f8f04ac5f025859 Mon Sep 17 00:00:00 2001 From: haneul Date: Wed, 28 Apr 2010 16:23:59 +0000 Subject: [PATCH 68/74] #18709101 : change mail format for windows git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7406 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- classes/mail/Mail.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/mail/Mail.class.php b/classes/mail/Mail.class.php index 7a4712528..e0fe0becc 100644 --- a/classes/mail/Mail.class.php +++ b/classes/mail/Mail.class.php @@ -43,7 +43,7 @@ } function getSender() { - if($this->sender_name) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->sender_name).'?=', $this->sender_email); + if(!stristr(PHP_OS, 'win') && $this->sender_name) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->sender_name).'?=', $this->sender_email); return $this->sender_email; } @@ -53,7 +53,7 @@ } function getReceiptor() { - if($this->receiptor_name && $this->receiptor_name != $this->receiptor_email) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->receiptor_name).'?=', $this->receiptor_email); + if(!stristr(PHP_OS, 'win') && $this->receiptor_name && $this->receiptor_name != $this->receiptor_email) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->receiptor_name).'?=', $this->receiptor_email); return $this->receiptor_email; } From ccd0c61c9fe9554d42b938f3c388f3327a22131c Mon Sep 17 00:00:00 2001 From: haneul Date: Wed, 28 Apr 2010 16:33:33 +0000 Subject: [PATCH 69/74] #18708272 : css modification for messages git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7407 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/communication/skins/default/css/default.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/communication/skins/default/css/default.css b/modules/communication/skins/default/css/default.css index 0f8a18c46..81c1ca0cc 100644 --- a/modules/communication/skins/default/css/default.css +++ b/modules/communication/skins/default/css/default.css @@ -75,7 +75,7 @@ #communicationModule .crossTable th.title *, #communicationModule .colTable th.title * { padding:0; margin:0; vertical-align:middle; } -#communicationModule p { color:#AAA; margin:3px 0 0 0; padding:0;} +#communicationModule p { margin:3px 0 0 0; padding:0;} #dummy_check_nick_name { color:red; margin:3px 0 0 0; padding:0; } #communicationModule .require { color:red; font-size:10px; font-family:tahoma; font-weight:bold; margin-left:5px; } #communicationModule .publicItem { margin:5px 0 0 0; padding:0; color:#aaa; } From 5600ba63c1f2cf659294c2248f3eb478bc190b6c Mon Sep 17 00:00:00 2001 From: haneul Date: Thu, 29 Apr 2010 02:42:43 +0000 Subject: [PATCH 70/74] #18864023 : set default time zone (for php5.3) git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7408 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- config/config.inc.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config/config.inc.php b/config/config.inc.php index fca9915f4..2aad45035 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -112,6 +112,14 @@ **/ require(_XE_PATH_.'config/func.inc.php'); + /** + * @brief Set Timezone as server time + **/ + if(version_compare(PHP_VERSION, '5.3.0') >= 0) + { + date_default_timezone_set(@date_default_timezone_get()); + } + if(__DEBUG__) define('__StartTime__', getMicroTime()); From 7f7a3a98c9170d852b473528a98fd76740c53e00 Mon Sep 17 00:00:00 2001 From: bnu Date: Thu, 29 Apr 2010 04:33:59 +0000 Subject: [PATCH 71/74] =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=EC=9D=84=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=ED=95=98=EC=97=AC=20euc-kr=EC=9D=B4=EB=A9=B4?= =?UTF-8?q?=20UTF-8=EB=A1=9C=20=EB=B3=80=ED=99=98=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80=20-=20detectUTF8()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7409 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- config/func.inc.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/config/func.inc.php b/config/func.inc.php index 668c12bbe..dca45029a 100644 --- a/config/func.inc.php +++ b/config/func.inc.php @@ -808,6 +808,20 @@ } + function detectUTF8($string, $return_convert = false, $urldecode = true) { + if($urldecode) $string = urldecode($string); + + $sample = iconv('utf-8', 'utf-8', $string); + $is_utf8 = (md5($sample) == md5($string)); + + if(!$urldecode) $string = urldecode($string); + + if($return_convert) return ($is_utf8) ? $string : iconv('euc-kr', 'utf-8', $string); + + return $is_utf8; + } + + function json_encode2($data) { switch (gettype($data)) { case 'boolean': From 9f10f636a13b3a407db9cfd92e8f75ccb00a5259 Mon Sep 17 00:00:00 2001 From: haneul Date: Thu, 29 Apr 2010 06:29:33 +0000 Subject: [PATCH 72/74] display korean-chars git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7410 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/admin/admin.admin.model.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/admin/admin.admin.model.php b/modules/admin/admin.admin.model.php index 7269a14e2..9e502f638 100644 --- a/modules/admin/admin.admin.model.php +++ b/modules/admin/admin.admin.model.php @@ -72,6 +72,10 @@ if($_list){ foreach($_list as $k => $v){ + $src = null; + $src->data = $v; + $res = Context::convertEncoding($src); + $v = $res->data; if(strpos($v,'d') === 0 || strpos($v, '')) $list[] = substr(strrchr($v,' '),1) . '/'; } } From ec733ca7d1d821329f0db8eeaad83144e543aa17 Mon Sep 17 00:00:00 2001 From: taggon Date: Thu, 29 Apr 2010 06:43:21 +0000 Subject: [PATCH 73/74] =?UTF-8?q?#18832818=20=EC=B0=BE=EA=B8=B0/=EB=B0=94?= =?UTF-8?q?=EA=BE=B8=EA=B8=B0=20=EC=B0=BD=EC=9D=B4=20=EB=82=98=ED=83=80?= =?UTF-8?q?=EB=82=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(Thanks=20to=20=ED=8C=8C=EC=9D=B4=EB=8D=B8?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7411 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- modules/editor/skins/xpresseditor/js/Xpress_Editor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/editor/skins/xpresseditor/js/Xpress_Editor.js b/modules/editor/skins/xpresseditor/js/Xpress_Editor.js index 1f91fdfdb..41cf1501b 100644 --- a/modules/editor/skins/xpresseditor/js/Xpress_Editor.js +++ b/modules/editor/skins/xpresseditor/js/Xpress_Editor.js @@ -2404,13 +2404,13 @@ xe.DialogLayerManager = $.Class({ bModal = $.$(bModal) || false; if(!oLayer) return; - if($.inArray(oLayer, this.aOpenedLayers)) return; + if($.inArray(oLayer, this.aOpenedLayers) != -1) return; this.oApp.exec("POSITION_DIALOG_LAYER", [oLayer]); this.aOpenedLayers[this.aOpenedLayers.length] = oLayer; - if(!$.inArray(oLayer, this.aMadeDraggable)){ + if($.inArray(oLayer, this.aMadeDraggable) == -1){ new xe.DraggableLayer(oLayer, {bModal: bModal, iMinY: 0}); this.aMadeDraggable[this.aMadeDraggable.length] = oLayer; }else{ From c91f6710231923eecd71aab9295c8d184e689ca0 Mon Sep 17 00:00:00 2001 From: haneul Date: Thu, 29 Apr 2010 06:51:06 +0000 Subject: [PATCH 74/74] version up to 1.4.1.0 git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7412 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- config/config.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.inc.php b/config/config.inc.php index 2aad45035..d373e9200 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -13,7 +13,7 @@ * @brief XE의 전체 버전 표기 * 이 파일의 수정이 없더라도 공식 릴리즈시에 수정되어 함께 배포되어야 함 **/ - define('__ZBXE_VERSION__', '1.4.0.11'); + define('__ZBXE_VERSION__', '1.4.1.0'); /** * @brief zbXE가 설치된 장소의 base path를 구함