www.gusucode.com > 支持select显示复选框的JS列表框插件源码程序 > 支持select显示复选框的JS列表框插件/dhtmlxCombo/dhtmlxCombo/sources/dhtmlxcombo.js

    //v.2.1 build 90226

/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/

/*_TOPICS_
@0:Initialization
@1:Selection control
@2:Add/delete
@3:Reserved
@4:Methods of Option object
*/
/**
*  Build combobox from existing select control.
*
*
*  @param   parent      {string} id of existing select control
*  @param   size      {int } size of control, optional
*  @return            {object} combobox object
*  @type   public
*  @topic   0
*
*/

function dhtmlXComboFromSelect(parent,size){
   if (typeof(parent)=="string")
      parent=document.getElementById(parent);
   
   
   size=size||parent.getAttribute("width")||(window.getComputedStyle?window.getComputedStyle(parent,null)["width"]:(parent.currentStyle?parent.currentStyle["width"]:0));
   if ((!size)||(size=="auto"))
   		size=parent.offsetWidth||100;

   var z=document.createElement("SPAN");
   
	if(parent.style.direction=="rtl") z.style.direction = "rtl"; 
  
   parent.parentNode.insertBefore(z,parent);
   parent.style.display='none';

    var s_type = parent.getAttribute('opt_type');
	
   var w= new dhtmlXCombo(z,parent.name,size,s_type,parent.tabIndex);
   
   var x=new Array();
   var sel=0;
   for (var i=0; i<parent.options.length; i++){
      if (parent.options[i].selected) sel=i;
      var label=parent.options[i].innerHTML;
      var val=parent.options[i].getAttribute("value");
      if ((typeof(val)=="undefined")||(val===null)) val=label;
      x[i]={value:val,text:label,img_src:parent.options[i].getAttribute("img_src")};
   }

    w.addOption(x);
   
   
   parent.parentNode.removeChild(parent);
   w.selectOption(sel,null,true);
   if (parent.onchange) 
   		w.attachEvent("onChange",parent.onchange);
   return w;
}

var dhtmlXCombo_optionTypes = [];
/**
*     @desc: build combobox
*     @param: parent - (string) id of existing object which will be used as container
*     @param: name - (string) name of combobox - will be used in FORM
*     @param: width - (int) size of combobox
*     @param: tabIndex - (int) tab index, optional
*     @type: public
*     @topic: 0
*/
function dhtmlXCombo(parent,name,width,optionType,tabIndex){
      if (typeof(parent)=="string")
         parent=document.getElementById(parent);

      dhtmlxEventable(this);
      this.optionType = (optionType != window.undefined && dhtmlXCombo_optionTypes[optionType]) ? optionType : 'default';
      this._optionObject = dhtmlXCombo_optionTypes[this.optionType];

      this._disabled = false;
	  
	  if(parent.style.direction == "rtl") this.rtl = true;
	  else this.rtl = false; 
     	
	  if (!window.dhx_glbSelectAr){
          window.dhx_glbSelectAr=new Array();
          window.dhx_openedSelect=null;
          window.dhx_SelectId=1;
          dhtmlxEvent(document.body,"click",this.closeAll);
          dhtmlxEvent(document.body,"keydown",function(e){ try { if ((e||event).keyCode==9)  window.dhx_glbSelectAr[0].closeAll(); } catch(e) {} return true; } );
      }
		
     if (parent.tagName=="SELECT")
         return dhtmlXComboFromSelect(parent);
      else
         this._createSelf(parent,name,width,tabIndex);
      dhx_glbSelectAr.push(this);
}

/**
*     @desc: change control size
*     @param: new_size - (int) new size value
*     @type: public
*     @topic: 0
*/
   dhtmlXCombo.prototype.setSize = function(new_size){
      this.DOMlist.style.width=new_size+"px";
      if (this.DOMlistF) this.DOMlistF.style.width=new_size+"px";
      this.DOMelem.style.width=new_size+"px";
      this.DOMelem_input.style.width = Math.max(0,(new_size-19))+'px';
   }      
/**
*     @desc: switch between combobox and auto-filter modes
*     @param: mode - (boolean) enable filtering mode
*     @param: url - (string) url for filtering from XML, optional
*     @param: cache - (boolean) XML caching, optional
*     @param: autosubload - (boolean) enable auto load additional suggestions on selecting last loaded option
*     @type: public
*     @topic: 0
*/
   dhtmlXCombo.prototype.enableFilteringMode = function(mode,url,cache,autosubload){
      this._filter=convertStringToBoolean(mode);

      if (url){
         this._xml=url;
         this._autoxml=convertStringToBoolean(autosubload);
      }
      if (convertStringToBoolean(cache)) this._xmlCache=[];
      //this.DOMelem_button.style.display=(this._filter?"none":"");
   }
   
   dhtmlXCombo.prototype.setFilteringParam=function(name,value){
   		if (!this._prs) this._prs=[];
   		this._prs.push([name,value]);
   }
