function DynamicCombo(url, combo, succFunction, failureFunction){
    this.optionTagName = 'record';
    this.valueTagName = 'value';
    this.textTagName = 'text';
    this.succFunction = succFunction;
    this.failureFunction = failureFunction;    
    
    this.noSelectedValue = '';
    this.noSelectedName = '-- '+(window.RS_CHOOSE || 'Избор') +' --';
    this.createNoSelectedItem = true;
        
    this.url = url;
    this.combo = combo;
    this.selectedValue = null;
    this.setSelectedValue = function(val) {
      this.selectedValue = val; 
      this.combo.value = val;
    }
    
    this.clearCombo = function() {  
      if (this.combo) this.combo.options.length = 0;
    }
    
    this.failureMessage = (window.RS_CHOOSE || 'Грешка при извличане на списъка!');

    
    this.success = function(o) {
          if (o.responseXML) {         
             
             options = o.responseXML.getElementsByTagName(this.optionTagName);
             this.clearCombo();
             
             if (this.createNoSelectedItem) {
               var newOption = document.createElement('option');   
               newOption.text = this.noSelectedName;         
               newOption.value = this.noSelectedValue;  
               AddOption(this.combo, newOption);
             }   
             
                
             for (var i = 0 ; i < options.length; i++) {
                var newOption = document.createElement('option');   
                newOption.text = options[i].getAttribute(this.textTagName);         
                newOption.value = options[i].getAttribute(this.valueTagName);  
                AddOption(this.combo, newOption);   
             }
             
             if (this.selectedValue) this.combo.value = this.selectedValue;
             if (this.succFunction) this.succFunction(o.responseXML);
          } else {
            alert(o.responseText);
            if (this.failureFunction) failureFunction(o.responseText);
          } 
            
    }
    
    this.failure = function(o) {
        if (this.failureMessage) alert(this.failureMessage);
        if (this.failureFunction) failureFunction();
    }
     
    
    this.fill = function() {
      if (!this.combo) {
        alert('Error: Combo is null!');
        return;
      }
      if (!this.url || this.url == '') {
        alert('Error: URL is empty');
        return;
      }

      YAHOO.util.Connect.asyncRequest('GET', this.url, this);
    }
}

function Xml2JS(xmlNode) {
    if (xmlNode.attributes.getNamedItem("type") && xmlNode.attributes.getNamedItem("type").nodeValue == "array") {
       return Xml2Array(xmlNode);
    } else if (xmlNode.attributes.getNamedItem("type") && xmlNode.attributes.getNamedItem("type").nodeValue == "boolean") {
       if (xmlNode.firstChild.nodeValue == 'true') {
          return true;
       } else if (xmlNode.firstChild.nodeValue == 'false') {
         return false;
       } else 
         return Boolean(xmlNode.firstChild.nodeValue);
    } else if (xmlNode.attributes.getNamedItem("type") && xmlNode.attributes.getNamedItem("type").nodeValue == "integer") {
       return parseInt(xmlNode.firstChild.nodeValue);       
    } else if (xmlNode.attributes.getNamedItem("type") && xmlNode.attributes.getNamedItem("type").nodeValue == "real") {
      return parseFloat(xmlNode.firstChild.nodeValue);           
    } else {  
       if (!xmlNode.firstChild) {
         return '';
       } else {
         return (xmlNode.firstChild.nodeName == '#text' ? xmlNode.firstChild.nodeValue : XmlNode2Object(xmlNode));
       }
       
    }
    return null;
}

function Xml2Object(xml) {
  var result = {};
  var root = xml.documentElement;
  var param = root.firstChild;
 
  result.name = root.nodeName;
  while (param) {
    result[param.nodeName] = Xml2JS(param);
    param = param.nextSibling;
  }
  
  return result;
}

function XmlNode2Object(xmlNode) {
  var result = {}
  if (!xmlNode) return result;
  
  var root = xmlNode;
  var param = root.firstChild;
 
  result.name = root.nodeName;
  while (param) {
    result[param.nodeName] = Xml2JS(param);
    param = param.nextSibling;
  }
  
  return result;
}

function Xml2Array(xmlNode) {
   var result = [];
   if (!xmlNode) return result;
    
   var root = xmlNode;
   var param = root.firstChild;

  while (param) {
    result.push(Xml2JS(param));
    param = param.nextSibling;
  }
  
  return result;
}

function isArray(obj) {if (obj.constructor.toString().indexOf("Array") == -1) return false; else return true;}

function DynamicRequest(url, succFunction, failureFunction, method, postBody, defaultFailureMessage, startFunction, endFunction, context){
    this.url = url;
    this.succFunction = succFunction;
    this.failureFunction = failureFunction;
    this.startFunction = startFunction;
    this.endFunction  = endFunction;
    this.method = method;
    this.postBody = postBody;
    this.tag = null;
    this.argument = null;
    this.context = (context || this)
       
    if (defaultFailureMessage) {
      this.failureMessage = defaultFailureMessage;
    } else {
      this.failureMessage = (window.RS_ERROR_EXEC_QUERY || 'Грешка при извършване на заявката!');
    }                          
    
    if (! this.method) this.method = "GET";

    this.success = function(o) {
        var result = null;
        
        if (o.getResponseHeader['Content-Type'].indexOf('application/json') != -1) {
          if (typeof YAHOO != 'undefined' && typeof YAHOO.lang != undefined && typeof YAHOO.lang.JSON != 'undefined') {
            try {  
              result = YAHOO.lang.JSON.parse(o.responseText);  
            }  
            catch (x) {  
             result = null;  
            } 
          }
        } else
        if (o.responseXML) {            
          var result = Xml2Object(o.responseXML);
        }
          
        if (result) {
          if (result.name == 'Result' && result.Error != null && result.Success != null) {
             if (this.succFunction) this.succFunction(result.Success, o);
             if (this.failureFunction) {
               this.failureFunction(result.Error, o);
             } else {
               alert(this.failureMessage + '\n' + result.Error.text);
             }
             if (this.endFunction) this.endFunction(result, o);  
          } else
          if (result.name != "Error") {
            if (this.succFunction) this.succFunction(result, o);  
            if (this.endFunction) this.endFunction(result, o);           
          } else {
            result.requestFailureMessage = this.failureMessage;
            if (this.failureFunction) {
              this.failureFunction(result, o);
            } else {
              alert(this.failureMessage + '\n' + result.text);
            }
            if (this.endFunction) this.endFunction(result, o);
          }   
        } else {
           var result = {name:"Error", requestFailureMessage:this.failureMessage, text:o.responseText};
           if (this.failureFunction) {
             this.failureFunction(result, o);
           } else {
             alert(result.requestFailureMessage + '\n' + result.text);
           }
           if (this.endFunction) this.endFunction(result, o);
        }  
    }
    
    this.failure = function() {
       var result = {name:"Error", requestFailureMessage:this.failureMessage};
       if (this.failureFunction) {
         this.failureFunction(result);
       } else {
         alert(result.requestFailureMessage);
       } 
       if (this.endFunction) this.endFunction(result);   
    }
     
    
    this.doRequest = function() {
      if (!this.url || this.url == '') {
        if (this.failureFunction) {
          this.failureFunction({text: 'URL is empty!'});
        } else {
          alert('Error: URL is empty!');
        }   
        return;
      }

      if (this.startFunction) this.startFunction();
      YAHOO.util.Connect.asyncRequest(this.method, this.url, this, this.postBody);
    }
}


