  var rpc;
  RPC.READY_STATE_COMPLETE=4;
  function RPC(fe) {
    if (window.XMLHttpRequest){
      this.req=new XMLHttpRequest();
    } else if (window.ActiveXObject){
      this.req=new ActiveXObject("Microsoft.XMLHTTP");
    } else {
      alert("RPC not available");
    }
    this.url=fe ? fe : "rpc_save.html";
    var req=this.req;
    var rpc=this;
    this.req.onreadystatechange=function(){ 
       if (req.readyState==RPC.READY_STATE_COMPLETE){
           var httpStatus=req.status;
           if (httpStatus==200 || httpStatus==0){
                var doc = req.responseXML;
                if(!doc) {  alert("Cannot parse server reply :\n" + req.responseText); return false; }
                var response = doc.getElementsByTagName('response').item(0);
                if(!response) { alert("Server reply has no response element " + "\n" + req.responseText); }
                var more = response.getAttribute('waitmore');
                var qid  = response.getAttribute('qid');
                var qn   = response.getAttribute('qn');
                if(more) {
                   document.body.style.cursor = "wait";
                   setTimeout(function() { (new RPC(fe)).request('__wait',{q:qid,qn:qn},rpc.onOk)}, parseInt(more) );
                } else {
                   var rc=response.getAttribute('rc');
                   if (rc == 'EXCEPTION') {
                     var ex = xml_getObjectAttributes(response); 
                     var func_name = 'exception_' + ex.exceptionClass.replace(/::/g,'_');
                     if(eval("window." + func_name)) { 
                       eval(func_name + "(ex)");
                     } else { 
                       alert(ex.text ? ex.text : 'произошла ошибка на сервере');
                     }
                     document.body.style.cursor ='default';
                     return false;
                   }
                   if(rc == 'FAILED') { 
                       alert('произошла ошибка на сервере');
                       document.body.style.cursor ='default';
                       return false;
                   } 
                   rpc.onOk(response,req);
                   document.body.style.cursor ='auto';
                }
           } else {
                rpc.onError(req);
                document.body.style.cursor ='auto';
           }
        }
    };
  }
  RPC.prototype.onError = function(req) { 
       alert("error fetching data!" 
    +"\n\nreadyState:"+req.readyState
    +"\nstatus: "+req.status
    +"\nheaders: "+req.getAllResponseHeaders());
  }
  RPC.prototype.onOk = function() {
      alert("Done");
  }
  RPC.prototype.request = function(proc,args,onOk) { 
      this.req.open("POST",this.url);
      this.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      var qs='_proc=' + proc;
      for (var arg in args)  { var val=args[arg];
          if (typeof(val)=='object'){ for(k in val) { 
            if (val[k].constructor != Function)
              qs+='&' + escape(arg) + '=' + escape(val[k]);
          }}
          else { qs +='&' + escape(arg) + '=' + escape(val); }
      }
      this.onOk = onOk;
      this.req.send(qs);
  }

  function server_call(proc,args,onOk,fe) {
     rpc = new RPC(fe);
     rpc.request(proc,args,onOk);
  }
  function xml_getObjectAttribute(node,attrName) {
     for(var i=0;i<node.childNodes.length;i++) {
        var nn = node.childNodes[i];
        if(nn.nodeType==1) {
          if (nn.tagName==attrName) {
             return nn.childNodes[0]?nn.childNodes[0].data:null;
          }
        }
     }
     return 'KO';
  }
  function xml_getObjectAttributes(node) {
     var o = {};
     if(!node) { 
        alert("Empty node got");
        return o;
     }
     for(var i=0;i<node.attributes.length;i++) { 
        o [ node.attributes[i].nodeName ] = node.attributes[i].nodeValue;
     }
     for(var i=0;i<node.childNodes.length;i++) {
        var nn = node.childNodes[i];
        if(nn.nodeType==1) {
          if(nn.getAttribute('class')=='subobject') { 
             o[ nn.tagName  ] = null;
             for(var j=0;j<nn.childNodes.length;j++) { 
               var nnn=nn.childNodes[j];
               if(nnn.nodeType==1) { 
                  o[ nn.tagName  ] = xml_getObjectAttributes(nnn);
               }
               break;
             }
          } else 
          if(nn.childNodes[0]) { 
             o[ nn.tagName  ] = nn.childNodes[0].data;
          } else {
             o[ nn.tagName  ] = null;
          }
        }
     }
     return o;
  }
  function xml_getObjectList(node) { 
    var l = new Array;
    for(var i=0;i<node.childNodes.length;i++) {
        var nn = node.childNodes[i];
        if(nn.nodeType==1) {
          l[l.length] = xml_getObjectAttributes(nn);
        }
    }
    return l;
  }


