/*================================================================
	ORC_JS, JavaScript Class Framework
 	version:3.10.80226
	Copyright 2007 by SourceTec Software Co.,LTD
	For more information, see:www.sothink.com
================================================================*/
if(typeof _STNS=="undefined"){if(!Array.prototype.push){Array.prototype.push=function(){for(var i=0;i<arguments.length;i++){this[this.length]=arguments[i];}return this.length;};}if(!Array.prototype.pop){Array.prototype.pop=function(){if(this.length){var o=this[this.length-1];this.length--;return o;}};}if(!Array.prototype.shift){Array.prototype.shift=function(){if(this.length){var o=this[0];for(var i=0;i<this.length-1;i++){this[i]=this[i+1];}this.length--;return o;}};}if(!Function.prototype.call){Function.prototype.call=function(_5){var _5=_5||window;_5.__tmp=this;var _6=_5.__tmp(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9],arguments[10]);_5.__tmp=null;return _6;};}_STNS={sVer:"3.0",bDebug:false,fvThrow:function(e){},bBufImg:true,oImgs:{},fvBufImgs:function(){if(!_STNS.bBufImg){return;}if(!_STNS.bLoaded){var s="";for(var i in _STNS.oImgs){if(_STNS.oImgs[i]!=2){s+=_STNS.fsGetTag("div","style=\"display:none\"",_STNS.fsGetImgTag(i,-1,-1));}_STNS.oImgs[i]=2;}document.write(s);}},bIsIE:false,bIsMIE:false,bIsFX:false,bIsOP:false,bIsSF:false,bIsKQ:false,oNav:null,bRTL:false,sDocMd:null,sURL:window.location.href+"",sDIR:null,bLocal:false,fsGetDocMd:function(w){var w=w||window;switch(w.document.compatMode){case "QuirksMode":case "BackCompat":return "quirks";case "CSS1Compat":return "css1";default:return document.compatMode;}},_foGetNav:function(){var _n=navigator,_u=_n.userAgent,_a=_n.appName,_p=_n.platform,n,v,p;if(/(Opera)[ \/]([\d\.]+)/.test(_u)||/(Netscape)\d*\/([\d\.]+)/.test(_u)||/(MSIE) ([\d\.]+)/.test(_u)||/(Safari)\/([\d\.]+)/.test(_u)||/(Konqueror)\/([\d\.]+)/.test(_u)||/(Gecko)\/(\d+)/.test(_u)){n=RegExp.$1.toLowerCase();v=RegExp.$2;}else{if(_a=="Netscape"&&_n.appVersion.charAt(0)=="4"){n="netscape4";v=parseFloat(_n.appVersion);}else{n="unknow";v=0;}}if(n=="netscape"){switch(_a){case "Microsoft Internet Explorer":n="msie";v=/(MSIE) ([\d\.]+)/.exec(_u)[2];break;case "Netscape":n="gecko";v=/(Gecko)\/(\d+)/.exec(_u)[2];}}if(/^(Win)/.test(_p)||/^(Mac)/.test(_p)||/^(SunOS)/.test(_p)||/^(Linux)/.test(_p)||/^(Unix)/.test(_p)){p=RegExp.$1.toLowerCase();}else{p=_p;}return {name:n,version:v,platform:p};},fiGetCT:function(w){var w=w||window;if(_STNS.bIsIE){return (_STNS.fsGetDocMd(w)=="css1"?w.document.documentElement:w.document.body).scrollTop;}else{return w.pageYOffset;}},fiGetCL:function(w){var w=w||window;if(_STNS.bIsIE){return (_STNS.fsGetDocMd(w)=="css1"?w.document.documentElement:w.document.body).scrollLeft;}else{return w.pageXOffset;}},fiGetCW:function(w){var w=w||window;if(_STNS.bIsIE){return (_STNS.fsGetDocMd(w)=="css1"?w.document.documentElement:w.document.body).clientWidth;}else{if(w.scrollbars&&w.scrollbars.visible||w.innerHeight<document.documentElement.offsetHeight){return w.innerWidth-20;}}return w.innerWidth;},fiGetCH:function(w){var w=w||window;if(_STNS.bIsIE){return (_STNS.fsGetDocMd(w)=="css1"?w.document.documentElement:w.document.body).clientHeight;}else{if(w.scrollbars&&w.scrollbars.visible||w.innerWidth<document.documentElement.offsetWidth){return w.innerHeight-20;}}return w.innerHeight;},foGetMediaInfor:function(s){_STNS.fvThrow(new Error("_STNS.runTime error:call foGetMediaInfor that has not been implemented"));},oLibs:{},sLibPth:"",fvInitLib:function(){var scs,sc,s,t,ls,pth;if(_STNS.bIsFX&&!_STNS.faGetElesByTagName("body").length){var hds=_STNS.faGetElesByTagName("head");sc=hds[0].lastChild;}else{scs=_STNS.faGetElesByTagName("script");sc=scs[scs.length-1];}if(sc){s=sc.src;}if(s){_STNS.sLibPth=s.substr(0,s.lastIndexOf("/")+1);t=_STNS.fcoGetAttribute(sc,"sothinkdebug");if(t=="true"){pth=_STNS.fsGetAbsPth(_STNS.sLibPth+"debug/stdebug.js");if(!_STNS.oLibs[pth]){_STNS.oLibs[pth]={state:1,defer:0};}}t=_STNS.fcoGetAttribute(sc,"sothinklib");if(t){ls=t.split(";");for(var i=0;i<ls.length;i++){if(!ls[i]){continue;}if(!_STNS.fbIsFile(ls[i])){ls[i]+=".js";}pth=_STNS.fsGetAbsPth(_STNS.sLibPth+ls[i]);if(_STNS.oLibs[pth]){continue;}_STNS.oLibs[pth]={state:1,defer:0};}}}else{_STNS.fvThrow(new Error("_STNS.runTime error:can't get lib path"));}},fvInc:function(s,f){if(!_STNS.oLibs[s]){_STNS.oLibs[s]={state:1,defer:f};}},fvLoadLib:function(){var s="";with(_STNS){for(var i in oLibs){if(oLibs[i].state!=2){if(bLoaded){fbInsJs(i);}else{s+=fsGetJsTag(i,oLibs[i].defer);}oLibs[i].state=2;}}}if(s){document.write(s);}},bLoaded:false,_aLoads:[],fbAddLoad:function(f){if(!_STNS.bLoaded&&typeof f=="function"){return _STNS._aLoads.push(f);}else{if(_STNS.bLoaded){_STNS.fvThrow(new Error("_STNS.runTime error:Page has been loaded!"));}else{_STNS.fvThrow(new Error("_STNS.runTime error:Not a function is pushed into onload event!"));}}return false;},_fvOnload:function(){with(_STNS){if(bLoaded){return;}bLoaded=true;for(var j=0;j<_aLoads.length;j++){_aLoads[j]();}}},_fvInitOnload:function(){if(_STNS.bIsIE&&window.attachEvent){window.attachEvent("onload",_STNS._fvOnload);}else{if(_STNS.oNav.name!="konqueror"&&window.addEventListener){window.addEventListener("load",_STNS._fvOnload,false);}else{if(!window.onload||window.onload.toString()!=_STNS._fvOnload.toString()){if(typeof window.onload=="function"){_STNS.fbAddLoad(window.onload);}onload=_STNS._fvOnload;}}}},_aCks:[],bCkPg:false,nCkTid:0,nCkTime:100,fvAddCk:function(f){if(typeof f=="function"){with(_STNS){if(bCkPg){clearTimeout(nCkTid);bCkPg=false;}_aCks.push(f);if(bLoaded){_fvCkPg();}}}else{_STNS.fvThrow(new Error("_STNS.runTime error:Not a function is pushed into check page event!"));}return false;},_fvCkPg:function(){with(_STNS){if(_aCks.length){bCkPg=true;for(var i=0;i<_aCks.length;i++){_aCks[i]();}nCkTid=setTimeout("_STNS._fvCkPg()",nCkTime);}else{bCkPg=false;}}},bShield:false,oDefCSS:{tb:"border-style:none;background-color:transparent;background-image:none;",tr:"border-style:none;background-color:transparent;background-image:none;",td:"border-style:none;background-color:transparent;background-image:none;",dv:"border-style:none;background-color:transparent;background-image:none;margin:0px;padding:0px;",a:"display:block;border-style:none;background-color:transparent;background-image:none;margin:0px;padding:0px;",hd:"display:none;",sp:"border-style:none;background-color:transparent;background-image:none;margin:0px;padding:0px;"},foCss2Obj:function(s){var o={},a,re=/([\w\-_]+):([^;]+)(;|$)/,ra;a=s.split(";");for(var i=0;i<a.length;i++){ra=re.exec(a[i]);if(ra){o[ra[1]]=ra[2];}}return o;},foCss2Style:function(s){var cs=_STNS.foCss2Obj(s),re=/-([a-z])/,o={},i,k,t;for(i in cs){t=re.exec(i);if(t){k=i.replace("-"+t[1],t[1].toUpperCase());}else{k=i;}o[k]=cs[i];}return o;},fsObj2Css:function(a){var s="";for(var i in a){if(a[i]!=null){s+=i+":"+a[i]+";";}}return s;},fvCSSShield:function(){with(_STNS){if(bLoaded){bShield=false;}else{if(faGetElesByTagName("body")&&faGetElesByTagName("body").length){bShield=false;}else{var i,s="\n<style type='text/css'>\n";for(i in oDefCSS){if(i=="a"){s+=".sta:link,.sta:hover,.sta:active,.sta:visited";}else{s+=".st"+i;}s+="{"+oDefCSS[i]+"}\n";}s+="</style>";bShield=true;document.write(s);}}}},fsReadCoki:function(n){var i,cs=document.cookie.split("; ");for(i=0;i<cs.length;i++){if(!cs[i].indexOf(n+"=")){return cs[i].substr(n.length);}}},fvSaveCoki:function(n,v,t){var s=n+"="+v+"; ",d=new Date;if(!t||!v){s+="expires=Fri, 31 Dec 1999 23:59:59 GMT; ";}else{s+="expires="+((new Date(d-0+t)).toGMTString())+"; ";}s+="path=/; ";document.cookie=s;},ffGetFun:function(f){if(typeof f=="function"){return f;}else{if(typeof f=="string"&&window[f]){return window[f];}}},fbIsAbsPth:function(s){var t=s.toLowerCase();return /^(#|\?|\/|[a-z]:|http:|https:|file:|ftp:|javascript:|vbscript:|mailto:|about:|gopher:|news:|res:|telnet:|view-source|wais:|rtsp:|mms:|outlook:)/.test(t);},fsGetAbsPth:function(s){if(!s){return s;}var re,t;if(!s.indexOf("//")){return s;}if(s.charAt(0)=="/"){re=/^(file:\/{2,}[^\/]+\/|http:\/\/[^\/]+\/|https:\/\/[^\/]+\/)/;if(re.exec(_STNS.sDIR)){s=RegExp.$1+s.substr(1);}else{return s;}}else{if(s=="#"){if(_STNS.sURL.charAt(_STNS.sURL.length-1)!="#"){return _STNS.sURL+"#";}else{return _STNS.sURL;}}else{if(!_STNS.fbIsAbsPth(s)){s=_STNS.sDIR+s;}else{return s;}}}while(s.indexOf("/./")>0){s=s.replace("/./","/");}while((t=s.indexOf("/../"))>0){var p1,p2;p1=s.substr(0,t);p2=s.substr(t).replace("/../","");p1=p1.substr(0,p1.lastIndexOf("/")+1);s=p1+p2;}return s;},fsGetImgTag:function(s,w,h,b,id,nw,nh){if(!s||!w||!h){return "";}if(nw&&nh){if(w==-1&&h==-1){w=nw,h=nh;}else{if(w==-1&&h!=-1){w=Math.floor(nw*h/nh);}else{if(w!=-1&&h==-1){h=Math.floor(nh*w/nw);}}}}return "<img class='stimg' src=\""+s+"\""+(w==-1?"":" width="+w)+(h==-1?"":" height="+h)+" border="+(b?b:0)+(id?" id='"+id+"'":"")+">";},fsGetJsTag:function(s,f){return "<script type='text/javascript' language='javascript1.2' src=\""+s+"\""+(f?" DEFER":"")+"></"+"script>";},fsGetTag:function(t,a,s){return "<"+t+" "+a+">"+(s?s:"")+"</"+t+">";},fbIsFile:function(s){return /\w+\.\w+$/.test(s);},fbIsImg:function(s){return /\.(gif|png|jpg|jpeg|bmp)$/.test(s.toLowerCase());},fsGetDIR:function(s){var t=s.toLowerCase();if(!t.indexOf("file:/")||!t.indexOf("http://")||!t.indexOf("https://")){return s.substr(0,s.lastIndexOf("/")+1);}else{return "";}},fsGetHTMLEnti:function(s,f){if(!s){return "";}var re;re=/&/g;s=s.replace(re,"&amp;");if(!f){re=/ /g;s=s.replace(re,"&nbsp;");}re=/</g;s=s.replace(re,"&lt;");re=/>/g;s=s.replace(re,"&gt;");re=/\"/g;s=s.replace(re,"&quot;");return s;},faJoinA:function(a,b){var c=[],l=Math.max(a.length,b.length);for(var i=0;i<l;i++){if(a[i]==null){c[i]=b[i];}else{c[i]=a[i];}}return c;},S64:"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ#@",fiTransX2D:function(n,m){m=String(m).replace(/ /gi,"");if(m==""){return 0;}var a=_STNS.S64.substr(0,n);if(eval("m.replace(/["+a+"]/gi,'')")!=""){_STNS.fvThrow(new Error("_STNS.runTime error:Transform bad number from "+m+" to 10!"));return 0;}var t=0,c=1;for(var x=m.length-1;x>-1;x--){t+=c*(a.indexOf(m.charAt(x)));c*=n;}return t;},fsTranD2X:function(n,m){m=String(m).replace(/ /gi,"");if(m==""){return 0;}if(parseInt(m)!=m){_STNS.fvThrow(new Error("_STNS.runTime error:Transform bad number from 10 to "+m+"!"));return "";}var t="",a=_STNS.S64.substr(0,n);while(m!=0){var b=m%n;t=a.charAt(b)+t;m=(m-b)/n;}if(!t){t="0";}return t;},faCP2PP:function(cp,w){var t,l;with(_STNS){t=fiGetCT(w);l=fiGetCL(w);return [cp[0]+l,cp[1]+t];}},faPP2CP:function(pp,w){var t,l;with(_STNS){t=fiGetCT(w);l=fiGetCL(w);return [pp[0]-l,pp[1]-t];}},fsGetLen:function(t,l,p,b,s,w){var _r=_STNS,u;if(w==null){w=true;}if(s==null){s=true;}if(p==null){p=0;}if(b==null){b=0;}if(typeof l=="string"){u=/%|px|pt|em|ex|pc|in|cm|mm$/.exec(l);}if(u){switch(u[0]){case "%":return l;default:u=u[0];}}else{l=parseInt(l);u="px";}switch(t){case "dv":if(_r.sDocMd=="css1"||(!_r.bIsIE&&!_r.bIsOP||(_r.bIsOP&&parseInt(_r.oNav.version)>=8))){return l-2*p-2*b+u;}break;case "tb":if(_r.bIsMIE&&!w&&s){return l-2*b-2*p+u;}break;case "td":if(_r.bIsSF){if(_r.sDocMd!="css1"||w){if(s){return l-2*b+u;}else{return l-2*p+u;}}else{return l-2*p-2*b+u;}}else{if(!_r.bIsMIE&&(_r.sDocMd=="css1"||w)){return l-2*b-2*p+u;}}break;}return l+u;},fdmGetEleById:function(id,w){var w=w||window;with(_STNS){if(bIsIE){var es=w.document.all(id);if(es&&es.length){return es[0];}else{return es;}}else{return w.document.getElementById(id);}}},faGetElesByTagName:function(n,w){var w=w||window;with(_STNS){if(bIsIE){return w.document.all.tags(n);}else{return w.document.getElementsByTagName(n);}}},faGetElesByCls:function(n,w){var w=w||window;var i,a=[],el,els=_STNS.bIsIE?w.document.all:w.document.getElementsByTagName("*");for(i=0;el=els[i];i++){if(el.className==n){a.push(el);}}return a;},fdmGetFmByName:function(n,w){var w=w||window;if(w.frames[t]){return w.frames[t];}else{if(w.parent){return w.parent.frames[t];}}},fbIsPar:function(p,c){if(_STNS.bIsIE){return p.contains(c);}else{if(!p||!c){return false;}if(p==c){return true;}do{if(c.parentNode){c=c.parentNode;}else{break;}if(p==c){return true;}}while(c);}return false;},fbInsHTML:function(e,p,h){if(_STNS.bIsIE){return e.insertAdjacentHTML(p,h);}else{var d=e.ownerDocument,t=d.createElement("span");t.innerHTML=h;switch(p){case "beforeBegin":return e.parentNode.insertBefore(t,e);case "afterBegin":return e.insertBefore(t,e.firstChild);case "beforeEnd":return e.appendChild(t);case "afterEnd":if(e.nextSibling){return e.parentNode.insertBefore(t,e.nextSibling);}else{return e.parentNode.appendChild(t);}}}return false;},fbInsEle:function(e,p,ne){if(_STNS.bIsIE){return e.insertAdjacentElement(p,ne);}else{switch(p){case "beforeBegin":return e.parentNode.insertBefore(ne,e);case "afterBegin":return e.insertBefore(ne,e.firstChild);case "beforeEnd":return e.appendChild(ne);case "afterEnd":if(o.nextSibling){return e.parentNode.insertBefore(ne,e.nextSibling);}else{return e.parentNode.appendChild(ne);}}}},fbDelEle:function(e){var p=e.parentNode;return p.removeChild(e);},fbInsJs:function(s,l){var l=l||"JavaScript";var hd=_STNS.faGetElesByTagName("HEAD");if(hd&&hd[0]){l=l.toLowerCase();var t=document.createElement("script");t.language=l;if(!l.indexOf("javascript")||!l.indexOf("jscript")){t.type="text/javascript";}t.src=s;_STNS.fbInsEle(hd,"beforeEnd",t);}},fdmCreateXMLHttp:function(){var _99;if(window.XMLHttpRequest){_99=new XMLHttpRequest();}else{var _9a=["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"];for(var n=0;n<_9a.length;n++){try{_99=new ActiveXObject(_9a[n]);break;}catch(e){_99=null;}}}if(!_99){_99=null;_STNS.fvThrow(new Error("Create XMLHttpRequest fail!"));return;}if(_99.readyState==null){_99.readyState=0;_99.addEventListener("load",function(){_99.readyState=4;if(typeof _99.onreadystatechange=="function"){_99.onreadystatechange();}},false);}return _99;},fdmCreateXMLDoc:function(){var _9c;if(_STNS.bIsIE){var _9d=["Msxml2.DOMDocument.4.0","Msxml2.DOMDocument.3.0","Msxml2.DOMDocument","Microsoft.XMLDOM"];for(var n=0;n<_9d.length;n++){try{_9c=new ActiveXObject(_9d[n]);break;}catch(e){}}}else{_9c=document.implementation.createDocument("","",null);}if(!_9c){_STNS.fvThrow(new Error("Create XMLDOMDocument fail!"));return;}return _9c;},faGetElePos:function(e){if(!e){return;}var x=y=bl=bt=0;if(_STNS.bIsSF&&_STNS.oNav.version>=523.12){var o=e.offsetParent.offsetParent.offsetParent.offsetParent;if(o&&o.tagName=="TABLE"){bl=parseInt(_STNS.fsGetEleStyle(o,"borderLeftWidth"));bt=parseInt(_STNS.fsGetEleStyle(o,"borderTopWidth"));if(!isNaN(bl)){x+=bl;}if(!isNaN(bt)){y+=bt;}}}while(e){x+=e.offsetLeft;y+=e.offsetTop;if((_STNS.oNav.name=="konqueror"||_STNS.oNav.name=="safari")&&e.style.position.toLowerCase()=="absolute"){break;}switch(e.tagName){case "TD":if(_STNS.bIsIE||_STNS.bIsOP&&_STNS.oNav.version<9){bl=parseInt(_STNS.fsGetEleStyle(e,"borderLeftWidth"));bt=parseInt(_STNS.fsGetEleStyle(e,"borderTopWidth"));if(!isNaN(bl)){x+=bl;}if(!isNaN(bt)){y+=bt;}}break;}if(e.parentNode&&e.parentNode.tagName=="DIV"){var s=_STNS.fsGetEleStyle(e.parentNode,"overflow").toLowerCase();var w=_STNS.fsGetEleStyle(e.parentNode,"width").toLowerCase();if(s=="hidden"||s=="scroll"||s=="auto"){x-=e.parentNode.scrollLeft;y-=e.parentNode.scrollTop;}if(w&&w!="auto"){if((_STNS.bIsFX&&_STNS.oNav.version>20060414&&s!="visible")||(_STNS.bIsIE&&_STNS.oNav.version>=5)){bl=parseInt(_STNS.fsGetEleStyle(e.parentNode,"borderLeftWidth"));bt=parseInt(_STNS.fsGetEleStyle(e.parentNode,"borderTopWidth"));if(!isNaN(bl)){x+=bl;}if(!isNaN(bt)){y+=bt;}}}}if(e.parentNode&&e.offsetParent&&e.parentNode!=e.offsetParent){if(e.offsetParent.tagName=="DIV"){var s=_STNS.fsGetEleStyle(e.offsetParent,"overflow").toLowerCase();var w=_STNS.fsGetEleStyle(e.offsetParent,"width").toLowerCase();if(s=="hidden"||s=="scroll"||s=="auto"){x-=e.offsetParent.scrollLeft;y-=e.offsetParent.scrollTop;}if(w&&w!="auto"){if((_STNS.bIsFX&&_STNS.oNav.version>20060414&&s!="visible")||(_STNS.bIsIE&&_STNS.oNav.version>=5)){bl=parseInt(_STNS.fsGetEleStyle(e.offsetParent,"borderLeftWidth"));bt=parseInt(_STNS.fsGetEleStyle(e.offsetParent,"borderTopWidth"));if(!isNaN(bl)){x+=bl;}if(!isNaN(bt)){y+=bt;}}}}}e=e.offsetParent;}return [x,y];},fiGetEleWid:function(e){return e.offsetWidth;},fiGetEleHei:function(e){return e.offsetHeight;},fsGetEleStyle:function(e,p){if(!e||!p){return;}if(_STNS.bIsIE){return e.currentStyle[p];}else{if(_STNS.bIsFX||_STNS.bIsSF||_STNS.bIsOP){var w=e.ownerDocument.defaultView;p=p.replace(/([A-Z])/g,"-$1");return w.getComputedStyle(e,"").getPropertyValue(p.toLowerCase());}else{return e.style[p];}}},fcoGetAttribute:function(e,a){if(!e||!a){return;}if(_STNS.bIsIE){return e[a];}else{return e.getAttribute(a);}},fbFalse:function(){return false;},fbTrue:function(){return true;}};_STNS.Class=(function(){var _ab=function(){var c=function(as){if(_STNS.bIsIE){this._cls=this.constructor;}else{this._cls=arguments.callee;}_ae.call(this,as);};_af(c,arguments);c.register=_b0;c.toString=_b1;c.subclsOf=_b2;c.superclassOf=_b3;return c;};_ab.toString=function(){return "[object Class]";};_ab.getC=function(pth){var _b5=[];if(!_b6(pth,_b5)||!_b7[_b5[0]][_b5[1]]){_STNS.fvThrow(new Error("Class get error: Class \""+pth+"\" is not found"));return;}return _b7[_b5[0]][_b5[1]];};_ab.getClsLst=function(o,pre){var o=o||_b7,pre=pre||"/",sp,s="";for(var i in o){if(typeof o[i]=="object"){sp=pre+i+"/";s+=_STNS.Class.getClsLst(o[i],sp);}else{s+=pre+i+"\n";}}return s;};var _b0=function(pth){var _be=[];if(!_b6(pth,_be)){_STNS.fvThrow(new Error("Class register error: Invalid class path:"+pth));return;}var pkg=_be[0];var cn=_be[1];if(pkg){if(!_b7[pkg]){_b7[pkg]={};}var _c1=_b7[pkg][cn];if(_c1){_STNS.fvThrow(new Error("Class register error: Class \""+pth+"\" already exists"));return;}_b7[pkg][cn]=this;}else{var _c1=_b7[cn];if(_c1){_STNS.fvThrow(new Error("Class register error: Class \""+pth+"\" already exists"));return;}_b7[cn]=this;}this._pkg=pkg;this._cn=cn;};var _b7={};var _c2=function(_c3,_c4){if(typeof _c3=="string"){_c3=_STNS.Class.getC(_c3);}if(typeof _c4=="string"){_c4=_STNS.Class.getC(_c4);}if(typeof _c3!="function"||typeof _c4!="function"){return false;}if(!_c3._supers){return false;}for(var i=0;i<_c3._supers.length;i++){if(_c3._supers[i]==_c4){return true;}else{if(_c2(_c3._supers[i],_c4)){return true;}}}return false;};var _b2=function(cls){return _c2(this,cls);};var _b3=function(cls){return _c2(cls,this);};var _b6=function(pth,_c9){if(typeof pth!="string"||!pth){return false;}var n=pth.lastIndexOf("/");if(n>-1){_c9[0]=pth.substr(0,n);_c9[1]=pth.substr(n+1);}else{_c9[0]="";_c9[1]=pth;}return true;};var _af=function(c,as){c._supers=[];for(var i=0;i<as.length;i++){var s=as[i];if(typeof s=="string"){s=_STNS.Class.getC(s);}if(typeof s!="function"){_STNS.fvThrow(new Error("Class create error: Invalid superclass: "+"args["+i+"]"));return;}c._supers.push(s);}};var _ae=function(as){var c=this._cls;for(var i=0;i<c._supers.length;i++){if(_STNS.bIsIE){this.constructor=c._supers[i];}c._supers[i].call(this,as);}if(_STNS.bIsIE){this.constructor=c;}this._cls=c;this.toString=_d2;this.getClass=_d3;this.instanceOf=_d4;this.toConvert=_d5;if(c.construct){c.construct.call(this,as);}};var _d5=function(cls,as){var c=this._cls;if(_c2(c,cls)){var t=new cls;for(var i in this){if(typeof t[i]=="undefined"){delete this[i];}if(cls[i]){this[i]=cls[i];}}}else{if(_c2(cls,c)){var f=0;for(var i=0;i<cls._supers.length;i++){if(_STNS.bIsIE){this.constructor=cls._supers[i];}if(cls._supers[i]!=c){cls._supers[i].call(this,as);}else{f=1;}}if(!f){_STNS.fvThrow(new Error("_STNS.runTime error:Can't convert this instance;The class of instance must be the target class's direct superClass!"));return;}if(_STNS.bIsIE){this.constructor=cls;}this._cls=cls;if(cls.construct){cls.construct.call(this,as);}}else{_STNS.fvThrow(new Error("_STNS.runTime error:Can't convert this instance;The class of instance must be the target class's subClass or direct superClass!"));}}};var _d4=function(c){if(typeof c=="string"){c=_STNS.Class.getC(c);}if(typeof c!=="function"){return false;}return this._cls==c;};var _d3=function(){return this._cls;};var _d2=function(){if(this._cls._cn){return "[object Object "+this._cls._pkg+"/"+this._cls._cn+"]";}else{return "[object Object Anonymous class]";}};var _b1=function(){if(this._cn){return "[object Class "+this._pkg+"/"+this._cn+"]";}return "[object Anonymous Class]";};return _ab;})();with(_STNS){sDocMd=fsGetDocMd();oNav=_foGetNav();bIsIE=oNav.name=="msie";bIsMIE=bIsIE&&oNav.platform=="Mac";bIsOP=oNav.name=="opera";bIsFX=oNav.name=="gecko";bIsSF=oNav.name=="safari";bIsKQ=oNav.name=="konqueror";sDIR=fsGetDIR(sURL);bLocal=!sURL.indexOf("file:");_fvInitOnload();fbAddLoad(_fvCkPg);}}_STNS.fvInitLib();_STNS.fvInc(_STNS.fsGetAbsPth(_STNS.sLibPth+"stcode.js"));_STNS.fvLoadLib();if(!_STNS.bShield){_STNS.fvCSSShield();}if(typeof _STNS!="undefined"&&!_STNS.EFFECT){_STNS.EFFECT={foGetEff:function(s,id,w,d,o){if(!s){return 0;}var t=s.toLowerCase(),c;if((!t.indexOf("progid:")||!t.indexOf("revealtrans"))&&_STNS.EFFECT["CEffIE"]){return new _STNS.EFFECT["CEffIE"]([s,id,w,d,o]);}else{if(!s.indexOf("stEffect")){s=s.substring(10,s.length-2);return stEffect(s,id,w,d,o);}else{return 0;}}}};with(_STNS.EFFECT){_STNS.EFFECT.CEffect=_STNS.Class();CEffect.register("EFFECT/CEffect");CEffect.construct=function(as){this._iStat=-1;this.sName=as[0];this.sDmId=as[1];this.dmWin=as[2]||window;with(_STNS.EFFECT.CEffect){this.fiGetStat=fiGetStat;this.fbSet=_STNS.fbFalse;this.fbDel=_STNS.fbFalse;this.fbApply=_STNS.fbFalse;this.fbPlay=_STNS.fbFalse;this.fbStop=_STNS.fbFalse;this.fbSetStyle=_STNS.fbFalse;}};CEffect.fiGetStat=function(){return this._iStat;};}function stEffect(n,id,w,dur,o){var cn="CEff"+n.charAt(0).toUpperCase()+n.substr(1);if(_STNS.EFFECT[cn]){return new _STNS.EFFECT[cn]([n,id,w,dur,o]);}}}


/*======================================================================*\
|| #################################################################### ||
|| # vBulletin 3.6.8
|| # ---------------------------------------------------------------- # ||
|| # Copyright ©2000-2007 Jelsoft Enterprises Ltd. All Rights Reserved. ||
|| # This file may not be redistributed in whole or significant part. # ||
|| # ---------------- VBULLETIN IS NOT FREE SOFTWARE ---------------- # ||
|| # http://www.vbulletin.com | http://www.vbulletin.com/license.html # ||
|| #################################################################### ||
\*======================================================================*/

/**
* Handle Firebug calls when Firebug is not available (getfirebug.com)
*/
if (!window.console || !console.firebug)
{
	window.console = {};
	var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
	for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {};
}

/**
* Handle YUI custom event calls when YUI is not available (clientscript/yui/yahoo-dom-event.js)
*/
if (typeof YAHOO == "undefined")
{
	function null_event() { this.fire = function() {}; this.subscribe = function() {}; };
}

/**
* Setup Variables
*
* @var	string	SESSIONURL - stores the session URL
* @var	array	vbphrase - stores text phrases
* @var	array	vB_Editor - array of vB_Text_Editor objects
* @var	boolean	ignorequotechars - ignore characters inside [quote] tags for message length check
* @var	integer	pagenavcounter - counts the number of pagenav instances encountered so far
* @var	boolean	is_regexp - does window.regExp exist? - Catch errors with less capable browsers
* @var	boolean	AJAX_Compatible - does the current browser support AJAX?
* @var	string	pointer_cursor - help out old versions of IE that don't understand style.cursor = pointer
*/
var SESSIONURL       = (typeof(SESSIONURL) == "undefined" ? "" : SESSIONURL);
var vbphrase         = (typeof(vbphrase) == "undefined" ? new Array() : vbphrase);
var vB_Editor        = new Array();
var ignorequotechars = false;
var pagenavcounter   = 0;
var is_regexp        = (window.RegExp) ? true : false;
var AJAX_Compatible  = false;
var pointer_cursor   = (is_ie ? 'hand' : 'pointer');

/**
* Define the browser loading the page
*
* @var	string	userAgent Useragent string
* @var	boolean	is_opera  Opera
* @var	boolean	is_saf    Safari
* @var	boolean	is_webtv  WebTV
* @var	boolean	is_ie     Internet Explorer
* @var	boolean	is_ie4    Internet Explorer 4
* @var	boolean	is_ie7    Internet Explorer 7
* @var	boolean	is_ps3    Playstation 3
* @var	boolean	is_moz    Mozilla / Firefox / Camino
* @var	boolean	is_kon    Konqueror
* @var	boolean	is_ns     Netscape
* @var	boolean	is_ns4    Netscape 4
* @var	boolean	is_mac    Client is running MacOS
*/
var userAgent = navigator.userAgent.toLowerCase();
var is_opera  = ((userAgent.indexOf('opera') != -1) || (typeof(window.opera) != 'undefined'));
var is_saf    = ((userAgent.indexOf('applewebkit') != -1) || (navigator.vendor == 'Apple Computer, Inc.'));
var is_webtv  = (userAgent.indexOf('webtv') != -1);
var is_ie     = ((userAgent.indexOf('msie') != -1) && (!is_opera) && (!is_saf) && (!is_webtv));
var is_ie4    = ((is_ie) && (userAgent.indexOf('msie 4.') != -1));
var is_ie7    = ((is_ie) && (userAgent.indexOf('msie 7.') != -1));
var is_ps3    = (userAgent.indexOf('playstation 3') != -1);
var is_moz    = ((navigator.product == 'Gecko') && (!is_saf));
var is_kon    = (userAgent.indexOf('konqueror') != -1);
var is_ns     = ((userAgent.indexOf('compatible') == -1) && (userAgent.indexOf('mozilla') != -1) && (!is_opera) && (!is_webtv) && (!is_saf));
var is_ns4    = ((is_ns) && (parseInt(navigator.appVersion) == 4));
var is_mac    = (userAgent.indexOf('mac') != -1);

/**
* Workaround for heinous IE bug - add special vBlength property to all strings
* This method is applied to ALL string objects automatically
*
* @return	integer
*/
String.prototype.vBlength = function()
{
	return (is_ie && this.indexOf("\n") != -1) ? this.replace(/\r?\n/g, "_").length : this.length;
}

/**
* Overrides IE's original String.prototype.substr to accept negative values
*
* @param	integer	Substring start position
* @param	integer	Substring length
*
* @return	string
*/
if ("1234".substr(-2, 2) == "12") // (which would be incorrect)
{
	String.prototype.substr_orig = String.prototype.substr;

	String.prototype.substr = function(start, length)
	{
		if (typeof(length) == "undefined")
		{
			return this.substr_orig((start < 0 ? this.length + start : start));
		}
		else
		{
			return this.substr_orig((start < 0 ? this.length + start : start), length);
		}
	};
}

/**
* Define Array.shift() for browsers that don't have it
*/
if (typeof Array.prototype.shift === 'undefined')
{
	Array.prototype.shift = function()
	{
		for(var i = 0, b = this[0], l = this.length-1; i < l; i++)
		{
			this[i] = this[i + 1];
		}
		this.length--;
		return b;
	};
}

/**
* Function to emulate document.getElementById
*
* @param	string	Object ID
*
* @return	mixed	null if not found, object if found
*/
function fetch_object(idname)
{
	if (document.getElementById)
	{
		return document.getElementById(idname);
	}
	else if (document.all)
	{
		return document.all[idname];
	}
	else if (document.layers)
	{
		return document.layers[idname];
	}
	else
	{
		return null;
	}
}

/**
* Function to emulate document.getElementsByTagName
*
* @param	object	Parent object (eg: document)
* @param	string	Tag type (eg: 'td')
*
* @return	array
*/
function fetch_tags(parentobj, tag)
{
	if (parentobj == null)
	{
		return new Array();
	}
	else if (typeof parentobj.getElementsByTagName != 'undefined')
	{
		return parentobj.getElementsByTagName(tag);
	}
	else if (parentobj.all && parentobj.all.tags)
	{
		return parentobj.all.tags(tag);
	}
	else
	{
		return new Array();
	}
}

/**
* Function to count the number of tags in an object
*
* @param	object	Parent object (eg: document)
* @param	string	Tag type (eg: 'td')
*
* @return	integer
*/
function fetch_tag_count(parentobj, tag)
{
	return fetch_tags(parentobj, tag).length;
}

// #############################################################################
// Event handlers

/**
* Handles the different event models of different browsers and prevents event bubbling
*
* @param	event	Event object
*
* @return	event
*/
function do_an_e(eventobj)
{
	if (!eventobj || is_ie)
	{
		window.event.returnValue = false;
		window.event.cancelBubble = true;
		return window.event;
	}
	else
	{
		eventobj.stopPropagation();
		eventobj.preventDefault();
		return eventobj;
	}
}

/**
* Handles the different event models of different browsers and prevents event bubbling in a lesser way than do_an_e()
*
* @param	event	Event object
*
* @return	event
*/
function e_by_gum(eventobj)
{
	if (!eventobj || is_ie)
	{
		window.event.cancelBubble = true;
		return window.event;
	}
	else
	{
		if (eventobj.target.type == 'submit')
		{
			// naughty safari
			eventobj.target.form.submit();
		}
		eventobj.stopPropagation();
		return eventobj;
	}
}

// #############################################################################
// Message manipulation and validation

/**
* Checks that a message is valid for submission to PHP
*
* @param	string	Message text
* @param	mixed	Either subject text (if you want to make sure it exists) or 0 if you don't care
* @param	integer	Minimum acceptable character limit for the message
*
* @return	boolean
*/
function validatemessage(messagetext, subjecttext, minchars)
{
	if (is_kon || is_saf || is_webtv)
	{
		// ignore less-than-capable browsers
		return true;
	}
	else if (subjecttext.length < 1)
	{
		// subject not specified
		alert(vbphrase['must_enter_subject']);
		return false;
	}
	else
	{
		var stripped = PHP.trim(stripcode(messagetext, false, ignorequotechars));

		if (stripped.length < minchars)
		{
			// minimum message length not met
			alert(construct_phrase(vbphrase['message_too_short'], minchars));
			return false;
		}
		else if (typeof(document.forms.vbform) != 'undefined' && typeof(document.forms.vbform.imagestamp) != 'undefined')
		{
			// This form has image verification enabled
			document.forms.vbform.imagestamp.failed = false;

			if (document.forms.vbform.imagestamp.value.length != 6)
			{
				alert(vbphrase['complete_image_verification']);
				document.forms.vbform.imagestamp.failed = true;
				document.forms.vbform.imagestamp.focus();
				return false;
			}
			else
			{
				return true;
			}
		}
		else
		{
			// everything seems ok
			return true;
		}
	}
}


/**
* Strips quotes and bbcode tags from text
*
* @param	string	Text to manipulate
* @param	boolean	If true, strip <x> otherwise strip [x]
* @param	boolean	If true, strip all [quote]...contents...[/quote]
*
* @return	string
*/
function stripcode(str, ishtml, stripquotes)
{
	if (!is_regexp)
	{
		return str;
	}

	if (stripquotes)
	{
		var start_time = new Date().getTime();

		while ((startindex = PHP.stripos(str, '[quote')) !== false)
		{
			if (new Date().getTime() - start_time > 2000)
			{
				// while loop has been running for over 2 seconds and has probably gone infinite
				break;
			}

			if ((stopindex = PHP.stripos(str, '[/quote]')) !== false)
			{
				fragment = str.substr(startindex, stopindex - startindex + 8);
				str = str.replace(fragment, '');
			}
			else
			{
				break;
			}
			str = PHP.trim(str);
		}
	}

	if (ishtml)
	{
		// exempt image tags -- they need to count as characters in the string
		// as the do as BB codes
		str = str.replace(/<img[^>]+src="([^"]+)"[^>]*>/gi, '$1');

		var html1 = new RegExp("<(\\w+)[^>]*>", 'gi');
		var html2 = new RegExp("<\\/\\w+>", 'gi');

		str = str.replace(html1, '');
		str = str.replace(html2, '');

		var html3 = new RegExp('(&nbsp;)', 'gi');
		str = str.replace(html3, ' ');
	}
	else
	{
		var bbcode1 = new RegExp("\\[(\\w+)(=[^\\]]*)?\\]", 'gi');
		var bbcode2 = new RegExp("\\[\\/(\\w+)\\]", 'gi');

		str = str.replace(bbcode1, '');
		str = str.replace(bbcode2, '');
	}

	return str;
}

// #############################################################################
// vB_PHP_Emulator class
// #############################################################################

/**
* PHP Function Emulator Class
*/
function vB_PHP_Emulator()
{
}

// =============================================================================
// vB_PHP_Emulator Methods

/**
* Find a string within a string (case insensitive)
*
* @param	string	Haystack
* @param	string	Needle
* @param	integer	Offset
*
* @return	mixed	Not found: false / Found: integer position
*/
vB_PHP_Emulator.prototype.stripos = function(haystack, needle, offset)
{
	if (typeof offset == 'undefined')
	{
		offset = 0;
	}

	index = haystack.toLowerCase().indexOf(needle.toLowerCase(), offset);

	return (index == -1 ? false : index);
}

/**
* Trims leading whitespace
*
* @param	string	String to trim
*
* @return	string
*/
vB_PHP_Emulator.prototype.ltrim = function(str)
{
	return str.replace(/^\s+/g, '');
}

/**
* Trims trailing whitespace
*
* @param	string	String to trim
*
* @return	string
*/
vB_PHP_Emulator.prototype.rtrim = function(str)
{
	return str.replace(/(\s+)$/g, '');
}

/**
* Trims leading and trailing whitespace
*
* @param	string	String to trim
*
* @return	string
*/
vB_PHP_Emulator.prototype.trim = function(str)
{
	return this.ltrim(this.rtrim(str));
}

/**
* Emulation of PHP's preg_quote()
*
* @param	string	String to process
*
* @return	string
*/
vB_PHP_Emulator.prototype.preg_quote = function(str)
{
	// replace + { } ( ) [ ] | / ? ^ $ \ . = ! < > : * with backslash+character
	return str.replace(/(\+|\{|\}|\(|\)|\[|\]|\||\/|\?|\^|\$|\\|\.|\=|\!|\<|\>|\:|\*)/g, "\\$1");
}

/**
* Emulates PHP's preg_match_all()... sort of
*
* @param	string	Haystack
* @param	string	Regular expression - to be inserted into RegExp(x)
*
* @return	mixed	Array on match, false on no match
*/
vB_PHP_Emulator.prototype.match_all = function(string, regex)
{
	var gmatch = string.match(RegExp(regex, "gim"));
	if (gmatch)
	{
		var matches = new Array();

		var iregex = new RegExp(regex, "im");
		for (var i = 0; i < gmatch.length; i++)
		{
			matches[matches.length] = gmatch[i].match(iregex);
		}

		return matches;
	}
	else
	{
		return false;
	}
}

/**
* Emulates unhtmlspecialchars in vBulletin
*
* @param	string	String to process
*
* @return	string
*/
vB_PHP_Emulator.prototype.unhtmlspecialchars = function(str)
{
	f = new Array(/&lt;/g, /&gt;/g, /&quot;/g, /&amp;/g);
	r = new Array('<', '>', '"', '&');

	for (var i in f)
	{
		str = str.replace(f[i], r[i]);
	}

	return str;
}

/**
* Unescape CDATA from vB_AJAX_XML_Builder PHP class
*
* @param	string	Escaped CDATA
*
* @return	string
*/
vB_PHP_Emulator.prototype.unescape_cdata = function(str)
{
	var r1 = /<\=\!\=\[\=C\=D\=A\=T\=A\=\[/g;
	var r2 = /\]\=\]\=>/g;

	return str.replace(r1, '<![CDATA[').replace(r2, ']]>');
}

/**
* Emulates PHP's htmlspecialchars()
*
* @param	string	String to process
*
* @return	string
*/
vB_PHP_Emulator.prototype.htmlspecialchars = function(str)
{
	//var f = new Array(/&(?!#[0-9]+;)/g, /</g, />/g, /"/g);
	var f = new Array(
		(is_mac && is_ie ? new RegExp('&', 'g') : new RegExp('&(?!#[0-9]+;)', 'g')),
		new RegExp('<', 'g'),
		new RegExp('>', 'g'),
		new RegExp('"', 'g')
	);
	var r = new Array(
		'&amp;',
		'&lt;',
		'&gt;',
		'&quot;'
	);

	for (var i = 0; i < f.length; i++)
	{
		str = str.replace(f[i], r[i]);
	}

	return str;
}

/**
* Searches an array for a value
*
* @param	string	Needle
* @param	array	Haystack
* @param	boolean	Case insensitive
*
* @return	integer	Not found: -1 / Found: integer index
*/
vB_PHP_Emulator.prototype.in_array = function(ineedle, haystack, caseinsensitive)
{
	var needle = new String(ineedle);

	if (caseinsensitive)
	{
		needle = needle.toLowerCase();
		for (var i in haystack)
		{
			if (haystack[i].toLowerCase() == needle)
			{
				return i;
			}
		}
	}
	else
	{
		for (var i in haystack)
		{
			if (haystack[i] == needle)
			{
				return i;
			}
		}
	}
	return -1;
}

/**
* Emulates PHP's strpad()
*
* @param	string	Text to pad
* @param	integer	Length to pad
* @param	string	String with which to pad
*
* @return	string
*/
vB_PHP_Emulator.prototype.str_pad = function(text, length, padstring)
{
	text = new String(text);
	padstring = new String(padstring);

	if (text.length < length)
	{
		padtext = new String(padstring);

		while (padtext.length < (length - text.length))
		{
			padtext += padstring;
		}

		text = padtext.substr(0, (length - text.length)) + text;
	}

	return text;
}

/**
* A sort of emulation of PHP's urlencode - not 100% the same, but accomplishes the same thing
*
* @param	string	String to encode
*
* @return	string
*/
vB_PHP_Emulator.prototype.urlencode = function(text)
{
	text = escape(text.toString()).replace(/\+/g, "%2B");

	// this escapes 128 - 255, as JS uses the unicode code points for them.
	// This causes problems with submitting text via AJAX with the UTF-8 charset.
	var matches = text.match(/(%([0-9A-F]{2}))/gi);
	if (matches)
	{
		for (var matchid = 0; matchid < matches.length; matchid++)
		{
			var code = matches[matchid].substring(1,3);
			if (parseInt(code, 16) >= 128)
			{
				text = text.replace(matches[matchid], '%u00' + code);
			}
		}
	}

	// %25 gets translated to % by PHP, so if you have %25u1234,
	// we see it as %u1234 and it gets translated. So make it %u0025u1234,
	// which will print as %u1234!
	text = text.replace('%25', '%u0025');

	return text;
}

/**
* Works a bit like ucfirst, but with some extra options
*
* @param	string	String with which to work
* @param	string	Cut off string before first occurence of this string
*
* @return	string
*/
vB_PHP_Emulator.prototype.ucfirst = function(str, cutoff)
{
	if (typeof cutoff != 'undefined')
	{
		var cutpos = str.indexOf(cutoff);
		if (cutpos > 0)
		{
			str = str.substr(0, cutpos);
		}
	}

	str = str.split(' ');
	for (var i = 0; i < str.length; i++)
	{
		str[i] = str[i].substr(0, 1).toUpperCase() + str[i].substr(1);
	}
	return str.join(' ');
}

// #############################################################################
// vB_AJAX_Handler
// #############################################################################

/**
* XML Sender Class
*
* @param	boolean	Should connections be asyncronous?
*/
function vB_AJAX_Handler(async)
{
	/**
	* Should connections be asynchronous?
	*
	* @var	boolean
	*/
	this.async = async ? true : false;
}

// =============================================================================
// vB_AJAX_Handler methods

/**
* Initializes the XML handler
*
* @return	boolean	True if handler created OK
*/
vB_AJAX_Handler.prototype.init = function()
{
	if (typeof vb_disable_ajax != 'undefined' && vb_disable_ajax == 2)
	{
		// disable all ajax features
		return false;
	}

	if (typeof XMLHttpRequest != "undefined")
	{
		this.handler = new XMLHttpRequest();
		return (this.handler.setRequestHeader ? true : false);
	}
	else if (is_ie && !is_ie7)
	{
		this.handler = eval("new A" + "ctiv" + "eX" + "Ob" + "ject('Micr" + "osoft.XM" + "LHTTP');");
		return true;
	}
	else
	{
		return false;
	}
}

/**
* Detects if the browser is fully compatible
*
* @return	boolean
*/
vB_AJAX_Handler.prototype.is_compatible = function()
{
	if (typeof vb_disable_ajax != 'undefined' && vb_disable_ajax == 2)
	{
		// disable all ajax features
		return false;
	}

	if (is_ie && !is_ie4) { return true; }
	else if (typeof XMLHttpRequest != 'undefined')
	{
		try { return XMLHttpRequest.prototype.setRequestHeader ? true : false; }
		catch(e)
		{
			try { var tester = new XMLHttpRequest(); return tester.setRequestHeader ? true : false; }
			catch(e) { return false; }
		}
	}
	else { return false; }
}

/**
* Checks if the system is ready
*
* @return	boolean	False if ready
*/
vB_AJAX_Handler.prototype.not_ready = function()
{
	return (this.handler.readyState && (this.handler.readyState < 4));
}

/**
* OnReadyStateChange event handler
*
* @param	function
*/
vB_AJAX_Handler.prototype.onreadystatechange = function(event)
{
	if (!this.handler)
	{
		if  (!this.init())
		{
			return false;
		}
	}
	if (typeof event == 'function')
	{
		this.handler.onreadystatechange = event;
	}
	else
	{
		alert('XML Sender OnReadyState event is not a function');
	}

	return false;
}

/**
* Sends data
*
* @param	string	Destination URL
* @param	string	Request Data
*
* @return	mixed	Return message
*/
vB_AJAX_Handler.prototype.send = function(desturl, datastream)
{
	if (!this.handler)
	{
		if (!this.init())
		{
			return false;
		}
	}
	if (!this.not_ready())
	{
		this.handler.open('POST', desturl, this.async);
		this.handler.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		this.handler.send(datastream + '&s=' + fetch_sessionhash());

		if (!this.async && this.handler.readyState == 4 && this.handler.status == 200)
		{
			return true;
		}
	}
	return false;
}

/**
* Fetches the contents of an XML node
*
* @param	object	XML node
*
* @return	string	XML node contents
*/
vB_AJAX_Handler.prototype.fetch_data = function(xml_node)
{
	if (xml_node && xml_node.firstChild && xml_node.firstChild.nodeValue)
	{
		return PHP.unescape_cdata(xml_node.firstChild.nodeValue);
	}
	else
	{
		return '';
	}
}

// we can check this variable to see if browser is AJAX compatible
AJAX_Compatible = vB_AJAX_Handler.prototype.is_compatible();
console.info("Browser is%s AJAX compatible", AJAX_Compatible ? "" : " NOT");

// #############################################################################
// vB_Hidden_Form
// #############################################################################

/**
* Form Generator Class
*
* Builds a form filled with hidden fields for invisible submit via POST
*
* @param	string	Script (my_target_script.php)
*/
function vB_Hidden_Form(script)
{
	this.action = script;
	this.variables = new Array();
}

// =============================================================================
// vB_Hidden_Form methods

/**
* Adds a hidden input field to the form object
*
* @param	string	Name attribute
* @param	string	Value attribute
*/
vB_Hidden_Form.prototype.add_variable = function(name, value)
{
	this.variables[this.variables.length] = new Array(name, value);
	console.log("vB_Hidden_Form :: add_variable(%s)", name);
};

/**
* Fetches all form elements inside an HTML element and performs 'add_input()' on them
*
* @param	object	HTML element to search
*/
vB_Hidden_Form.prototype.add_variables_from_object = function(obj)
{
	if (!obj)
	{
		return;
	}
	console.info("vB_Hidden_Form :: add_variables_from_object(%s)", obj.id);
	var inputs = fetch_tags(obj, 'input');
	for (var i = 0; i < inputs.length; i++)
	{
		switch (inputs[i].type)
		{
			case 'checkbox':
			case 'radio':
				if (inputs[i].checked)
				{
					this.add_variable(inputs[i].name, inputs[i].value);
				}
				break;
			case 'text':
			case 'hidden':
			case 'password':
				this.add_variable(inputs[i].name, inputs[i].value);
				break;
			default:
				continue;
		}
	}

	var textareas = fetch_tags(obj, 'textarea');
	for (var i = 0; i < textareas.length; i++)
	{
		this.add_variable(textareas[i].name, textareas[i].value);
	}

	var selects = fetch_tags(obj, 'select');
	for (var i = 0; i < selects.length; i++)
	{
		if (selects[i].multiple)
		{
			for (var j = 0; j < selects[i].options.length; j++)
			{
				if (selects[i].options[j].selected)
				{
					this.add_variable(selects[i].name, selects[i].options[j].value);
				}
			}
		}
		else
		{
			this.add_variable(selects[i].name, selects[i].options[selects[i].selectedIndex].value);
		}
	}
};

/**
* Fetches a variable value
*
* @param	string	Variable name
*
* @return	mixed	Variable value
*/
vB_Hidden_Form.prototype.fetch_variable = function(varname)
{
	for (var i = 0; i < this.variables.length; i++)
	{
		if (this.variables[i][0] == varname)
		{
			return this.variables[i][1];
		}
	}

	return null;
};

/**
* Submits the hidden form object
*/
vB_Hidden_Form.prototype.submit_form = function()
{
	this.form = document.createElement('form');
	this.form.method = 'post';
	this.form.action = this.action;

	for (var i = 0; i < this.variables.length; i++)
	{
		var inputobj = document.createElement('input');

		inputobj.type  = 'hidden';
		inputobj.name  = this.variables[i][0];
		inputobj.value = this.variables[i][1];

		this.form.appendChild(inputobj);
	}

	console.info("vB_Hidden_Form :: submit_form() -> %s", this.action);
	document.body.appendChild(this.form).submit();
};

/**
* Builds a URI query string from the given variables
*/
vB_Hidden_Form.prototype.build_query_string = function()
{
	var query_string = '';

	for (var i = 0; i < this.variables.length; i++)
	{
		query_string += this.variables[i][0] + '=' + PHP.urlencode(this.variables[i][1]) + '&';
	}

	console.info("vB_Hidden_Form :: Query String = %s", query_string);
	return query_string;
}

/**
* Legacy functions for backward compatability
*/
vB_Hidden_Form.prototype.add_input = vB_Hidden_Form.prototype.add_variable;
vB_Hidden_Form.prototype.add_inputs_from_object = vB_Hidden_Form.prototype.add_variables_from_object;

// #############################################################################
// Window openers and instant messenger wrappers

/**
* Opens a generic browser window
*
* @param	string	URL
* @param	integer	Width
* @param	integer	Height
* @param	string	Optional Window ID
*/
function openWindow(url, width, height, windowid)
{
	return window.open(
		url,
		(typeof windowid == 'undefined' ? 'vBPopup' : windowid),
		'statusbar=no,menubar=no,toolbar=no,scrollbars=yes,resizable=yes'
		+ (typeof width != 'undefined' ? (',width=' + width) : '') + (typeof height != 'undefined' ? (',height=' + height) : '')
	);
}

/**
* Opens control panel help window
*
* @param	string	Script name
* @param	string	Action type
* @param	string	Option value
*
* @return	window
*/
function js_open_help(scriptname, actiontype, optionval)
{
	return openWindow(
		'help.php?s=' + SESSIONHASH + '&do=answer&page=' + scriptname + '&pageaction=' + actiontype + '&option=' + optionval,
		600, 450, 'helpwindow'
	);
}

/**
* Opens a window to show a list of attachments in a thread (misc.php?do=showattachments)
*
* @param	integer	Thread ID
*
* @return	window
*/
function attachments(threadid)
{
	return openWindow(
		'misc.php?' + SESSIONURL + 'do=showattachments&t=' + threadid,
		480, 300
	);
}

/**
* Opens a window to show a list of posters in a thread (misc.php?do=whoposted)
*
* @param	integer	Thread ID
*
* @return	window
*/
function who(threadid)
{
	return openWindow(
		'misc.php?' + SESSIONURL + 'do=whoposted&t=' + threadid,
		230, 300
	);
}

/**
* Opens an IM Window
*
* @param	string	IM type
* @param	integer	User ID
* @param	integer	Width of window
* @param	integer	Height of window
*
* @return	window
*/
function imwindow(imtype, userid, width, height)
{
	return openWindow(
		'sendmessage.php?' + SESSIONURL + 'do=im&type=' + imtype + '&u=' + userid,
		width, height
	);
}

/**
* Sends an MSN message
*
* @param	string	Target MSN handle
*
* @return	boolean	false
*/
function SendMSNMessage(name)
{
	if (!is_ie)
	{
		alert(vbphrase['msn_functions_only_work_in_ie']);
		return false;
	}
	else
	{
		MsgrObj.InstantMessage(name);
		return false;
	}
}

/**
* Adds an MSN Contact (requires MSN)
*
* @param	string	MSN handle
*
* @return	boolean	false
*/
function AddMSNContact(name)
{
	if (!is_ie)
	{
		alert(vbphrase['msn_functions_only_work_in_ie']);
		return false;
	}
	else
	{
		MsgrObj.AddContact(0, name);
		return false;
	}
}

/**
* Detects Caps-Lock when a key is pressed
*
* @param	event
*
* @return	boolean	True if Caps-Lock is on
*/
function detect_caps_lock(e)
{
	e = (e ? e : window.event);

	var keycode = (e.which ? e.which : (e.keyCode ? e.keyCode : (e.charCode ? e.charCode : 0)));
	var shifted = (e.shiftKey || (e.modifiers && (e.modifiers & 4)));
	var ctrled = (e.ctrlKey || (e.modifiers && (e.modifiers & 2)));

	// if characters are uppercase without shift, or lowercase with shift, caps-lock is on.
	return (keycode >= 65 && keycode <= 90 && !shifted && !ctrled) || (keycode >= 97 && keycode <= 122 && shifted);
}

/**
* Confirms log-out request
*
* @param	string	Log-out confirmation message
*
* @return	boolean
*/
function log_out(confirmation_message)
{
	var ht = document.getElementsByTagName("html")[0];
	ht.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)";
	if (confirm(confirmation_message))
	{
		return true;
	}
	else
	{
		ht.style.filter = "";
		return false;
	}
}

// #############################################################################
// Cookie handlers

/**
* Sets a cookie
*
* @param	string	Cookie name
* @param	string	Cookie value
* @param	date	Cookie expiry date
*/
function set_cookie(name, value, expires)
{
	console.log("Set Cookie :: %s = '%s'", name, value);
	document.cookie = name + '=' + escape(value) + '; path=/' + (typeof expires != 'undefined' ? '; expires=' + expires.toGMTString() : '');
}

/**
* Deletes a cookie
*
* @param	string	Cookie name
*/
function delete_cookie(name)
{
	console.log("Delete Cookie :: %s", name);
	document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT' +  '; path=/';
}

/**
* Fetches the value of a cookie
*
* @param	string	Cookie name
*
* @return	string
*/
function fetch_cookie(name)
{
	cookie_name = name + '=';
	cookie_length = document.cookie.length;
	cookie_begin = 0;
	while (cookie_begin < cookie_length)
	{
		value_begin = cookie_begin + cookie_name.length;
		if (document.cookie.substring(cookie_begin, value_begin) == cookie_name)
		{
			var value_end = document.cookie.indexOf (';', value_begin);
			if (value_end == -1)
			{
				value_end = cookie_length;
			}
			var cookie_value = unescape(document.cookie.substring(value_begin, value_end));
			console.log("Fetch Cookie :: %s = '%s'", name, cookie_value);
			return cookie_value;
		}
		cookie_begin = document.cookie.indexOf(' ', cookie_begin) + 1;
		if (cookie_begin == 0)
		{
			break;
		}
	}
	console.log("Fetch Cookie :: %s (null)", name);
	return null;
}

// #############################################################################
// Form element managers (used for 'check all' type systems)

/**
* Sets all checkboxes, radio buttons or selects in a given form to a given state, with exceptions
*
* @param	object	Form object
* @param	string	Target element type (one of 'radio', 'select-one', 'checkbox')
* @param	string	Selected option in case of 'radio'
* @param	array	Array of element names to be excluded
* @param	mixed	Value to give to found elements
*/
function js_toggle_all(formobj, formtype, option, exclude, setto)
{
	for (var i =0; i < formobj.elements.length; i++)
	{
		var elm = formobj.elements[i];
		if (elm.type == formtype && PHP.in_array(elm.name, exclude, false) == -1)
		{
			switch (formtype)
			{
				case 'radio':
					if (elm.value == option) // option == '' evaluates true when option = 0
					{
						elm.checked = setto;
					}
				break;
				case 'select-one':
					elm.selectedIndex = setto;
				break;
				default:
					elm.checked = setto;
				break;
			}
		}
	}
}

/**
* Sets all <select> elements to the selectedIndex specified by the 'selectall' element
*
* @param	object	Form object
*/
function js_select_all(formobj)
{
	exclude = new Array();
	exclude[0] = 'selectall';
	js_toggle_all(formobj, 'select-one', '', exclude, formobj.selectall.selectedIndex);
}

/**
* Sets all <input type="checkbox" /> elements to have the same checked status as 'allbox'
*
* @param	object	Form object
*/
function js_check_all(formobj)
{
	exclude = new Array();
	exclude[0] = 'keepattachments';
	exclude[1] = 'allbox';
	exclude[2] = 'removeall';
	js_toggle_all(formobj, 'checkbox', '', exclude, formobj.allbox.checked);
}

/**
* Sets all <input type="radio" /> groups to have a particular option checked
*
* @param	object	Form object
* @param	mixed	Selected option
*/
function js_check_all_option(formobj, option)
{
	exclude = new Array();
	exclude[0] = 'useusergroup';
	js_toggle_all(formobj, 'radio', option, exclude, true);
}

/**
* Alias to js_check_all
*/
function checkall(formobj)
{
	js_check_all(formobj);
}

/**
* Alias to js_check_all_option
*/
function checkall_option(formobj, option)
{
	js_check_all_option(formobj, option);
}

/**
* Resize function for CP textareas
*
* @param	integer	If positive, size up, otherwise size down
* @param	string	ID of the textarea
*
* @return	boolean	false
*/
function resize_textarea(to, id)
{
	if (to < 0)
	{
		var rows = -5;
		var cols = -10;
	}
	else
	{
		var rows = 5;
		var cols = 10;
	}

	var textarea = fetch_object(id);
	if (typeof textarea.orig_rows == 'undefined')
	{
		textarea.orig_rows = textarea.rows;
		textarea.orig_cols = textarea.cols;
	}

	var newrows = textarea.rows + rows;
	var newcols = textarea.cols + cols;

	if (newrows >= textarea.orig_rows && newcols >= textarea.orig_cols)
	{
		textarea.rows = newrows;
		textarea.cols = newcols;
	}

	return false;
}

// #############################################################################
// Collapsible element handlers

/**
* Toggles the collapse state of an object, and saves state to 'vbulletin_collapse' cookie
*
* @param	string	Unique ID for the collapse group
*
* @return	boolean	false
*/
function toggle_collapse(objid)
{
	if (!is_regexp)
	{
		return false;
	}

	obj = fetch_object('collapseobj_' + objid);
	img = fetch_object('collapseimg_' + objid);
	cel = fetch_object('collapsecel_' + objid);

	if (!obj)
	{
		// nothing to collapse!
		if (img)
		{
			// hide the clicky image if there is one
			img.style.display = 'none';
		}
		return false;
	}

	if (obj.style.display == 'none')
	{
		obj.style.display = '';
		save_collapsed(objid, false);
		if (img)
		{
			img_re = new RegExp("_collapsed\\.gif$");
			img.src = img.src.replace(img_re, '.gif');
		}
		if (cel)
		{
			cel_re = new RegExp("^(thead|tcat)(_collapsed)$");
			cel.className = cel.className.replace(cel_re, '$1');
		}
	}
	else
	{
		obj.style.display = 'none';
		save_collapsed(objid, true);
		if (img)
		{
			img_re = new RegExp("\\.gif$");
			img.src = img.src.replace(img_re, '_collapsed.gif');
		}
		if (cel)
		{
			cel_re = new RegExp("^(thead|tcat)$");
			cel.className = cel.className.replace(cel_re, '$1_collapsed');
		}
	}
	return false;
}

/**
* Updates vbulletin_collapse cookie with collapse preferences
*
* @param	string	Unique ID for the collapse group
* @param	boolean	Add a cookie
*/
function save_collapsed(objid, addcollapsed)
{
	var collapsed = fetch_cookie('vbulletin_collapse');
	var tmp = new Array();

	if (collapsed != null)
	{
		collapsed = collapsed.split('\n');

		for (var i in collapsed)
		{
			if (collapsed[i] != objid && collapsed[i] != '')
			{
				tmp[tmp.length] = collapsed[i];
			}
		}
	}

	if (addcollapsed)
	{
		tmp[tmp.length] = objid;
	}

	expires = new Date();
	expires.setTime(expires.getTime() + (1000 * 86400 * 365));
	set_cookie('vbulletin_collapse', tmp.join('\n'), expires);
}

// #############################################################################
// Event Handlers for PageNav menus

/**
* Class to handle pagenav events
*/
function vBpagenav()
{
}

/**
* Handles clicks on pagenav menu control objects
*/
vBpagenav.prototype.controlobj_onclick = function(e)
{
	this._onclick(e);
	var inputs = fetch_tags(this.menu.menuobj, 'input');
	for (var i = 0; i < inputs.length; i++)
	{
		if (inputs[i].type == 'text')
		{
			inputs[i].focus();
			break;
		}
	}
};

/**
* Submits the pagenav form... sort of
*/
vBpagenav.prototype.form_gotopage = function(e)
{
	if ((pagenum = parseInt(fetch_object('pagenav_itxt').value, 10)) > 0)
	{
		window.location = this.addr + '&page=' + pagenum;
	}
	return false;
};

/**
* Handles clicks on the 'Go' button in pagenav popups
*/
vBpagenav.prototype.ibtn_onclick = function(e)
{
	return this.form.gotopage();
};

/**
* Handles keypresses in the text input of pagenav popups
*/
vBpagenav.prototype.itxt_onkeypress = function(e)
{
	return ((e ? e : window.event).keyCode == 13 ? this.form.gotopage() : true);
};

// #############################################################################
// DHTML Popup Menu Handling (complements vbulletin_menu.js)

/**
* Wrapper for vBmenu.register
*
* @param	string	Control ID
* @param	boolean	No image (true)
* @param	boolean	Does nothing any more
*/
function vbmenu_register(controlid, noimage, datefield)
{
	if (typeof(vBmenu) == "object")
	{
		return vBmenu.register(controlid, noimage);
	}
	else
	{
		return false;
	}
}

// #############################################################################
// Stuff that really doesn't fit anywhere else

/**
* Sets an element and all its children to be 'unselectable'
*
* @param	object	Object to be made unselectable
*/
function set_unselectable(obj)
{
	if (!is_ie4 && typeof obj.tagName != 'undefined')
	{
		if (obj.hasChildNodes())
		{
			for (var i = 0; i < obj.childNodes.length; i++)
			{
				set_unselectable(obj.childNodes[i]);
			}
		}
		obj.unselectable = 'on';
	}
}

/**
* Fetches the sessionhash from the SESSIONURL variable
*
* @return	string
*/
function fetch_sessionhash()
{
	return (SESSIONURL == '' ? '' : SESSIONURL.substr(2, 32));
}

/**
* Emulates the PHP version of vBulletin's construct_phrase() sprintf wrapper
*
* @param	string	String containing %1$s type replacement markers
* @param	string	First replacement
* @param	string	Nth replacement
*
* @return	string
*/
function construct_phrase()
{
	if (!arguments || arguments.length < 1 || !is_regexp)
	{
		return false;
	}

	var args = arguments;
	var str = args[0];
	var re;

	for (var i = 1; i < args.length; i++)
	{
		re = new RegExp("%" + i + "\\$s", 'gi');
		str = str.replace(re, args[i]);
	}
	return str;
}

/**
* Handles the quick style/language options in the footer
*
* @param	object	Select object
* @param	string	Type (style or language)
*/
function switch_id(selectobj, type)
{
	var id = selectobj.options[selectobj.selectedIndex].value;

	if (id == '')
	{
		return;
	}

	var url = new String(window.location);
	var fragment = new String('');

	// get rid of fragment
	url = url.split('#');

	// deal with the fragment first
	if (url[1])
	{
		fragment = '#' + url[1];
	}

	// deal with the main url
	url = url[0];

	// remove id=x& from main bit
	if (url.indexOf(type + 'id=') != -1 && is_regexp)
	{
		re = new RegExp(type + "id=\\d+&?");
		url = url.replace(re, '');
	}

	// add the ? to the url if needed
	if (url.indexOf('?') == -1)
	{
		url += '?';
	}
	else
	{
		// make sure that we have a valid character to join our id bit
		lastchar = url.substr(url.length - 1);
		if (lastchar != '&' && lastchar != '?')
		{
			url += '&';
		}
	}

	window.location = url + type + 'id=' + id + fragment;
}

/**
* Takes the 'alt' attribute for an image and attaches it to the 'title' attribute
*
* @param	object	Image object
*/
function img_alt_2_title(img)
{
	if (!img.title && img.alt != '')
	{
		img.title = img.alt;
	}
}

// #############################################################################
// Initialize a PostBit

/**
* This function runs all the necessary Javascript code on a PostBit
* after it has been loaded via AJAX. Don't use this method before a
* complete page load or you'll have problems.
*
* @param	object	Object containing postbits
*/
function PostBit_Init(obj, postid)
{
	console.log("PostBit Init: %d", postid);

	if (typeof vBmenu != 'undefined')
	{
		// init profile menu(s)
		var divs = fetch_tags(obj, 'div');
		for (var i = 0; i < divs.length; i++)
		{
			if (divs[i].id && divs[i].id.substr(0, 9) == 'postmenu_')
			{
				vBmenu.register(divs[i].id, true);
			}
		}
	}

	if (typeof vB_QuickEditor != 'undefined')
	{
		// init quick edit controls
		vB_AJAX_QuickEdit_Init(obj);
	}

	if (typeof vB_QuickReply != 'undefined')
	{
		// init quick reply button
		qr_init_buttons(obj);
	}

	if (typeof mq_init != 'undefined')
	{
		// init quick reply button
		mq_init(obj);
	}

	if (typeof vBrep != 'undefined')
	{
		if (typeof postid != 'undefined' && typeof postid != 'null')
		{
			vbrep_register(postid);
		}
	}

	if (typeof inlineMod != 'undefined')
	{
		im_init(obj);
	}
}

// #############################################################################
// Main vBulletin Javascript Initialization

/**
* This function runs (almost) at the end of script loading on most vBulletin pages
*
* It sets up things like image alt->title tags, turns on the popup menu system etc.
*
* @return	boolean
*/
function vBulletin_init()
{
	// don't bother doing any exciting stuff for WebTV
	if (is_webtv)
	{
		return false;
	}

	// set 'title' tags for image elements
	var imgs = fetch_tags(document, 'img');
	for (var i = 0; i < imgs.length; i++)
	{
		img_alt_2_title(imgs[i]);
	}

	// finalize popup menus
	if (typeof vBmenu == 'object')
	{
		// close all menus on document click or resize
		if (typeof(YAHOO) != "undefined")
		{
			YAHOO.util.Event.on(document, "click", vbmenu_hide);
			YAHOO.util.Event.on(window, "resize", vbmenu_hide);
		}
		else if (window.attachEvent && !is_saf)
		{
			document.attachEvent('onclick', vbmenu_hide);
			window.attachEvent('onresize', vbmenu_hide);
		}
		else if (document.addEventListener && !is_saf)
		{
			document.addEventListener('click', vbmenu_hide, false);
			window.addEventListener('resize', vbmenu_hide, false);
		}
		else
		{
			window.onclick = vbmenu_hide;
			window.onresize = vbmenu_hide;
		}

		// add popups to pagenav elements
		var pagenavs = fetch_tags(document, 'td');
		for (var n = 0; n < pagenavs.length; n++)
		{
			if (pagenavs[n].hasChildNodes() && pagenavs[n].firstChild.name && pagenavs[n].firstChild.name.indexOf('PageNav') != -1)
			{
				var addr = pagenavs[n].title;
				pagenavs[n].title = '';
				pagenavs[n].innerHTML = '';
				pagenavs[n].id = 'pagenav.' + n;
				var pn = vBmenu.register(pagenavs[n].id);
				if (is_saf)
				{
					pn.controlobj._onclick = pn.controlobj.onclick;
					pn.controlobj.onclick = vBpagenav.prototype.controlobj_onclick;
				}
			}
		}

		// process the pagenavs popup form
		if (typeof addr != 'undefined')
		{
			fetch_object('pagenav_form').addr = addr;
			fetch_object('pagenav_form').gotopage = vBpagenav.prototype.form_gotopage;
			fetch_object('pagenav_ibtn').onclick = vBpagenav.prototype.ibtn_onclick;
			fetch_object('pagenav_itxt').onkeypress = vBpagenav.prototype.itxt_onkeypress;
		}

		// activate the menu system
		vBmenu.activate(true);
	}

	// the new init system
	vBulletin.init();

	return true;
}

// #############################################################################
// vBulletin Javascript Framework

/**
* General class for handling custom events and custom controls
*/
function vBulletin_Framework()
{
	/**
	* @var	array	Array of elements to be passed to control init functions
	* @var	array	Array of AJAX load/save URLs
	* @var	array	Array of YUI custom events
	* @var	date	Current time
	*/
	this.elements = new Array();
	this.ajaxurls = new Array();
	this.events = new Array();
	this.time = new Date();

	// custom event to fire during class init
	this.add_event("systemInit");
}

/**
* Initializes the object - usually called at end of footer template
*/
vBulletin_Framework.prototype.init = function()
{
	this.events.systemInit.fire();
	console.info("System Init Fired");
}

/**
* Emulates OOP class extension
*
* @param	object	Extended class
* @param	object	Base class
*/
vBulletin_Framework.prototype.extend = function(subClass, baseClass)
{
   function inheritance() {}
   inheritance.prototype = baseClass.prototype;

   subClass.prototype = new inheritance();
   subClass.prototype.constructor = subClass;
   subClass.baseConstructor = baseClass;
   subClass.superClass = baseClass.prototype;
}

/**
* Registers a custom control for later initialization
* Arguments 1-n are stored for later use
*
* @param	string	Control type (vB_DatePicker etc.)
* @param	string	HTML element ID
*/
vBulletin_Framework.prototype.register_control = function(controltype, element)
{
	var args = new Array();
	for (var i = 1; i < arguments.length; i++)
	{
		args.push(arguments[i]);
	}
	if (!this.elements[controltype])
	{
		console.info("Creating array vBulletin.elements[\"%s\"]", controltype);
		this.elements[controltype] = new Array();
	}
	var x = this.elements[controltype].push(args);
	console.log("vBulletin.elements[\"%s\"][%d] = %s", controltype, x-1, args.join(", "));
}

/**
* Registers AJAX load/save urls for a control
*
* @param	Fetch URL
* @param	Save URL
* @param	List of elements to which these URLs apply
*/
vBulletin_Framework.prototype.register_ajax_urls = function(fetch, save, elements)
{
	var fetch = fetch.split("?"); fetch[1] = SESSIONURL + "ajax=1&" + fetch[1].replace(/\{(\d+)(:\w+)?\}/gi, '%$1$s');
	var save  =  save.split("?");  save[1] = SESSIONURL + "ajax=1&" + save[1].replace(/\{(\d+)(:\w+)?\}/gi, '%$1$s');

	console.log("Register AJAX URLs for %s", elements);

	for (var i = 0; i < elements.length; i++)
	{
		this.ajaxurls[elements[i]] = new Array(fetch, save);
	}
}

/**
* Register a custom event
*
* @param	string	Event name
*/
vBulletin_Framework.prototype.add_event = function(eventname)
{
	this.events[eventname] = (typeof YAHOO != 'undefined' ? new YAHOO.util.CustomEvent(eventname) : new null_event());
}

/**
* BC: Pass console calls to Firebug if it's available
*/
vBulletin_Framework.prototype.console = console.log;

// #############################################################################

// initialize the PHP function emulator
var PHP = new vB_PHP_Emulator();

// Create an instance of the vBulletin Framework object
var vBulletin = new vBulletin_Framework();

/*======================================================================*\
|| ####################################################################
|| # Downloaded: 03:12, Tue Jul 31st 2007
|| # CVS: $RCSfile$ - $Revision: 17556 $
|| ####################################################################
\*======================================================================*/