function DynamicPostRequest(url, succFunction, failureFunction, postBody, defaultFailureMessage, startFunction, endFunction, context){
   this.dynRec = new DynamicRequest(url, succFunction, failureFunction, "POST", postBody, defaultFailureMessage, startFunction, endFunction, context)

   this.url = this.dynRec.url;
   this.succFunction = this.dynRec.succFunction;
   this.failureFunction = this.dynRec.failureFunction;
   this.startFunction = this.dynRec.startFunction;
   this.endFunction  = this.dynRec.endFunction;
   this.method = this.dynRec.method;
   this.postBody = this.dynRec.postBody;  
   this.failureMessage = this.dynRec.failureMessage; 
   this.doRequest = this.dynRec.doRequest;      
   this.success = this.dynRec.success;   
   this.failure = this.dynRec.failure;  
   this.argument = this.dynRec.argument;
   this.setArgument = function(argument) {this.dynRec.argument = argument; this.argument = argument;}
   this.context = this.dynRec.context; 
}

function DynamicGetRequest(url, succFunction, failureFunction, defaultFailureMessage, startFunction, endFunction, context){
   this.dynRec = new DynamicRequest(url, succFunction, failureFunction, "GET", null, defaultFailureMessage, startFunction, endFunction, context)

   this.url = this.dynRec.url;
   this.succFunction = this.dynRec.succFunction;
   this.failureFunction = this.dynRec.failureFunction;
   this.startFunction = this.dynRec.startFunction;
   this.endFunction  = this.dynRec.endFunction;
   this.method = this.dynRec.method;
   this.postBody = this.dynRec.postBody;  
   this.failureMessage = this.dynRec.failureMessage;
   this.doRequest = this.dynRec.doRequest; 
   this.success = this.dynRec.success;   
   this.failure = this.dynRec.failure;   
   this.setArgument = function(argument) {this.dynRec.argument = argument; this.argument = argument;}      
   this.context = this.dynRec.context;     
}