/**
*     @desc: disable combobox
*     @param: mode - (boolean) disable combobox
*     @type: public
*     @topic: 1
*/
   dhtmlXCombo.prototype.disable = function(mode){
      var z=convertStringToBoolean(mode);
      if (this._disabled==z) return;
      this.DOMelem_input.disabled=z;
      this._disabled=z;
   }
/**
*     @desc: switch to readonly mode
*     @param: mode - (boolean) readonly mode
*     @param: autosearch - (boolean) true by default 
*     @type: public
*     @topic: 1
*/
   dhtmlXCombo.prototype.readonly = function(mode,autosearch){
        this.DOMelem_input.readOnly=mode ? true : false;
		if(autosearch===false || mode===false){
			this.DOMelem.onkeyup=function(ev){ }
		} else {
			var that = this;
			this.DOMelem.onkeyup=function(ev){ 
				ev=ev||window.event; 
				if (ev.keyCode!=9) ev.cancelBubble=true;
				if((ev.keyCode >= 48 && ev.keyCode <= 57)||(ev.keyCode >= 65 && ev.keyCode <= 90)){
					for(var i=0; i<that.optionsArr.length; i++){
						var text = that.optionsArr[i].text;
						if(text.toString().toUpperCase().indexOf(String.fromCharCode(ev.keyCode)) == 0){
								that.selectOption(i);
								break;
						}
					}
					ev.cancelBubble=true;
				}
			}
		}
	}	
   
/**
*     @desc: get Option by value
*     @param: value - (string) value of option in question
*     @type: public
*     @return: option object
*     @topic: 2
*/
   dhtmlXCombo.prototype.getOption = function(value)
   {
      for(var i=0; i<this.optionsArr.length; i++)
         if(this.optionsArr[i].value==value)
            return this.optionsArr[i];
      return null;
   }
/**
*     @desc: get Option by label
*     @param: label - (string) label of option in question
*     @type: public
*     @return: option object
*     @topic: 2
*/
   dhtmlXCombo.prototype.getOptionByLabel = function(value)
   {
	  //value=value.replace(/&/g,"&amp;")
      for(var i=0; i<this.optionsArr.length; i++)
         if(this.optionsArr[i].text==value || this.optionsArr[i]._ctext==value)
            return this.optionsArr[i];
      return null;
   }
/**
*     @desc: get Option by index
*     @param: ind - (int) index of option in question
*     @type: public
*     @return: option object
*     @topic: 2
*/
   dhtmlXCombo.prototype.getOptionByIndex = function(ind){
      return this.optionsArr[ind];
   }
/**
*     @desc: clear all options from combobox
*     @type: public
*     @param: value - (bool) clear current value as well
*     @topic: 2
*/
   dhtmlXCombo.prototype.clearAll = function(all)
   {
	  if (all) this.setComboText("");   	  
      this.optionsArr=new Array();
      this.redrawOptions();
      if (all) this._confirmSelection();
   }
/**
*     @desc: delete option by value
*     @param: value - (string) value of option in question
*     @type: public
*     @topic: 2
*/
   dhtmlXCombo.prototype.deleteOption = function(value)
   {
        var ind=this.getIndexByValue(value);
      if(ind<0) return;                            
      if (this.optionsArr[ind]==this._selOption) this._selOption=null;
      this.optionsArr.splice(ind, 1);
      this.redrawOptions();
   }

/**
*     @desc: enable/disable immideatly rendering after changes in combobox
*     @param: mode - (boolean) enable/disable
*     @type: public
*     @topic: 1
*/
   dhtmlXCombo.prototype.render=function(mode){
      this._skiprender=(!convertStringToBoolean(mode));
      this.redrawOptions();
   }

/**
*     @desc: update option in combobox
*     @param: oldvalue - (string) index of option in question
*     @param: avalue - (variable)
*     @type: public
*     @topic: 2
*/
   dhtmlXCombo.prototype.updateOption = function(oldvalue, avalue, atext, acss)
   {
      var dOpt=this.getOption(oldvalue);
      if (typeof(avalue)!="object") avalue={text:atext,value:avalue,css:acss};
      dOpt.setValue(avalue);
        this.redrawOptions();
   }
/**
*     @desc: add new option
*     @param: value - (variable) - different input for different kinds of options - please refer to examples
*     @type: public
*     @topic: 2
*/
   dhtmlXCombo.prototype.addOption = function(options)
   {
      if (!arguments[0].length || typeof(arguments[0])!="object")
         args = [arguments];
      else
         args = options;

      this.render(false);
        for (var i=0; i<args.length; i++) {
            var attr = args[i];
         if (attr.length){
               attr.value = attr[0]||"";
               attr.text = attr[1]||"";
               attr.css = attr[2]||"";
         }
            this._addOption(attr);
        }
      this.render(true);
   }

   dhtmlXCombo.prototype._addOption = function(attr)
   {
         dOpt = new this._optionObject();
         this.optionsArr.push(dOpt);
         dOpt.setValue.apply(dOpt,[attr]);
         this.redrawOptions();
   }