function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
  if ( node == null ) node = document;
  if ( tag == null )  tag = '*';
  var els = node.getElementsByTagName(tag);
  var elsLen = els.length;
  var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
  for (i = 0, j = 0; i < elsLen; i++) {
    if ( pattern.test(els[i].className) ) {
      classElements[j] = els[i];
      j++;
    }
  }
  return classElements;

}



function tr_make_td(tr,attrs,style_attrs) {
var __document = (tr.ownerDocument && tr.ownerDocument != null && tr.ownerDocument != undefined) ? tr.ownerDocument : document;
      var td = __document.createElement('td');
      if(attrs) {
        for(var i in attrs) {
          td.setAttribute(i, attrs[i]);
          switch(i) {
            case 'colspan' : 
            case 'colSpan' : td.colSpan = attrs[i]; break;
            case 'rowspan' : 
            case 'rowSpan' : td.rowSpan = attrs[i]; break;
            case 'nowrap'  : 
            case 'noWrap'  : td.noWrap  = attrs[i]; break;
            case 'valign'  : 
            case 'vAlign'  : td.vAlign  = attrs[i]; break;
            case 'bgcolor' : 
            case 'bgColor' : td.bgColor = attrs[i]; break;
            case 'align'   : td.align   = attrs[i]; break;
            default        : break;
          }
        }
      }
      if (style_attrs) {
        for (var i in style_attrs) td.style[i] = style_attrs[i];
      }
      tr.appendChild(td);
      return td;

}



function createInputElement(doc, type, name, value,attrs,style) {
var inp;
  if(type == 'textarea') { 
    inp = doc.createElement('textarea');
    var txt = doc.createTextNode(value);
    inp.appendChild(txt);
  } else {
    inp = doc.createElement('input');
    inp.setAttribute('type',type);
    inp.setAttribute('value',value);
  }
  inp.setAttribute('name',name);
  inp.setAttribute('id', name);
  inp.onchange = function(){if(this.form && this.form.__is_any_field_modified__) this.form.__is_any_field_modified__.value = 1};
  if(attrs) { for(var i in attrs)  inp.setAttribute(i, attrs[i]); }
  if(style) { for(var i in style)  inp.style[i] = style[i]; }
  return inp;

}


function createObjectSelectElement(name,array) {
var select = document.createElement('select');
   select.setAttribute('name', name);
   for (var i=0;i<array.length;i++) { 
     var option = document.createElement('option'); select.appendChild(option);
     option.setAttribute('value', array[i][0]);
     option.appendChild(document.createTextNode(array[i][1]));
   }
   return select;

}

function createListSelectElement(document,name,array,value,class_name,style) {
var select = document.createElement('select');
   select.setAttribute('name', name);
   if(array) { for (var i=0;i<array.length;i++) { 
     var option = document.createElement('option'); select.appendChild(option);
     option.setAttribute('value', array[i][0]);
     if(array[i][0] == value) { option.selected=true; option.setAttribute('selected', 'selected'); }
     option.appendChild(document.createTextNode(array[i][1]));
   }}
   if(class_name) { select.className = class_name; }
   if(style) { for (var i in style) { select.style[i] = style[i]; }}
   return select;

}

function createList2SelectElement(document,name,array,value,class_name,style,opts) {
var select = document.createElement('select');
   select.setAttribute('name', name);
   if(array) {
     for (var i=0;i<array.length;i++) {
       var node = array[i];
       select.options[select.options.length] = new Option (node[1],node[0],(i ? false : true),(node[0] == value ? true : false));
     }
   }
   if(class_name) { select.className = class_name; }
   if(style) { for (var i in style) { select.style[i] = style[i]; }}
   if(opts) { for (var i in opts) { select.setAttribute(i,opts[i]); }}
   return select;

}