function DynamicDialogRequest(succFunction, failureFunction, defaultFailureMessage, hideDialogOnlyAtSuccess, startFunction, endFunction){
   this.succFunction = succFunction;
   this.failureFunction = failureFunction;
   this.startFunction = startFunction;
   this.endFunction = endFunction;
   this.hideDialogOnlyAtSuccess = hideDialogOnlyAtSuccess;
   this.onSubmit = null;
   this.onCancel = null;
   this.savingMessage = (window.RS_SAVING || 'Записвам...');
   this.savingMessageHtml = '<div style="width:100%; height: 200px; text-align:center;padding-top:90px;">%s</div>'
   if (this.hideDialogOnlyAtSuccess != false) this.hideDialogOnlyAtSuccess  = true;
   this.dialogCaptionNew  = '';
   this.dialogCaptionEdit = '';
   this.autoCaptionGeneration = true;
   this.multiSelectBehaviour = 1;
   this.mappings = {};
   this.objectDataExtractUrl = null;
   //{speciality_id:{entityFieldId:'id', dataFieldId:'worker_id', dataFieldValue:'speciality_id', dataFieldText:'speciality_name', behaviorType:'choose', controlType:'list' data:}}
   
   this.context = null;
   
   
   //пример [{mode:'new', buttons:[{caption:'Изтриване', visible:false}]},{mode:'edit', buttons:[{caption:'Изтриване', visible:true}]}]   
   this.configButtonsInMode = null;   
   
   if (defaultFailureMessage) {
     this.failureMessage = defaultFailureMessage;
   } else {
     this.failureMessage = (window.RS_ERROR_EXEC_QUERY || 'Грешка при извършване на заявката!');
   }
   
   
   this.handleCancel = function() {
     var doIt = true;
     if (this.callback.onCancel) doIt = this.callback.onCancel();
     
     if (!doIt) return;
     this.cancel();
   }
   this.handleSubmit = function() {
     var doIt = true;
     this.callback.parepareFormForSubmit();
     if (this.callback.onSubmit) doIt = this.callback.onSubmit(); 
     
     if (!doIt) return;
     if (this.callback.startFunction) this.callback.startFunction();
     if (this.callback.hideDialogOnlyAtSuccess) {this.doSubmit();} else {this.submit();}
   
   }
   
   this.parepareFormForSubmit = function() {
     if (this.mappings) {
       for (controlId in this.mappings) {
         if (this.mappings[controlId].controlType == 'list' &&  this.mappings[controlId].behaviorType == 'choose') {
            var selObj = this.dialog.form[controlId];
            for (var i=0; i<selObj.options.length; i++) {
              selObj.options[i].selected = true;
            }
         }       
       }
     }   
   }
   
   
   this.createDialog = function(dialogDiv, dialogSettings, showDialogHiddentContainer, dialogHolderVariable) {
	  var effectSettings = null;
	  if (YAHOO.widget.ContainerEffect.FADE) effectSettings = {effect:YAHOO.widget.ContainerEffect.FADE, duration:0.25};

	  var defaultDialogSettings = { 
			width:'50%',
			fixedcenter : true,
			visible : false, 
            effect:effectSettings,
			modal:false, 
			iframe: true,
			zIndex: 300,
			postmethod: "async",
			buttons : [{text:"Отказ", handler:this.handleCancel}, {text:"Запис", handler:this.handleSubmit, isDefault:true} ]
	  };

	  for (var fieldname in defaultDialogSettings) {
	    if (! dialogSettings[fieldname]) dialogSettings[fieldname] = defaultDialogSettings[fieldname]; 
	  }
	  
  	  this.dialog = new YAHOO.widget.Dialog( dialogDiv, dialogSettings );
      if (dialogHolderVariable) dialogHolderVariable = this.dialog;
  
      this.dialog.callback = this;
      if (showDialogHiddentContainer) document.getElementById(dialogDiv).parentNode.parentNode.style.display = "block";
      
      this.dialog.render(); 
      if (this.dialogCaptionNew  == '') this.dialogCaptionNew  = this.dialog.header.innerHTML;
      if (this.dialogCaptionEdit == '') this.dialogCaptionEdit = this.dialog.header.innerHTML;
      if (this.autoCaptionGeneration && this.dialogCaptionEdit.search(/Нов[ао]?\s/i) >= 0) {
        this.dialogCaptionEdit = this.dialogCaptionEdit.replace(/Нов[ао]?\s+(.*)/i, 'Редакция на $1');
      }
      if (this.autoCaptionGeneration && this.dialogCaptionNew.search(/Редакция на\s+/i) >= 0 && this.dialogCaptionEdit == this.dialogCaptionNew) {
        //не го замествам с "Нов ...", щото не се знае рода - нов/нова/ново...
        //затова е добре да се зададе заглавието с "Нов/а/о ..." и от него автоматично ще се генерира "Редакция на .."
        this.dialogCaptionEdit = this.dialogCaptionEdit.replace(/Редакция на\s+(.*)/, 'Добавяне на $1');
      }      
   }
   
    this.success = function(o) {
      try {
        var result = null;
        
        if (o.getResponseHeader['Content-Type'].indexOf('application/json') != -1) {
          if (typeof YAHOO != 'undefined' && typeof YAHOO.lang != undefined && typeof YAHOO.lang.JSON != 'undefined') {
            try {  
              result = YAHOO.lang.JSON.parse(o.responseText);  
            }  
            catch (x) {  
             result = null;  
            } 
          }
        } else
        if (o.responseXML) {            
          var result = Xml2Object(o.responseXML);
        }
          
        if (result) {
          if (result.name == 'Result' && result.Error != null && result.Success != null) {
             if (this.succFunction) this.succFunction(result.Success, o, this);
             if (this.failureFunction) {
               this.failureFunction(result.Error);
             } else {    
               if (result.Error.text) alert(this.failureMessage + '\n' + result.Error.text);
               if (result.Error.redirectURL) location.href= result.Error.redirectURL;
             }
             if (this.endFunction) this.endFunction(result);  
          } else
          if (result.name != "Error") {
            if (this.hideDialogOnlyAtSuccess) this.hide();
            if (this.succFunction) this.succFunction(result, o, this);  
            if (this.endFunction) this.endFunction(result);           
          } else {
            result.requestFailureMessage = this.failureMessage;
            if (this.failureFunction) {
              this.failureFunction(result);
            } else {
              if (result.text) alert(this.failureMessage + '\n' + result.text);
              if (result.redirectURL) location.href= result.redirectURL;
            }
            if (this.endFunction) this.endFunction(result);
          }   
        } else {
           var result = {name:"Error", requestFailureMessage:this.failureMessage, text:o.responseText};
           if (this.failureFunction) {
             this.failureFunction(result);
           } else {
             alert(result.requestFailureMessage + '\n' + result.text);
           }
           
        }  
      }
      catch(err) {
        alert((window.RS_ERROR_PROCESSING_RESULT || "Грешка при обработка на върнатия резултат.") + "\n\n" + (window.RS_DESCRIPTION || 'Описание') + "\n" + (window.RS_NAME || "Име") + ": "+ err.name +"\n" + (window.RS_FILE || "Файл") + ": " + err.fileName + "\n" + (window.RS_ROW || "Ред") + ": " + err.lineNumber + '\n' + (window.RS_TEXT || 'Текст') + ': '+ err.message);
      }

      if (this.endFunction) this.endFunction(result);        
    }
    
    this.failure = function() {
       var result = {name:"Error", requestFailureMessage:this.failureMessage};
       if (this.failureFunction) {
         this.failureFunction(result);
       } else {
         alert(result.requestFailureMessage);
       } 
       if (this.endFunction) this.endFunction(result);   
    }
    
    
    this.findButtonByCaption = function(caption) {
      var buttons = this.dialog.footer.getElementsByTagName('button');
      for (var i = 0; i < buttons.length; i++) {
        if (buttons[i].innerHTML == caption) return buttons[i];
      }
    }
    
    this.configureButton = function(cfgButton) {
      if (cfgButton) {
        if (cfgButton.caption) {
          var btn = this.findButtonByCaption(cfgButton.caption);
          if (btn) {
            if (cfgButton.visible === false) {
              btn.style.display = 'none';
            } else if (cfgButton.visible === true) {
              btn.style.display = '';
            }
          }
        }
      }    
    }

    
    
    this.updateButtons = function(mode) {
       if (this.configButtonsInMode) {
           for (var i = 0 ; i< this.configButtonsInMode.length; i++) {
             var cfgMode = this.configButtonsInMode[i];
             if (cfgMode.mode == mode) {
                for (var j = 0; j < cfgMode.buttons.length; j++ ) {
                   this.configureButton(cfgMode.buttons[j]);
                }
             }
             
           }
       }
    }
    
    this.show = function(mode) {
        if (mode == "new") {
            this.dialog.header.innerHTML = this.dialogCaptionNew;
        } else if (mode == "edit") {
            this.dialog.header.innerHTML = this.dialogCaptionEdit;
        }
        this.updateButtons(mode);
        this.dialog.show();
    }
    this.hide = function() {
        this.dialog.hide();
    }
    this.clear = function() {
      this.dialog.form.reset();
      if (this.mappings) {
         for (controlId in this.mappings) {
           
          if (this.mappings[controlId].controlType == 'list' &&  this.mappings[controlId].behaviorType == 'choose') {
             this.dialog.form[controlId].options.length = 0;
          } else
          if (this.mappings[controlId].controlType == 'image') {         
            hid = this.mappings[controlId].hideControlId;
            ifd = this.mappings[controlId].isImageForDeleteInputId;
            
            if (hid) document.getElementById(hid).style.display = 'none';
            if (this.dialog.form[controlId]) this.dialog.form[controlId].src = '';
            if (this.mappings[controlId].flashEnabled) {
              if (document.getElementById('emb'+ controlId)) document.getElementById('emb'+ controlId).src = '';
              if (document.getElementById('par'+ controlId)) document.getElementById('par'+ controlId).value = '';
            }
            
            if (ifd) document.getElementById(ifd).value = 0;
            if (this.mappings[controlId].editFileDivId) document.getElementById(this.mappings[controlId].editFileDivId).style.display = '';
            
          }           
                 
         }
      }   
      this.dialog.sizeUnderlay();       
    }
    
    this.fillObjectHandler = function(DO, responseObject) {
      if (responseObject.argument.sender) {
        responseObject.argument.sender.fillFromObject(DO);
      } else {
        this.fillFromObject(DO);
      }
    }
    
    this.fill = function(DataObject) {
      if (this.objectDataExtractUrl) {
         var ObjectDataExtractor = new DynamicGetRequest(
                                    this.objectDataExtractUrl+(DataObject.id || DataObject.Id),
                                    this.fillObjectHandler, 
                                    null, 
                                    "Грешка при извличане данните на обекта.");
         ObjectDataExtractor.setArgument({sender:this});                           
         ObjectDataExtractor.doRequest();   
      }
      
      this.fillFromObject(DataObject);
    }
    
    this.doDecodeHtmlEntities = function(text) {
      if (text ) {
        return text.replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&quot;/g,'"');
      } else {
        return text;
      }
    }
    
    this.processValue = function(text){
      if (this.decodeHtmlEntities) {
        return this.doDecodeHtmlEntities(text);
      } else {
        return text;
      }
    }
    
    this.fillFromObject = function(DataObject) {
      for (prop in DataObject) {
        if (this.dialog.form[prop]) {
          //if (this.dialog.form[prop].tagName.toLowerCase() == 'input') {
            if (this.dialog.form[prop].type == "checkbox") {
              this.dialog.form[prop].checked =  (DataObject[prop] || this.dialog.form[prop].value == DataObject[prop]);            
            } else {
                this.dialog.form[prop].value = DataObject[prop];
            }
          //} else if (this.dialog.form[prop].tagName.toLowerCase() == 'image') {
          //   if (DataObject[prop] != '') {this.dialog.form[prop].style.display = '';} else {this.dialog.form[prop].style.display = 'none';}
          //   this.dialog.form[prop].src = DataObject[prop];
          //}
        }
      }
      
    
      for (controlId in this.mappings) {
        if (this.dialog.form[controlId]) {
        
          d = this.mappings[controlId].data;
          if (this.mappings[controlId].behaviorType == 'choose') {
             this.dialog.form[controlId].options.length = 0;
             
              
                    
             for(i = 0; i< d.length; i++) {
               if ( d[i][this.mappings[controlId].dataFieldId] == DataObject[this.mappings[controlId].entityFieldId] ) {
               
               
                 var newOption = document.createElement('option');   
                 newOption.text = d[i][this.mappings[controlId].dataFieldText];      
                 newOption.value = d[i][this.mappings[controlId].dataFieldValue];
                 AddOption(this.dialog.form[controlId], newOption);
                 
               }
             }
          } else
          if (this.mappings[controlId].controlType == 'image') {         
            h = this.mappings[controlId].hideIfSrcEquals;
            hid = this.mappings[controlId].hideControlId;
            ifd = this.mappings[controlId].isImageForDeleteInputId;
            
            src = ( ! this.mappings[controlId].entityFieldId ? DataObject[controlId] : DataObject[this.mappings[controlId].entityFieldId]); 
            if (h) {
              if (src == h) {
                document.getElementById(hid).style.display = 'none';
                
              } else {
                document.getElementById(hid).style.display = '';
              }
            }
            src = (this.mappings[controlId].srcPrefix ? this.mappings[controlId].srcPrefix : '') + src;             
            if (this.dialog.form[controlId]) this.dialog.form[controlId].src = src;
            
            if (this.mappings[controlId].flashEnabled) {
              if (document.getElementById('emb'+ controlId)) document.getElementById('emb'+ controlId).src = src;
              if (document.getElementById('obj'+ controlId)) {
                var p = document.getElementById('obj'+ controlId).parentNode;
                if (p) {
                  var ih = p.innerHTML;
                  ih = ih.replace(/<PARAM NAME="Movie" VALUE="[^"]*"/, '<PARAM NAME="Movie" VALUE="'+src+'"');
                  ih = ih.replace(/<PARAM NAME="Src" VALUE="[^"]*"/, '<PARAM NAME="Src" VALUE="'+src+'"');
                  p.innerHTML = ih;
                }
              }
              var ext = (src.substring(src.lastIndexOf('.') + 1,src.length)).toLowerCase(); 
              if (ext == 'swf') {
                 if (document.getElementById('obj'+ controlId)) document.getElementById('obj'+ controlId).parentNode.style.display = '';
                 if (this.dialog.form[controlId]) this.dialog.form[controlId].parentNode.style.display = 'none';                  
              } else {
                 if (document.getElementById('obj'+ controlId)) document.getElementById('obj'+ controlId).parentNode.style.display = 'none';
                 if (this.dialog.form[controlId]) this.dialog.form[controlId].parentNode.style.display = '';          
              } 
            }


            if ( this.mappings[controlId].editFileDivId && document.getElementById(this.mappings[controlId].editFileDivId) ) {
                            
              if (this.mappings[controlId].editSupport === false && this.dialog.form[controlId].src != '') {
                document.getElementById(this.mappings[controlId].editFileDivId).style.display = 'none';
              } else {
                document.getElementById(this.mappings[controlId].editFileDivId).style.display = '';              
              }

            }
            
            if (ifd) document.getElementById(ifd).value = 0;
            
          } else
          
          if (! this.mappings[controlId].controlType) {
             if (isArray(this.mappings[controlId].entityFieldId)) {
               if (this.mappings[controlId].entityFieldId.length > 0) {
                 val = DataObject[this.mappings[controlId].entityFieldId[0]];
                 for (i = 1; i < this.mappings[controlId].entityFieldId.length; i++) {
                    if (val == null) break;
                    val = val[this.mappings[controlId].entityFieldId[i]];
                 }                
               }
               
               if (val != null) {
                 if (this.mappings[controlId].decodeHtmlEntities) {
                   this.dialog.form[controlId].value = this.doDecodeHtmlEntities(val);
                 } else {
                   this.dialog.form[controlId].value = val;
                 }
               }
             
             } else {
                 if (this.mappings[controlId].decodeHtmlEntities) {
                   this.dialog.form[controlId].value = this.doDecodeHtmlEntities(DataObject[this.mappings[controlId].entityFieldId]);
                 } else {
                   this.dialog.form[controlId].value = DataObject[this.mappings[controlId].entityFieldId];
                 }
             }
             
          }     
          
          
        }
      }  
      this.dialog.sizeUnderlay();  
    }
}