/**
*     @desc: return index of item by value
*     @param: value - (string) value of option in question
*     @type: public
*     @return: option index
*     @topic: 2
*/
   dhtmlXCombo.prototype.getIndexByValue = function(val){
      for(var i=0; i<this.optionsArr.length; i++)
         if(this.optionsArr[i].value == val) return i;
      return -1;
   }

/**
*     @desc: get value of selected item
*     @type: public
*     @return: option value
*     @topic: 2 
*/
   dhtmlXCombo.prototype.getSelectedValue = function(){
      return (this._selOption?this._selOption.value:null);
   }
/**
*     @desc: get current text in combobox
*     @type: public
*     @return: combobox text
*     @topic: 2
*/
   dhtmlXCombo.prototype.getComboText = function(){
      return this.DOMelem_input.value;
   }
/**
*     @desc: set text in covmbobox
*     @param: text - (string) new text label
*     @type: public
*     @topic: 2
*/
   dhtmlXCombo.prototype.setComboText = function(text){
      this.DOMelem_input.value=text;
   }
   
/**
*     @desc: set text in covmbobox
*     @param: text - (string) new text label
*     @type: public
*     @topic: 2
*/
   dhtmlXCombo.prototype.setComboValue = function(text){
      this.setComboText(text);
	  for(var i=0; i<this.optionsArr.length; i++)
         if (this.optionsArr[i].data()[0]==text)
         return this.selectOption(i,null,true);      
      this.DOMelem_hidden_input.value=text;
   }   

/**
*     @desc: get value which will be sent with form
*     @type: public
*     @return: combobox value
*     @topic: 2
*/
   dhtmlXCombo.prototype.getActualValue = function(){
      return this.DOMelem_hidden_input.value;
   }
/**
*     @desc: get text of selected option
*     @type: public
*     @return: text of option
*     @topic: 2
*/
   dhtmlXCombo.prototype.getSelectedText = function(){
      return (this._selOption?this._selOption.text:"");
   }
/**
*     @desc: get index of selected option
*     @type: public
*     @return: option index
*     @topic: 2
*/
   dhtmlXCombo.prototype.getSelectedIndex = function(){
      for(var i=0; i<this.optionsArr.length; i++)
         if(this.optionsArr[i] == this._selOption) return i;
      return -1;
   }
/**
*     @desc: set name used while form submit
*     @param: name - (string) new combobox name
*     @type: public
*     @topic: 2
*/
   dhtmlXCombo.prototype.setName = function(name){  
        this.DOMelem_hidden_input.name = name;
        this.DOMelem_hidden_input2 = name+"_new_value";
        this.name = name;
   }
/**
*     @desc: show combox ( reversion to hide command )
*     @param: mode - (boolean) enable/disable
*     @type: public
*     @topic: 1
*/
   dhtmlXCombo.prototype.show = function(mode){
      if (convertStringToBoolean(mode))
         this.DOMelem.style.display = "";
      else
         this.DOMelem.style.display = "none";
   }

/**
*     @desc: destroy object and any related HTML elements
*     @type: public
*     @topic: 0
*/
   dhtmlXCombo.prototype.destructor = function()
   {
      var _sID = this._inID;
      this.DOMParent.removeChild(this.DOMelem);
      this.DOMlist.parentNode.removeChild(this.DOMlist);
      var s=dhx_glbSelectAr;
      this.DOMParent=this.DOMlist=this.DOMelem=0;
      this.DOMlist.combo=this.DOMelem.combo=0;
      for(var i=0; i<s.length; i++)
      {
         if(s[i]._inID == _sID)
         {
            s[i] = null;
            s.splice(i,1);
            return;
         }
      }
   }

