/**
  * JsHttpRequest: JavaScript "AJAX" data loader.
  * (C) 2006 Dmitry Koterov, http://forum.dklab.ru/users/DmitryKoterov/
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * See http://www.gnu.org/copyleft/lesser.html
  *
  * Do not remove this comment if you want to use script!
  * Не удаляйте данный комментарий, если вы хотите использовать скрипт!
  *
  * This library tries to use XMLHttpRequest (if available), and on
  * failure - use dynamically created <script> elements. Backend code
  * is the same for both cases. Library also supports file uploading;
  * in this case it uses FORM+IFRAME-based loading.
  *
  * @author Dmitry Koterov
  * @version 4.16
  */
 
 function JsHttpRequest(){this._construct()}
 (function(){var COUNT=0;var PENDING={};var CACHE={};JsHttpRequest.dataReady=function(id,text,js){var undef;var th=PENDING[id];delete PENDING[id];if(th){delete th._xmlReq;if(th.caching&&th.hash)CACHE[th.hash]=[text,js];th._dataReady(text,js);}else if(th!==false){throw"JsHttpRequest.dataReady(): unknown pending id: "+id;}}
 JsHttpRequest.query=function(url,content,onready,nocache){var req=new JsHttpRequest();req.caching=!nocache;req.onreadystatechange=function(){if(req.readyState==4){onready(req.responseJS,req.responseText);}}
 req.open(null,url,true);req.send(content);},JsHttpRequest.prototype={onreadystatechange:null,readyState:0,responseText:null,responseXML:null,status:200,statusText:"OK",responseJS:null,session_name:"PHPSESSID",caching:false,loader:null,_span:null,_id:null,_xmlReq:null,_openArg:null,_reqHeaders:null,_maxUrlLen:2000,dummy:function(){},abort:function(){if(this._xmlReq){this._xmlReq.abort();this._xmlReq=null;}
 this._cleanupScript();this._changeReadyState(4,true);},open:function(method,url,asyncFlag,username,password){var sid=this._getSid();if(sid)url+=(url.indexOf('?')>=0?'&':'?')+this.session_name+"="+this.escape(sid);this._openArg={method:(method||'').toUpperCase(),url:url,asyncFlag:asyncFlag,username:username!=null?username:'',password:password!=null?password:''};this._id=null;this._xmlReq=null;this._reqHeaders=[];this._changeReadyState(1,true);return true;},send:function(content){this._changeReadyState(1,true);var id=(new Date().getTime())+""+COUNT++;var url=this._openArg.url;var queryText=[];var queryElem=[];if(!this._hash2query(content,null,queryText,queryElem))return;var loader=(this.loader||'').toLowerCase();var method=this._openArg.method;var xmlReq=null;if(queryElem.length&&!loader){loader='form';}else{xmlReq=this._obtainXmlReq(id,url)}
 var fullGetUrl=url+(url.indexOf('?')>=0?'&':'?')+queryText.join('&');this.hash=null;if(this.caching&&!queryElem.length){this.hash=fullGetUrl;if(CACHE[this.hash]){var c=CACHE[this.hash];this._dataReady(c[0],c[1]);return false;}}
 var canSetHeaders=xmlReq&&(window.ActiveXObject||xmlReq.setRequestHeader);if(!loader){if(xmlReq){loader='xml';switch(method){case"POST":if(!canSetHeaders){loader='form';}
 break;case"GET":break;default:if(canSetHeaders){method='POST';}else{if(fullGetUrl.length>this._maxUrlLen){method='POST';loader='form';}else{method='GET';}}}}else{loader='script';switch(method){case"POST":loader='form';break;case"GET":break;default:if(fullGetUrl.length>this._maxUrlLen){method='POST';loader='form';}else{method='GET';}}}}else if(!method){switch(loader){case'form':method='POST';break;case'script':method='GET';break;default:if(canSetHeaders){method='POST';}else{method='GET';}}}
 var requestBody=null;if(method=='GET'){url=fullGetUrl;if(url.length>this._maxUrlLen)return this._error('Cannot use so long query (URL is '+url.length+' byte(s) length) with GET request.');}else if(method=='POST'){requestBody=queryText.join('&');}else{return this._error('Unknown method: '+method+'. Only GET and POST are supported.');}
 url=url+(url.indexOf('?')>=0?'&':'?')+'JsHttpRequest='+id+'-'+loader;PENDING[id]=this;switch(loader){case'xml':if(!xmlReq)return this._error('Cannot use XMLHttpRequest or ActiveX loader: not supported');if(method=="POST"&&!canSetHeaders)return this._error('Cannot use XMLHttpRequest loader or ActiveX loader, POST method: headers setting is not supported');if(queryElem.length)return this._error('Cannot use XMLHttpRequest loader: direct form elements using and uploading are not implemented');this._xmlReq=xmlReq;var a=this._openArg;this._xmlReq.open(method,url,a.asyncFlag,a.username,a.password);if(canSetHeaders){for(var i=0;i<this._reqHeaders.length;i++)
 this._xmlReq.setRequestHeader(this._reqHeaders[i][0],this._reqHeaders[i][1]);this._xmlReq.setRequestHeader('Content-Type','application/octet-stream');}
 return this._xmlReq.send(requestBody);case'script':if(method!='GET')return this._error('Cannot use SCRIPT loader: it supports only GET method');if(queryElem.length)return this._error('Cannot use SCRIPT loader: direct form elements using and uploading are not implemented');this._obtainScript(id,url);return true;case'form':if(!this._obtainForm(id,url,method,queryText,queryElem))return null;return true;default:return this._error('Unknown loader: '+loader);}},getAllResponseHeaders:function(){if(this._xmlReq)return this._xmlReq.getAllResponseHeaders();return'';},getResponseHeader:function(label){if(this._xmlReq)return this._xmlReq.getResponseHeader(label);return'';},setRequestHeader:function(label,value){this._reqHeaders[this._reqHeaders.length]=[label,value];},_construct:function(){},_dataReady:function(text,js){with(this){if(text!==null||js!==null){status=4;responseText=responseXML=text;responseJS=js;}else{status=500;responseText=responseXML=responseJS=null;}
 _changeReadyState(2);_changeReadyState(3);_changeReadyState(4);_cleanupScript();}},_error:function(msg){throw(window.Error?new Error(msg):msg);},_obtainXmlReq:function(id,url){var p=url.match(new RegExp('^([a-z]+)://([^/]+)(.*)','i'));if(p){if(p[2].toLowerCase()==document.location.hostname.toLowerCase()){url=p[3];}else{return null;}}
 var req=null;if(window.XMLHttpRequest){try{req=new XMLHttpRequest()}catch(e){}}else if(window.ActiveXObject){try{req=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}
 if(!req)try{req=new ActiveXObject("Msxml2.XMLHTTP")}catch(e){}}
 if(req){var th=this;req.onreadystatechange=function(){if(req.readyState==4){req.onreadystatechange=th.dummy;th.status=null;try{th.status=req.status;th.responseText=req.responseText;}catch(e){}
 if(!th.status)return;var funcRequestBody=null;try{eval('funcRequestBody = function() {\n'+th.responseText+'\n}');}catch(e){return th._error("JavaScript code generated by backend is invalid!\n"+th.responseText)}
 funcRequestBody();}};this._id=id;}
 return req;},_obtainScript:function(id,href){with(document){var span=createElement('SPAN');span.style.display='none';body.insertBefore(span,body.lastChild);span.innerHTML='Text for stupid IE.<s'+'cript></'+'script>';setTimeout(function(){var s=span.getElementsByTagName('script')[0];s.language='JavaScript';if(s.setAttribute)s.setAttribute('src',href);else s.src=href;},10);this._id=id;this._span=span;}},_obtainForm:function(id,url,method,queryText,queryElem){if(method=='GET'){queryText=url.split('?',2)[1].split('&');url=url.split('?',2)[0];}
 var div=document.createElement('DIV');div.id='jshr_d_'+id;div.style.position='absolute';div.style.visibility='hidden';div.innerHTML='<form enctype="multipart/form-data"></form>'+'<iframe src="javascript:\'\'" name="jshr_i_'+id+'" style="width:0px; height:0px; overflow:hidden; border:none"></iframe>';var form=div.getElementsByTagName('FORM')[0];var iframe=div.getElementsByTagName('IFRAME')[0];if(queryElem.length){form=queryElem[0][1].form;var foundFile=false;for(var i=0;i<queryElem.length;i++){var e=queryElem[i][1];if(!e.form){return this._error('Element "'+e.name+'" do not belongs to any form!');}
 if(e.form!=form){return this._error('Element "'+e.name+'" belongs to different form. All elements must belong to the same form!');}
 foundFile=foundFile||(e.tagName.toLowerCase()=='input'&&(e.type||'').toLowerCase()=='file');}
 var et="multipart/form-data";if(form.enctype!=et&&foundFile){return this._error('Attribute "enctype" of elements\' form must be "'+et+'" (for IE), "'+form.enctype+'" given.');}}
 for(var i=0;i<form.elements.length;i++){var e=form.elements[i];if(e.name!=null){e.jshrSaveName=e.name;e.name='';}}
 var tmpE=[];for(var i=0;i<queryText.length;i++){var pair=queryText[i].split('=',2);var e=document.createElement('INPUT');e.type='hidden';e.name=unescape(pair[0]);e.value=pair[1]!=null?unescape(pair[1]):'';form.appendChild(e);tmpE[tmpE.length]=e;}
 for(var i=0;i<queryElem.length;i++)queryElem[i][1].name=queryElem[i][0];document.body.insertBefore(div,document.body.lastChild);this._span=div;var sv={};sv.enctype=form.enctype;form.enctype="multipart/form-data";sv.action=form.action;form.action=url;sv.method=form.method;form.method=method;sv.target=form.target;form.target=iframe.name;sv.onsubmit=form.onsubmit;form.onsubmit=null;form.submit();for(var i in sv)form[i]=sv[i];for(var i=0;i<tmpE.length;i++)tmpE[i].parentNode.removeChild(tmpE[i]);for(var i=0;i<form.elements.length;i++){var e=form.elements[i];if(e.jshrSaveName!=null){e.name=e.jshrSaveName;e.jshrSaveName=null;}}},_cleanupScript:function(){var span=this._span;if(span){this._span=null;setTimeout(function(){span.parentNode.removeChild(span);},50);}
 if(this._id){PENDING[this._id]=false;}
 return false;},_hash2query:function(content,prefix,queryText,queryElem){if(prefix==null)prefix="";if(content instanceof Object){for(var k in content){var v=content[k];if(v instanceof Function)continue;var curPrefix=prefix?prefix+'['+this.escape(k)+']':this.escape(k);if(this._isFormElement(v)){var tn=v.tagName.toLowerCase();if(tn=='form'){for(var i=0;i<v.elements.length;i++){var e=v.elements[i];if(e.name)queryElem[queryElem.length]=[e.name,e];}}else if(tn=='input'||tn=='textarea'||tn=='select'){queryElem[queryElem.length]=[curPrefix,v];}else{return this._error('Invalid FORM element detected: name='+(e.name||'')+', tag='+e.tagName);}}else if(v instanceof Object){this._hash2query(v,curPrefix,queryText,queryElem);}else{if(v===null)continue;queryText[queryText.length]=curPrefix+"="+this.escape(''+v);}}}else{queryText[queryText.length]=content;}
 return true;},_isFormElement:function(e){return e&&e.ownerDocument&&e.parentNode&&e.parentNode.appendChild&&e.tagName;},_getSid:function(){var m=document.location.search.match(new RegExp('[&?]'+this.session_name+'=([^&?]*)'));var sid=null;if(m){sid=m[1];}else{var m=document.cookie.match(new RegExp('(;|^)\\s*'+this.session_name+'=([^;]*)'));if(m)sid=m[2];}
 return sid;},_changeReadyState:function(s,reset){with(this){if(reset){status=statusText=responseJS=null;responseText='';}
 readyState=s;if(onreadystatechange)onreadystatechange();}},escape:function(s){return escape(s).replace(new RegExp('\\+','g'),'%2B');}}})();