function DynamicHtmlTable(tableId, data, fieldsData, onRowClick, zebra, useRowHighlight, context) {
  this.table = document.getElementById(tableId);
  this.data = data;
  this.fieldsData = fieldsData;
  this.zebra = true; if (zebra == false) this.zebra = false;
  this.useRowHighlight = true; if (useRowHighlight == false) this.useRowHighlight = false; 
  this.onRowClick = onRowClick; //метод, ако контекста не е зададен/име на метод, ако контекста е зададен
  this.RowClickParamFieldName = 'id';
  this.Index = null;
  this.noRowsElement = null;
  this.context = (context || this);
  this.onSumRowCalculated = null; //метод, ако контекста не е зададен/име на метод, ако контекста е зададен
  
  //{Data: [{dataField:...|colName:...}]} - ако е зададено dataField - сумира се то от data обектите, ако е colName - взема се от колоната съответното dataField, или пък се вика дефинирата функция...
  this.sumRowFields = null;
  
  //{visibleWithData: [id1, id2]}
  this.visibility = null;
  
  //[{name:fieldName,type:'asc'|'desc'}, {name:fieldName2,type:'asc'|'desc'}]  
  this.sorting = null;
  this.isSorted = true;
    
  this.isArray = function(obj) {
   if (obj.constructor.toString().indexOf("Array") == -1)
      return false;
   else
      return true;
  }
   
  this.addRow	= function(Result) {
      var lastRow = this.table.rows.length;
      var row = this.table.insertRow(lastRow);
      var cell = null;
      if (!this.RowClickParamFieldName) this.RowClickParamFieldName = 'id';
  
      if (this.zebra) {   
        if (lastRow <= 1 || this.table.rows[lastRow-1].className != 'odd') {
          row.className = 'odd';
        } else {
          row.className = 'even';    
        }  
      }
        
      for (i = 0; i < this.fieldsData.length; i++) {
        cell = row.insertCell(i);
        cell.className = (this.fieldsData[i].className ? this.fieldsData[i].className : "");
        cell.tableController = this;
        
        cell.context = this.context;
        cell.onRowClick = (this.context == this ? 'onRowClick' : this.onRowClick);
        
        if (this.onRowClick && this.fieldsData[i].onclick !== false) { 
          if (!this.fieldsData[i].onclick) {
            cell.onclick = function() {
                          if (this.tableController.isArray(this.tableController.RowClickParamFieldName)) {
                              var param = {}
                              for (var i = 0; i < this.tableController.RowClickParamFieldName.length; i++) {
                                param[this.tableController.RowClickParamFieldName[i]] = Result[this.tableController.RowClickParamFieldName];
                              }
                              
                              this.context[this.onRowClick](param);
                          } else {
                              this.context[this.onRowClick](Result[this.tableController.RowClickParamFieldName]);
                          }
                        }
           } else {
              cell.onclick = this.fieldsData[i].onclick;
           } 
        } else if (this.fieldsData[i].onclick === false) {
          cell.onclick = null;        
        }
                        
        
        if (this.fieldsData[i].func) {
          cell.innerHTML = this.fieldsData[i].func(Result);
        } 
        else 
          if (this.fieldsData[i].cmbData) {
                if (Result[this.fieldsData[i].dataObjectProperty] == '' || Result[this.fieldsData[i].dataObjectProperty] == 'null' || Result[this.fieldsData[i].dataObjectProperty] == null) {
                  cell.appendChild(document.createTextNode(''));
                } else { 
                  var tmp = this.fieldsData[i].cmbData.selectedIndex;
                  this.fieldsData[i].cmbData.value = Result[this.fieldsData[i].dataObjectProperty];
                  var index = this.fieldsData[i].cmbData.selectedIndex;
                  var text = this.fieldsData[i].cmbData.options[index].text;
                  
                  if (this.fieldsData[i].noValue != null && this.fieldsData[i].cmbData.options[index].value == this.fieldsData[i].noValue) text = '';
                  
                  cell.appendChild(document.createTextNode(text));
                  this.fieldsData[i].cmbData.selectedIndex = tmp
                }
          } 
        else    
          {    
            
            if (this.fieldsData[i].dataObjectProperty) {
              if (isArray(this.fieldsData[i].dataObjectProperty)) {
              
                 if (this.fieldsData[i].dataObjectProperty.length > 0) {
                   val = Result[this.fieldsData[i].dataObjectProperty[0]];
                   for (j = 1; j < this.fieldsData[i].dataObjectProperty.length; j++) {
                      if (val == null) break;
                      val = val[this.fieldsData[i].dataObjectProperty[j]];
                   }                
                 }
                 
                 if (val != null) cell.appendChild(document.createTextNode(val));
               
               } else {
                  if (Result[this.fieldsData[i].dataObjectProperty] != null) {
                    cell.appendChild(document.createTextNode(Result[this.fieldsData[i].dataObjectProperty]));
                  } 
               }   
                        
            }
            
            
          }

      }        
      
      this.validateVisibility();
  }
  
  this.validateVisibility = function() {
      var visibleWithData = '';
      if (this.data.length == 0) {
         if (this.noRowsElement) this.noRowsElement.style.display = '';
         this.table.style.display = 'none';
         visibleWithData = 'none';
      } else {
         if (this.noRowsElement) this.noRowsElement.style.display = 'none';
         this.table.style.display = '';
      }   
      
      if (this.visibility && this.visibility.visibleWithData) {
        for (var i = 0; i < this.visibility.visibleWithData.length; i++) {
          if (document.getElementById(this.visibility.visibleWithData[i])) document.getElementById(this.visibility.visibleWithData[i]).style.display = visibleWithData;
        }
      }
  }
  
  this.getDataObjectIndex = function(row) {
    var result = {};
    if (this.Index && this.Index.Table) {
      for (var i = 0; i < this.Index.Table.MultiFields.length; i++) {
          result[this.Index.Table.MultiFields[i].fieldName] = row.cells[this.Index.Table.MultiFields[i].colIndex].innerHTML; 
      }
    }
    return result;
  }
  
  this.walk = function(func) {
    var dataIndex;
    var data;
    
    for (i = 0; i < this.table.rows.length; i++) {

      if (this.Index && this.Index.Data) {
          if (this.Index.Data.MultiFields) {
            dataIndex = this.indexOfDataMultiFields(this.Index.Data.MultiFields, this.getDataObjectIndex(this.table.rows[i]));
          } else {
            if (!this.Index.Data.valueFieldName) this.Index.Data.valueFieldName = this.Index.Data.fieldName;
            dataIndex = this.indexOfData(DataObject[this.Index.Data.valueFieldName], this.Index.Data.fieldName);
          }
      } else {
          dataIndex = this.indexOfData(this.table.rows[i].cells[0].innerHTML);
      }

       if (dataIndex > -1) {data = this.data[dataIndex];} else {data = null;}
       func(this.table.rows[i], data);
    }
  }
  
  this.indexOfRow = function(value, colIndex) {
    var result = -1;
    if (!colIndex) colIndex = 0;
    
    for (var i = 0 ; i < this.table.rows.length; i++) {
       if (this.table.rows[i].cells[colIndex].childNodes.length > 0 && this.table.rows[i].cells[colIndex].innerHTML == value) {
          result = i
          break;
       }
    } 
    return result;   
  }
  
  this.indexOfRowMultiFields = function (FieldsArray, DataObject) {
    var result = -1;
    
    for (var i = 0 ; i < this.table.rows.length; i++) {
      var row = this.table.rows[i];
      isFound = true;
      for (var j = 0 ; j < FieldsArray.length; j++) {
        isFound = (isFound && row.cells[FieldsArray[j].colIndex].childNodes.length > 0 && row.cells[FieldsArray[j].colIndex].innerHTML == DataObject[FieldsArray[j].fieldName]);
      }
      if (isFound) {
        result = i;
        break;
      }
    } 
    return result;  
  }
  
  
  this.indexOfData = function(value, fieldName) {
    if (!fieldName) fieldName = 'id';
    for (var i = 0; i < this.data.length; i++) {
      if (this.data[i][fieldName] == value) return i;
    }
    return -1;
  }  
  
  this.indexOfDataMultiFields = function(FieldsArray, DataObject) {

    for (var i = 0; i < this.data.length; i++) {
      isFound = true;
      for (var j = 0; j < FieldsArray.length; j++) {
         if (!FieldsArray[j].valueFieldName) FieldsArray[j].valueFieldName = FieldsArray[j].fieldName;
         isFound = (isFound && this.data[i][FieldsArray[j].fieldName] == DataObject[FieldsArray[j].valueFieldName]);
      }
      
      if (isFound) return i      
    }
    return -1;
  }   
  
  this.updateRow = function(DataObject, rowIndex) {
    if (!rowIndex) {
      var rowIndex = this.indexOfRow(DataObject.id);    
    }

    if (rowIndex > -1) {

      for (i = 0; i < this.fieldsData.length; i++) { 

          if (this.fieldsData[i].func) {
            if (this.fieldsData[i].dataObjectProperty && this.fieldsData[i].dataObjectProperty.constructor == Array) {
              var isAllNeededFieldsExists = true;
              
              for (j=0; j<this.fieldsData[i].dataObjectProperty.length; j++) {
                 isAllNeededFieldsExists =  (isAllNeededFieldsExists) && (DataObject[this.fieldsData[i].dataObjectProperty[j]] != null);
                 if (!isAllNeededFieldsExists) break;
              } 
              
              if (isAllNeededFieldsExists) {
                this.table.rows[rowIndex].cells[i].innerHTML = this.fieldsData[i].func(DataObject);
              }
            
            } else {
              if (! this.fieldsData[i].dataObjectProperty || DataObject[this.fieldsData[i].dataObjectProperty] != null) {
              		this.table.rows[rowIndex].cells[i].innerHTML = this.fieldsData[i].func(DataObject);
              }
            }
          } 
          else
            if (this.fieldsData[i].cmbData) {
                if (DataObject[this.fieldsData[i].dataObjectProperty] != null)
                  if (DataObject[this.fieldsData[i].dataObjectProperty] == '' || DataObject[this.fieldsData[i].dataObjectProperty] == 'null') {
                    this.table.rows[rowIndex].cells[i].innerHTML = '';
                  } else { 
                    var tmp = this.fieldsData[i].cmbData.selectedIndex;
                    this.fieldsData[i].cmbData.value = DataObject[this.fieldsData[i].dataObjectProperty];
                    var index = this.fieldsData[i].cmbData.selectedIndex;
                  
                    var text = this.fieldsData[i].cmbData.options[index].text;
                    if (this.fieldsData[i].noValue != null && this.fieldsData[i].cmbData.options[index].value == this.fieldsData[i].noValue) text = '';

                                      
                    this.table.rows[rowIndex].cells[i].innerHTML = text;
                    this.fieldsData[i].cmbData.selectedIndex = tmp;
                  }
            } 
          else  
            if (this.fieldsData[i].dataObjectProperty) {
              if (isArray(this.fieldsData[i].dataObjectProperty)) {
              
                 if (this.fieldsData[i].dataObjectProperty.length > 0) {
                   val = DataObject[this.fieldsData[i].dataObjectProperty[0]];
                   for (j = 1; j < this.fieldsData[i].dataObjectProperty.length; j++) {
                      if (val == null) break;
                      val = val[this.fieldsData[i].dataObjectProperty[j]];
                   }                
                 }
                 
                 if (val != null) this.table.rows[rowIndex].cells[i].innerHTML = val;                
               } else {
                  if (DataObject[this.fieldsData[i].dataObjectProperty] != null) {
                    this.table.rows[rowIndex].cells[i].innerHTML = DataObject[this.fieldsData[i].dataObjectProperty]; 
                  } 
               }   
                        
            }

          
          
        this.table.rows[rowIndex].cells[i].context = this.context;
        this.table.rows[rowIndex].cells[i].onRowClick = (this.context == this ? 'onRowClick' : this.onRowClick);
                        
          if (this.isArray(this.RowClickParamFieldName)) {
              var param = {}
              
              for (var j = 0; j < this.RowClickParamFieldName.length; j++) {
                param[this.RowClickParamFieldName[j]] = DataObject[this.RowClickParamFieldName[j]];
              }
              
              this.table.rows[rowIndex].cells[i].rowClickParam = param;
          } else {
              this.table.rows[rowIndex].cells[i].rowClickParam = DataObject[this.RowClickParamFieldName];
          } 
                  
        if (this.fieldsData[i].onclick === false) {
           this.table.rows[rowIndex].cells[i].onclick = ''; 
        } else
        if (this.onRowClick) { 
            this.table.rows[rowIndex].cells[i].onclick = function() {this.context[this.onRowClick](this.rowClickParam);}
        } 
          
          
      }
    } 

    
  }
  
  this.addData = function(DataObject, SearchCriteria, index) {
    if (SearchCriteria) {
        if (SearchCriteria.MultiFields) {
          index = this.indexOfDataMultiFields(SearchCriteria.MultiFields, DataObject)
        } else {
          if (!SearchCriteria.valueFieldName) SearchCriteria.valueFieldName = SearchCriteria.fieldName;
          index = this.indexOfData(DataObject[SearchCriteria.valueFieldName], SearchCriteria.fieldName);
        }
    } else {
      if (!index) {
        index = this.indexOfData(DataObject.id);
      }
    }
    
    var newData = {};
    if (index > -1) newData = this.data[index];

    for ( prop in DataObject ) {
      if (DataObject[prop] != null)  newData[prop] = DataObject[prop];
    } 

    if (index > -1) {this.data[index] = newData;} else {this.data.push(newData);};  
  }
  
  this.addUpdateDataObject = function(DataObject, SearchCriteria, rowIndex) {
      if (SearchCriteria && SearchCriteria.Table) {
        if (SearchCriteria.Table.MultiFields) {
          rowIndex = this.indexOfRowMultiFields(SearchCriteria.Table.MultiFields, DataObject);
        } else {
          rowIndex = this.indexOfRow(DataObject[SearchCriteria.Table.fieldName], SearchCriteria.Table.colIndex);
        }
      } else {
        if (!rowIndex) {
          rowIndex = this.indexOfRow(DataObject.id);
        }
      }
      
      if (rowIndex > -1) {
         this.updateRow(DataObject, rowIndex);
      }  else {
         this.addRow(DataObject);
      }

      this.addData(DataObject, ((SearchCriteria && SearchCriteria.Data) ? SearchCriteria.Data : null));
      if (this.sumRowFields) this.addSumRow();
      
      if (this.sorting != null) {
      	this.sort();
      }
      
      this.validateVisibility();
  }
  
  this.clear = function() {
    for(i = this.table.rows.length-1; i > 0; i--) {
        this.table.deleteRow(i);
    }
    this.data = [];
            
    this.validateVisibility();
  }
  
  this.removeRow = function(DataObject) {
      var rowIndex = null;
      var dataIndex = null;
      if (!rowIndex) rowIndex = this.indexOfRow(DataObject.id);
      if (!dataIndex) dataIndex =  this.indexOfData(DataObject.id);
      
      if (rowIndex > -1 && dataIndex > -1) {
        this.table.deleteRow(rowIndex);
        this.data.splice(dataIndex, 1);
       
        this.validateVisibility();
	      if (this.zebra) this.updateZebra();
	 
			  if (this.sumRowFields) this.addSumRow();
      }
  }
  
  this.updateZebra = function() {
    lastClassName = "even";
    for (var i = 1; i < this.table.rows.length; i++) {
      if (lastClassName == "even") {
        this.table.rows[i].className = 'odd';
      } else {
        this.table.rows[i].className = 'even';    
      }  
      lastClassName = this.table.rows[i].className;
    }  	
  }
  
  this.dataFromRow = function(DataObject) {
      var result = DataObject;
      var rowIndex = null;
      var dataIndex = null;
      if (!rowIndex) rowIndex = this.indexOfRow(DataObject.id);      
      
      if (rowIndex > -1) {
         for (i = 0; i < this.fieldsData.length; i++) {
            if (this.fieldsData[i].dataObjectProperty) {
              result[this.fieldsData[i].dataObjectProperty] = this.table.rows[rowIndex].cells[i].innerHTML ;
            }
         }
      }
      
      return result;
  }
   
  this.sort = function() {
  	window.dhtSorting = this.sorting;
  	try {
  	  this.data.sort(this.sortCompare);
  	   this.updateRowsOrder();
  	  this.is_sorted = true;
  	} catch (e) {}
  	window.dhtSorting = null;
  }
  
  this.updateRowsOrder = function() {
  	var d, index, row;
  	 
  	for (var i = 0 ; i < this.data.length; i++) {
  		d = this.data[i];
  		index = this.indexOfRow(d.id);
  		row = this.table.rows[index];
  		row.parentNode.appendChild(row);
  	}
  	
  	this.updateZebra();
  }
  
  this.sortCompare = function(a, b) {
  	var sortingFieldName = this.dhtSorting[0].name; 
  	var sortingType = ('type' in this.dhtSorting[0] ? this.dhtSorting[0]['type'] : 'asc');
  	
    var x = a[sortingFieldName];
    var y = b[sortingFieldName];
    
    return (sortingType == 'desc' ? -1 : 1) * ((x < y) ? -1 : ((x > y) ? 1 : 0));
  }
  
  this.addSumRow = function() {
      if (!this.sumRow) {
        //var foot = document.createElement("tfoot");
        //this.table.appendChild(foot);
        var lastRow = this.table.rows.length;
        this.sumRow = this.table.insertRow(lastRow);
        var row = this.sumRow;
      } else {
        var row = this.sumRow;
        var c = row.lastChild;
        while (c) {
          row.removeChild(c);
          c = row.lastChild;
        }
      }

      var cell = null;
  
      var result = {};

      for (var i = 0; i < this.sumRowFields.Data.length; i++) {
        result[this.sumRowFields.Data[i].dataField] = 0;
      }
   
      for (var i = 0; i < this.data.length; i++) {
        for (var j = 0; j < this.sumRowFields.Data.length; j++) {   
          
          if (this.data[i][this.sumRowFields.Data[j].dataField]) {
            if (! this.sumRowFields.Data[j].condition ||
                  this.sumRowFields.Data[j].condition(this.data[i]) ) {
              if (!this.sumRowFields.Data[j].func) {
                result[this.sumRowFields.Data[j].dataField] += parseFloat(this.data[i][this.sumRowFields.Data[j].dataField]);
              } else {
				        result[this.sumRowFields.Data[j].dataField] += this.sumRowFields.Data[j].func(this.data[i]);              
              }
              
            }
          }
        }
        
      }
      


      var resultIndex = -1;  
      for (i = 0; i < this.fieldsData.length; i++) {
        colName = this.fieldsData[i].dataObjectProperty;
        if (!colName ||  this.isArray(this.fieldsData[i].dataObjectProperty)) {
          colName = this.fieldsData[i].colName;
        }      
      
        resultIndex = -1;
        for (var j = 0; j < this.sumRowFields.Data.length; j++) {
          if (colName == this.sumRowFields.Data[j].dataField) {
             resultIndex = j;
             break
          }
        }
        
        resultIndexVisual = -1;
        if (this.sumRowFields.Visual && this.sumRowFields.Visual.Fields) {
	        for (var j = 0; j < this.sumRowFields.Visual.Fields.length; j++) {
	          if (colName == this.sumRowFields.Visual.Fields[j].dataField) {
	        	  resultIndexVisual = j;
	             break
	          }
	        }        
        }
        
        cell = row.insertCell(i);
        if (this.fieldsData[i].className == 'hidden') {
          cell.className = 'hidden';
        } else {
          if (resultIndexVisual != -1) {
        	cell.className = this.sumRowFields.Visual.Fields[resultIndexVisual].className;
          }	else {
	          if (this.sumRowFields.Visual.cellClassName) {
	            cell.className = this.sumRowFields.Visual.cellClassName;
	          } else {
	              cell.className = '';
	          }
          }
        }
        
        cell.context = this.context;   
             
        if (resultIndex > -1) {
          var value = result[this.sumRowFields.Data[resultIndex].dataField];
          value = value.toFixed(this.sumRowFields.Visual.decimalPlaces || 2);
          cell.innerHTML = value;
        }

              
      };
      
    if (this.onSumRowCalculated) {
      if (this.context) {
        this.context[this.onSumRowCalculated](result); 
      } else {
        this.onSumRowCalculated(result);
      }
    }
  }
  
  this.createHtml = function(config) {
    var aContainer = config.container;
    var tableConfig = config.tableConfig;
    var noRowsConfig = config.noRowsConfig;
  
    var container = (typeof(aContainer) == 'string' ? document.getElementById(aContainer) : aContainer);
    if (!container) container = document.body;
    
    if (!this.noRowsElement && noRowsConfig) {
      if (noRowsConfig.element) {
        this.noRowsElement = noRowsConfig.element;
      } else {
	      var messageDiv = document.createElement('div');
	      messageDiv.className = noRowsConfig.className;
	      messageDiv.id = noRowsConfig.id;
	      messageDiv.innerHTML = noRowsConfig.message;
	      
	      container.appendChild(messageDiv);
	      this.noRowsElement = messageDiv;
      }
      
      this.noRowsElement.style.display = 'none';
    }
    
    if (tableConfig) {
      this.table = document.createElement('table');
      this.table.style.display = 'none';
      this.table.id = tableConfig.id;
      this.table.className = tableConfig.className;
       
      //var thead = document.createElement("thead"); 
      var tbody = document.createElement("tbody"); 
      //var tfoot = document.createElement("tfoot");  
           
      var row = document.createElement("tr");
      var cell = null;
			for (var i = 0; i < this.fieldsData.length; i++) {
  			 cell = document.createElement('th');
  			 if (this.fieldsData[i].headerFunc) {
  			   cell.innerHTML = this.fieldsData[i].headerFunc();
  			 } else {
  			   cell.innerHTML = (this.fieldsData[i].caption || '');
  			 } 
  			 if (this.fieldsData[i].className == 'hidden') cell.className = 'hidden';  	
  			 if (this.fieldsData[i].headerClassName) cell.className = this.fieldsData[i].headerClassName;
  			 row.appendChild(cell);
      }
      
      tbody.appendChild(row);
      //this.table.appendChild(thead); 
      this.table.appendChild(tbody);
      //this.table.appendChild(tfoot);
      container.appendChild(this.table);              
    }
  }
}

function searchInDataArray(data, criteria) {
  var isFound = false; 
  for (var i = 0 ; i < data.length; i++) {
    isFound = true;
    for (field in criteria) {
      if (! data[i][field] || data[i][field] != criteria[field]) {
        isFound = false;
        break;
      }
    }
    if (isFound) return data[i];
  }
  
  return null;
}