/**
*     @desc: create self HTML
*     @type: private
*     @topic: 0
*/
      dhtmlXCombo.prototype._createSelf = function(selParent, name, width, tab)
      {
         if (width.toString().indexOf("%")!=-1){ 
            var self = this;
            var resWidht=parseInt(width)/100;
            window.setInterval(function(){ 
               if (!selParent.parentNode) return;
               var ts=selParent.parentNode.offsetWidth*resWidht-2;
               if (ts<0) return;
               if (ts==self._lastTs) return;
               self.setSize(self._lastTs=ts);},500);
            var width=parseInt(selParent.offsetWidth); //mm
         }

         var width=parseInt(width||100); //mm
         this.ListPosition = "Bottom"; //set optionlist positioning
         this.DOMParent = selParent;
         this._inID = null;
         this.name = name;

         this._selOption = null; //selected option object pointer
         this.optionsArr = Array();

            var opt = new this._optionObject();
            opt.DrawHeader(this,name, width,tab);
         //HTML select part 2 - options list DIV element
         this.DOMlist = document.createElement("DIV");
         this.DOMlist.className = 'dhx_combo_list';
		 if(this.rtl) this.DOMlist.className = 'dhx_combo_list_rtl'; //rtl
         this.DOMlist.style.width=width-(_isIE?0:0)+"px";
		 if (_isOpera || _isKHTML ) 
		 		this.DOMlist.style.overflow="auto";      
         this.DOMlist.style.display = "none";
         document.body.insertBefore(this.DOMlist,document.body.firstChild);         
         if (_isIE)    {
            this.DOMlistF = document.createElement("IFRAME");
            this.DOMlistF.style.border="0px";
            this.DOMlistF.className = 'dhx_combo_list';
            this.DOMlistF.style.width=width-(_isIE?0:0)+"px";
            this.DOMlistF.style.display = "none";
            this.DOMlistF.src="javascript:false;"; 
            document.body.insertBefore(this.DOMlistF,document.body.firstChild);
            }



         this.DOMlist.combo=this.DOMelem.combo=this;

         this.DOMelem_input.onkeydown = this._onKey;
          this.DOMelem_input.onkeypress = this._onKeyF;
         this.DOMelem_input.onblur = this._onBlur;
         this.DOMelem.onclick = this._toggleSelect;
         this.DOMlist.onclick = this._selectOption;
         this.DOMlist.onmousedown = function(){
         	this._skipBlur=true;
     	 }
         
         this.DOMlist.onkeydown = function(e){
         	this.combo.DOMelem_input.focus();
         	(e||event).cancelBubble=true;
         	this.combo.DOMelem_input.onkeydown(e)
     	 }
		  this.DOMlist.onmouseover = this._listOver;
     	 
      }

      dhtmlXCombo.prototype._listOver = function(e)
      {
         e = e||event;
         e.cancelBubble = true;
         var node = (_isIE?event.srcElement:e.target);
         var that = this.combo;
         if ( node.parentNode == that.DOMlist ) {
            if(that._selOption) that._selOption.deselect(); 
			if(that._tempSel) that._tempSel.deselect();
           
		    var i=0;
            for (i; i<that.DOMlist.childNodes.length; i++) {
               if (that.DOMlist.childNodes[i]==node) break;
            }
            var z=that.optionsArr[i];
           that._tempSel=z;
           that._tempSel.select();
            
			if ((that._autoxml)&&((i+1)==that._lastLength))
            	that._fetchOptions(i+1,that._lasttext||"");            
         }

      }

/**
*     @desc: place option list in necessary place on screen
*     @type: private
*     @topic: 0
*/
      dhtmlXCombo.prototype._positList = function()
      {
	  	//if(this.ListAutoPosit) this.enableOptionAutoPositioning(true); //mm auto posit
         var pos=this.getPosition(this.DOMelem);
         if(this.ListPosition == 'Bottom'){
            this.DOMlist.style.top = pos[1]+this.DOMelem.offsetHeight+"px";
            this.DOMlist.style.left = pos[0]+"px";
         }
         else if(this.ListPosition == 'Top'){ //mm
				this.DOMlist.style.top = pos[1] - this.DOMlist.offsetHeight+"px";
            	
				this.DOMlist.style.left = pos[0]+"px"; //mm
          }
		  else{
			this.DOMlist.style.top = pos[1]+"px";
            this.DOMlist.style.left = pos[0]+this.DOMelem.offsetWidth+"px";
         }
     
      }
	  
      dhtmlXCombo.prototype.getPosition = function(oNode,pNode){

                  if(!pNode)
                        var pNode = document.body

                  var oCurrentNode=oNode;
                  var iLeft=0;
                  var iTop=0;
                  while ((oCurrentNode)&&(oCurrentNode!=pNode)){//.tagName!="BODY"){
               iLeft+=oCurrentNode.offsetLeft-oCurrentNode.scrollLeft;
               iTop+=oCurrentNode.offsetTop-oCurrentNode.scrollTop;
               oCurrentNode=oCurrentNode.offsetParent;
                  }
              if (pNode == document.body ){
                 if (_isIE){
                 if (document.documentElement.scrollTop)
                  iTop+=document.documentElement.scrollTop;
                 if (document.documentElement.scrollLeft)
                  iLeft+=document.documentElement.scrollLeft;
                  }
                  else
                       if (!_isFF){
                             iLeft+=document.body.offsetLeft;
                           iTop+=document.body.offsetTop;
                  }
                 }
                     return new Array(iLeft,iTop);
               }
/**
*     @desc: correct current selection ( move it to first visible option )
*     @type: private
*     @topic: 2
*/
      dhtmlXCombo.prototype._correctSelection = function(){
		 if (this.getComboText()!="")
         for (var i=0; i<this.optionsArr.length; i++)
            if (!this.optionsArr[i].isHidden()){
               return this.selectOption(i,true,false);
           }
         this.unSelectOption();
      }
/**
*     @desc: select next option in combobox
*     @param: step - (int) step size
*     @type: private
*     @topic: 2
*/
      dhtmlXCombo.prototype.selectNext = function(step){
         var z=this.getSelectedIndex()+step;
         while (this.optionsArr[z]){
            if (!this.optionsArr[z].isHidden())
               return this.selectOption(z,false,false);
            z+=step;
         }
      }
/**
*     @desc: on keypressed handler
*     @type: private
*     @topic: 0
*/
      dhtmlXCombo.prototype._onKeyF = function(e){
         var that=this.parentNode.combo;
         var ev=e||event;
         ev.cancelBubble=true;
         if (ev.keyCode=="13" || ev.keyCode=="9" ){
         	that._confirmSelection();
         	that.closeAll();
     	} else
        if (ev.keyCode=="27" ){
         	that._resetSelection();
         	that.closeAll();
     	} else that._activeMode=true;
         if (ev.keyCode=="13" || ev.keyCode=="27" ){ //enter
            that.callEvent("onKeyPressed",[ev.keyCode])
            return false;
         }
         return true;
      }
/**
*     @desc: on keyup handler
*     @type: private
*     @topic: 0
*/
      dhtmlXCombo.prototype._onKey = function(e){
         var that=this.parentNode.combo;
         (e||event).cancelBubble=true;
         var ev=(e||event).keyCode;
         if (ev>15 && ev<19) return true; //shift,alt,ctrl
        if (ev==27) return;
        if ((that.DOMlist.style.display!="block")&&(ev!="13")&&(ev!="9")&&((!that._filter)||(that._filterAny)))
            that.DOMelem.onclick(e||event);
       
		if ((ev!="13")&&(ev!="9")){
         	window.setTimeout(function(){ that._onKeyB(ev); },1);
         	if (ev=="40" || ev=="38")
         		return false;
     	}
         else if (ev==9){
         	that.closeAll();
         	(e||event).cancelBubble=false;
         }
      }
      dhtmlXCombo.prototype._onKeyB = function(ev)
      {
         if (ev=="40"){  //down
            var z=this.selectNext(1);
         } else if (ev=="38"){ //up
            this.selectNext(-1);
         } else{
            this.callEvent("onKeyPressed",[ev])
            if (this._filter) return this.filterSelf((ev==8)||(ev==46));
            for(var i=0; i<this.optionsArr.length; i++)
               if (this.optionsArr[i].data()[1]==this.DOMelem_input.value){
//                  ev.cancelBubble=true;
                  this.selectOption(i,false,false);
                  return false;
                  }
            this.unSelectOption();
         }
         return true;
      }


/**
*     @desc: on data change handler
*     @type: private
*     @topic: 0
*/
      dhtmlXCombo.prototype._onBlur = function()
      {
          var self = this.parentNode._self;
          window.setTimeout(function(){
          	if (self.DOMlist._skipBlur) return !(self.DOMlist._skipBlur=false);
          	self._confirmSelection();        
          	self.callEvent("onBlur",[]);
          },100)
          
      }
/**
*     @desc: redraw combobox options
*     @type: private
*     @topic: 2
*/
      dhtmlXCombo.prototype.redrawOptions = function(){
         if (this._skiprender) return;
         for(var i=this.DOMlist.childNodes.length-1; i>=0; i--)
            this.DOMlist.removeChild(this.DOMlist.childNodes[i]);
         for(var i=0; i<this.optionsArr.length; i++)
            this.DOMlist.appendChild(this.optionsArr[i].render());
			
		
		
						

      }
/**
*     @desc: load list of options from XML
*     @param: url - (string) xml url
*     @type: public
*     @topic: 0
*/
      dhtmlXCombo.prototype.loadXML = function(url,afterCall){
         this._load=true;
         this.callEvent("onXLS",[]);
         if ((this._xmlCache)&&(this._xmlCache[url])){
            this._fillFromXML(this,null,null,null,this._xmlCache[url]);
            if (afterCall) afterCall();
        }
         else{
            var xml=(new dtmlXMLLoaderObject(this._fillFromXML,this,true,true));
            if (afterCall) xml.waitCall=afterCall;
            if (this._prs)
            	for (var i=0; i<this._prs.length; i++)
            		url+=[getUrlSymbol(url),escape(this._prs[i][0]),"=",escape(this._prs[i][1])].join("");
            xml._cPath=url;
            xml.loadXML(url);
         }
      }

/**
*     @desc: load list of options from XML string
*     @param: astring - (string) xml string
*     @type: public
*     @topic: 0
*/
      dhtmlXCombo.prototype.loadXMLString = function(astring){
         var xml=(new dtmlXMLLoaderObject(this._fillFromXML,this,true,true));
         xml.loadXMLString(astring);
      }

/**
*     @desc: on XML load handler
*     @type: private
*     @topic: 0
*/
      dhtmlXCombo.prototype._fillFromXML = function(obj,b,c,d,xml){
         if (obj._xmlCache) obj._xmlCache[xml._cPath]=xml;

         //check that XML is correct 
         var toptag=xml.getXMLTopNode("complete");
         if (toptag.tagName!="complete") return;
         var top=xml.doXPath("//complete");
         var options=xml.doXPath("//option");
         
         obj.render(false);
         if ((!top[0])||(!top[0].getAttribute("add"))){
            obj.clearAll();
            obj._lastLength=options.length;
	         if (obj._xml){
	         if ((!options) || (!options.length)) 
	         	obj.closeAll();
	         else {
	         		if (obj._activeMode){
	         			obj._positList();
	        			obj.DOMlist.style.display="block";
	         			if (_isIE) obj._IEFix(true);
         			}
	     	 }}            
         } else
            obj._lastLength+=options.length;

         for (var i=0; i<options.length; i++) {
            var attr = new Object();
            attr.text = options[i].firstChild?options[i].firstChild.nodeValue:"";
            for (var j=0; j<options[i].attributes.length; j++) {
               var a = options[i].attributes[j];
               if (a)
                  attr[a.nodeName] = a.nodeValue;
            }
            obj._addOption(attr);
         }
         obj.render(true);
         	
         if ((obj._load)&&(obj._load!==true))
            obj.loadXML(obj._load);
         else{
            obj._load=false;
             if ((!obj._lkmode)&&(!obj._filter))
               obj._correctSelection();
            }

         var selected=xml.doXPath("//option[@selected]");
         if (selected.length)
         	obj.selectOption(obj.getIndexByValue(selected[0].getAttribute("value")),false,true);

         obj.callEvent("onXLE",[]);

      }
/**
*     @desc: deselect option
*     @type: public
*     @topic: 1
*/
      dhtmlXCombo.prototype.unSelectOption = function(){
         if (this._selOption) this._selOption.deselect();
         if(this._tempSel) this._tempSel.deselect();
         this._tempSel=this._selOption=null;
      }
      
      dhtmlXCombo.prototype._confirmSelection = function(data,status){
      	if(arguments.length==0){
      	    var z=this.getOptionByLabel(this.DOMelem_input.value);
          	data = z?z.value:this.DOMelem_input.value;
          	status = (z==null);
          	if (data==this.getActualValue()) return;
      	}
          	
      	this.DOMelem_hidden_input.value=data;
        this.DOMelem_hidden_input2.value = (status?"true":"false");
      	this.callEvent("onChange",[]);
      	this._activeMode=false;
  	  }
      dhtmlXCombo.prototype._resetSelection = function(data,status){
      		var z=this.getOption(this.DOMelem_hidden_input.value);
      		this.setComboValue(z?z.data()[0]:this.DOMelem_hidden_input.value)
      		this.setComboText(z?z.data()[1]:this.DOMelem_hidden_input.value)
  	  }  	  
  	  
/**
*     @desc: select option
*     @param: ind - (int) index of option in question
*     @param: filter - (boolean) enable autocomplit range, optional
*     @param: conf - (boolean) true for real selection, false for pre-selection
*     @type: public
*     @topic: 1
*/
      dhtmlXCombo.prototype.selectOption = function(ind,filter,conf){
      	 if (arguments.length<3) conf=true;
         this.unSelectOption();
         var z=this.optionsArr[ind];
         if (!z)  return;
         this._selOption=z;
         this._selOption.select();

         var corr=this._selOption.content.offsetTop+this._selOption.content.offsetHeight-this.DOMlist.scrollTop-this.DOMlist.offsetHeight;
         if (corr>0) this.DOMlist.scrollTop+=corr;
            corr=this.DOMlist.scrollTop-this._selOption.content.offsetTop;
         if (corr>0) this.DOMlist.scrollTop-=corr;
         var data=this._selOption.data();

	 	 if (conf){
	 	 	this.setComboText(data[1]);
	 	 	this._confirmSelection(data[0],false);
		 } 	 
	 	 
         if ((this._autoxml)&&((ind+1)==this._lastLength))
            this._fetchOptions(ind+1,this._lasttext||"");

         if (filter){
            var text=this.getComboText();
            if (text!=data[1]){
               this.setComboText(data[1]);
               dhtmlXRange(this.DOMelem_input,text.length+1,data[1].length);
            }
         }
         else
            this.setComboText(data[1]);
         this._selOption.RedrawHeader(this);

         /*Event*/
         this.callEvent("onSelectionChange",[]);
      }
/**
*     @desc: option on select handler
*     @type: private
*     @topic: 2
*/
      dhtmlXCombo.prototype._selectOption = function(e)
      {
         (e||event).cancelBubble = true;
         var node=(_isIE?event.srcElement:e.target);
         var that=this.combo;
         while (!node._self) {
            node = node.parentNode;
            if (!node)
               return;
         }

         var i=0;
         for (i; i<that.DOMlist.childNodes.length; i++) {
            if (that.DOMlist.childNodes[i]==node) break;
         }
         that.selectOption(i,false,true);
         that.closeAll();
         that.callEvent("onBlur",[])
         that._activeMode=false;
      }
/**
*     @desc: open list of options 
*     @type: public
*     @topic: 2
*/
   dhtmlXCombo.prototype.openSelect = function(){ 
   	
	
    
	  if (this._disabled) return;
      this.closeAll();
      this._positList();
      this.DOMlist.style.display="block";
      this.callEvent("onOpen",[]);
	  if(this._tempSel) this._tempSel.deselect();
	  if(this._selOption) this._selOption.select();
	  if(this._selOption){
	 	var corr=this._selOption.content.offsetTop+this._selOption.content.offsetHeight-this.DOMlist.scrollTop-this.DOMlist.offsetHeight;
         if (corr>0) this.DOMlist.scrollTop+=corr;
            corr=this.DOMlist.scrollTop-this._selOption.content.offsetTop;
         if (corr>0) this.DOMlist.scrollTop-=corr;
	  }
	  /* if (this.autoOptionSize){
        	var x=this.DOMlist.offsetWidth; 
			
        	for ( var i=0; i<this.optionsArr.length; i++){
				if(i==0) alert("this.DOMlist.childNodes[i].scrollWidth ="+ this.DOMlist.childNodes[i].scrollWidth + "> x= "+ x);
        		if (this.DOMlist.childNodes[i].scrollWidth > x)
        			x=this.DOMlist.childNodes[i].scrollWidth;
			}
        			
			this.DOMlist.style.width=x+"px";
		}*/
		
		      
      if (_isIE) this._IEFix(true);
      this.DOMelem_input.focus();
	
      if (this._filter) this.filterSelf();
   }
/**
*     @desc: open(close) list
*     @type: private
*     @topic: 2
*/
   dhtmlXCombo.prototype._toggleSelect = function(e)
   {
      var that=this.combo;
      if ( that.DOMlist.style.display == "block" ) {
      that.closeAll();
      } else {
         that.openSelect();
      }
      (e||event).cancelBubble = true;
   }

    dhtmlXCombo.prototype._fetchOptions=function(ind,text){
          if (text=="") { this.closeAll();  return this.clearAll();   }
         var url=this._xml+((this._xml.indexOf("?")!=-1)?"&":"?")+"pos="+ind+"&mask="+encodeURIComponent(text);
         this._lasttext=text;
         if (this._load) this._load=url;
         else this.loadXML(url);
    }
/**
*     @desc: filter list of options
*     @type: private
*     @topic: 2
*/
    dhtmlXCombo.prototype.filterSelf = function(mode)
   {
      var text=this.getComboText();
      if (this._xml){
         this._lkmode=mode;
         this._fetchOptions(0,text);
      }
      try{ var filter=new RegExp("^"+text,"i"); } catch (e){ var filter=new RegExp("^"+text.replace(/([\[\]\{\}\(\)\+\*\\])/g,"\\$1")); }
      this.filterAny=false;
      for(var i=0; i<this.optionsArr.length; i++){
      	 var z=filter.test(this.optionsArr[i].text);
      	 this.filterAny|=z;
         this.optionsArr[i].hide(!z);
      }
      if (!this.filterAny) {
		  this.closeAll();
		  this._activeMode=true;
	  }
      else {
      	  if (this.DOMlist.style.display!="block")
      	   		this.openSelect();
	      if (_isIE) this._IEFix(true);
  		}
         
        if (!mode)
         this._correctSelection();   
        else this.unSelectOption();
   }
 
 


/**
*     @desc: set hidden iframe for IE
*     @type: private
*     @topic: 2
*/
   dhtmlXCombo.prototype._IEFix = function(mode){
      this.DOMlistF.style.display=(mode?"block":"none");
        this.DOMlistF.style.top=this.DOMlist.style.top;
        this.DOMlistF.style.left=this.DOMlist.style.left;
   }
/**
*     @desc: close opened combobox list
*     @type: public
*     @topic: 1
*/
   dhtmlXCombo.prototype.closeAll = function()
   {
      if(window.dhx_glbSelectAr)
         for (var i=0; i<dhx_glbSelectAr.length; i++){
            if (dhx_glbSelectAr[i].DOMlist.style.display=="block") {
               dhx_glbSelectAr[i].DOMlist.style.display = "none";
               if (_isIE) dhx_glbSelectAr[i]._IEFix(false);
            }
            dhx_glbSelectAr[i]._activeMode=false;
        }
   }
/**
*     @desc: create selection range in input control
*     @param: InputId - (string) id of input ( object can be used as well )
*     @param: Start - (int) start selection position
*     @param: End - (int) end selection position
*     @type: public
*     @topic: 0
*/
function dhtmlXRange(InputId, Start, End)
{
   var Input = typeof(InputId)=='object' ? InputId : document.getElementById(InputId);
   try{    Input.focus();   } catch(e){};
   var Length = Input.value.length;
   Start--;
   if (Start < 0 || Start > End || Start > Length)
      Start = 0;
   if (End > Length)
      End = Length;
   if (Start==End) return;
   if (Input.setSelectionRange) {
      Input.setSelectionRange(Start, End);
   } else if (Input.createTextRange) {
      var range = Input.createTextRange();
      range.moveStart('character', Start);
      range.moveEnd('character', End-Length);
      range.select();
   }
}
/**
*     @desc: combobox option object constructor
*     @type: public
*     @topic: 0
*/
      dhtmlXCombo_defaultOption = function(){
         this.init();
      }
/**
*     @desc: option initialization function
*     @type: private
*     @topic: 4
*/
      dhtmlXCombo_defaultOption.prototype.init = function(){
         this.value = null;
         this.text = "";
         this.selected = false;
         this.css = "";
      }
/**
*     @desc: mark option as selected
*     @type: public
*     @topic: 4
*/
      dhtmlXCombo_defaultOption.prototype.select = function(){
         if (this.content)
            this.content.className="dhx_selected_option";
      }
/**
*     @desc: hide option
*     @param: mode - (boolean)
*     @type: public
*     @topic: 4
*/
      dhtmlXCombo_defaultOption.prototype.hide = function(mode){
         this.render().style.display=mode?"none":"";
      }
/**
*     @desc: return hide state of option
*     @type: public
*     @return: hide state of option
*     @topic: 4
*/
      dhtmlXCombo_defaultOption.prototype.isHidden = function(){
         return (this.render().style.display=="none");
      }
/**
*     @desc: mark option as not selected
*     @type: public
*     @topic: 4
*/
      dhtmlXCombo_defaultOption.prototype.deselect = function(){
         if (this.content) this.render();
            this.content.className="";
      }
/**
*     @desc: set value of option
*     @param: value - (string) value
*     @param: text - (string) text
*     @param: css - (string) css style string
*     @type: public
*     @topic: 4
*/
dhtmlXCombo_defaultOption.prototype.setValue = function(attr){
    this.value = attr.value||"";
    this.text = attr.text||"";
    this.css = attr.css||"";
   this.content=null;
}

				
/**
*     @desc: render option
*     @type: private
*     @topic: 4
*/
      dhtmlXCombo_defaultOption.prototype.render = function(){
         if (!this.content){
            this.content=document.createElement("DIV");
        this.content._self = this;

            this.content.style.cssText='width:100%; overflow:hidden;'+this.css;
            if (_isOpera || _isKHTML ) this.content.style.padding="2px 0px 2px 0px";
            this.content.innerHTML=this.text;
            this._ctext=_isIE?this.content.innerText:this.content.textContent;
         }
         return this.content;
      }
/**
*     @desc: return option data
*     @type: public
*     @return: array of data related to option
*     @topic: 4
*/
      dhtmlXCombo_defaultOption.prototype.data = function(){
         if (this.content)
            return [this.value,this._ctext ? this._ctext : this.text];
      }

dhtmlXCombo_defaultOption.prototype.DrawHeader = function(self, name, width, tab)
{
    var z=document.createElement("DIV");
    z.style.width = width+"px";
    z.className = 'dhx_combo_box';
    z._self = self;
	self.DOMelem = z;	
   	this._DrawHeaderInput(self, name, width,tab);
	this._DrawHeaderButton(self, name, width);
    self.DOMParent.appendChild(self.DOMelem);
}

dhtmlXCombo_defaultOption.prototype._DrawHeaderInput = function(self, name, width,tab)
{

	if(self.rtl && _isIE)  {
		var z=document.createElement('textarea');
 		z.style.overflow = "hidden";
		z.style.whiteSpace="nowrap"
	}
 	else {
 		var z=document.createElement('input');
		z.setAttribute("autocomplete","off"); 
		z.type = 'text';
	}
   z.className = 'dhx_combo_input';
   
   if(self.rtl) {
   	z.style.left = "18px";
	z.style.direction = "rtl";
   	z.style.unicodeBidi = "bidi-override";  
   }
   

   if (tab) z.tabIndex=tab;
   z.style.width = (width-19)+'px';
   self.DOMelem.appendChild(z);
   self.DOMelem_input = z;

   z = document.createElement('input');
   z.type = 'hidden';
   z.name = name;
   self.DOMelem.appendChild(z);
   self.DOMelem_hidden_input = z;

   z = document.createElement('input');
   z.type = 'hidden';
   z.name = name+"_new_value";
   z.value="true";
   self.DOMelem.appendChild(z);
   self.DOMelem_hidden_input2 = z;
}

dhtmlXCombo_defaultOption.prototype._DrawHeaderButton = function(self, name, width)
{
   var z=document.createElement('img');
   z.className = (self.rtl)?'dhx_combo_img_rtl':'dhx_combo_img';

   z.src = (window.dhx_globalImgPath?dhx_globalImgPath:"")+'combo_select.gif';
   self.DOMelem.appendChild(z);
   self.DOMelem_button=z;
}

dhtmlXCombo_defaultOption.prototype.RedrawHeader = function(self)
{
}


dhtmlXCombo_optionTypes['default'] = dhtmlXCombo_defaultOption;

//(c)dhtmlx ltd. www.dhtmlx.com