文本框+层模拟下拉框,并实现输入自动提示和过滤

采用xml,xsl,js,xmldom编写.兼容ie和firefox浏览器.

效果如以下网址:

http://www.vcsale.com/cheap.Final_Fantasy_XI.3.aspx

 

1.首先,一个简单的js类.

function inputSelection()
{
    
/*fcuandy 2007-11-22*/    

    
var txtObj      = null;  //输入框 input text
    var selObj      = null;  //模拟下拉列表的层 the div which used for option items container
    var xd          = null;  //数据据源. xmldom对象 xmldom data source
    var pstIdObj    = null;  //下拉后,将id也即option.value存放的位置 
    var pstNameObj  = null;  //下拉后,将name也即option.outertext存放的位置.这两个主要用于表单提交的参数,可用input type=hidden
    var selXPath    = null;  //针对xmldom进行查询的路径 xpath string
    var selAttributeName = null;  //输入框中的值与哪个属性值,或节点值进行匹配比较  compare attribute name
    var callMethod = null//点击模拟下拉列表层中的某个项后,数据进行了处理之后,是否再调用其它页面js方法. 可为空
    var idIndex = 0;  //设置,pstIdObj的值取node的第0个属性 
    var txtIndex = 1//设置,pstNameObj的值取node的第1个属性


    
//清空select div
    this.clearSEL=function()
    
{
        
this.selObj.innerHTML = "";
        
this.pstIdObj.value = "";
        
this.pstNameObj.value = "";
    }



    
//根跟用户输入值重建select div 里的选项
    this.reBuildSEL=function()
    
{
   
        
var s = this.txtObj.value.toLowerCase();
        
var outHTML = "";

        
if(ie4)
        
{this.xd.setProperty("SelectionLanguage","XPath");}
    
    
        
//text input .value is null, then list all servers
        if(s.length==0)
        
{
            
var root=this.xd.selectNodes(this.selXPath);

        }

        
else
        
{
            
var root=this.xd.selectNodes(this.selXPath + "[starts-with(translate(@" + this.selAttributeName + ",'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ'),'" + s.toUpperCase()  + "')]");

        }

        
        
//no server available,then list all servers
        /*if(root.length==0)
        {
            root=this.xd.selectNodes("//server");
            var root=this.xd.selectNodes(this.selXPath);
        }
*/


        
if(ie4)
        
{
            
for(var i=0;i<root.length;i++)
            
{
                
                outHTML 
+= "<a href='#'><div style='cursor:hand;width:182;text-decoration:none;color:#333;' onmouseover='this.style.backgroundColor="#98CDCD"' onmouseout='this.style.backgroundColor=""' id="li_" + root(i).attributes(this.idIndex).value + "" onclick='javascript:document.getElementById("" + this.txtObj.id + "").value=this.innerText;document.getElementById("" + this.pstIdObj.id + "").value=this.id.substring(this.id.indexOf("_")+1,this.id.length);document.getElementById("" + this.pstNameObj.id + "").value=this.innerText;document.getElementById("" + this.selObj.id + "").style.display="none";" + (this.callMethod == null ? "" : this.callMethod + ";"+ "'>" + root(i).attributes(1).value + "</div></a>";
            }

        }

        
else
        
{
            
for(var i=0;i<root.length;i++)
            
{
                
                outHTML 
+= "<a href='javascript:void(0)'><div style='height:20px;width:182px;text-decoration:none;color:#333;' onmouseover='this.style.backgroundColor="#98CDCD"' onmouseout='this.style.backgroundColor=""' id="li_" + root[i].attributes[this.idIndex].value + "" onclick='document.getElementById("" + this.txtObj.id + "").value=this.textContent;document.getElementById("" + this.pstIdObj.id + "").value=this.id.substring(this.id.indexOf("_")+1,this.id.length);document.getElementById("" + this.pstNameObj.id + "").value=this.textContent;document.getElementById("" + this.selObj.id + "").style.display="none";" + (this.callMethod == null ? "" : this.callMethod + ";"+ "'>" + root[i].attributes[this.txtIndex].value + "</div></a>";
                
            }

        }

        
//alert(this.callMethod);
        if(outHTML == "")
        
{
            outHTML 
= "<br/>";
        }

        i
= i==0 ? 1 : i;
        
this.selObj.innerHTML = outHTML;
    
    
//当对outHTML中写的onclick事件中的代码有一些特列操作时,比如创建新对象,或是给创建新事件等等,总之创建新的html element的话,采用inserAdjacentHTML方法替换innerHTML.
        //this.selObj.insertAdjacentHTML("afterBegin",outHTML);
        this.selObj.style.position="absolute";
        
this.selObj.style.height = 20 * i > 200 ? 200 : 20 * i;
        
this.selObj.style.display = "";
    }

    

}

 调用说明:

a.首先您可以先通过服务器端脚本输出获得xmldocument供 inputSelection使用.

比如使用asp.net,asp,或php

也可以使用xmlhttp或xmldom直接获取数据提供页输出的xml(或字串并自己转换为xml)

本来这步操作,我可以加在 inputSelection 类里的,但是我的页面是由服务器在xslt输出html时生成的xml串,所以将获提xmldomcumnet的过程分离出来了.

 

          var ns4 = (document.layers) ? true : false;
          
var ie4 = (document.all) ? true : false;
          
var ServerStr="<xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>root<xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>";
          
<xsl:for-each select="//CurrentGame/Server">
        ServerStr 
+= "<xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>Server id="<xsl:value-of select="./@ServerID"/>" name="<xsl:value-of select="./@Name"/>" /<xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>";
          
</xsl:for-each>
          ServerStr 
+= "<xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>/root<xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>";


          
if(ie4)
          
{
         
var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
              xmlDoc.async 
= false;
          xmlDoc.loadXML(ServerStr);

          }

          
else
          
{



              Node.prototype.selectNodes
=function(xPath)
          
{
              
var xresult=this.evaluate(xPath,this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
              
var nod=null,nods=[],k=0;
              
while((nod=xresult.iterateNext())!=null)
                  
{
                      nods[k
++]=nod;
                  }

                  
return nods;
              }


          XMLDocument.prototype.loadXML 
= function(xmlString)
              
{
              
var childNodes = this.childNodes;
              
for (var i = childNodes.length - 1; i <xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>= 0; i--)
                  
this.removeChild(childNodes[i]);

                  
var dp = new DOMParser();
                  
var newDOM = dp.parseFromString(xmlString, "text/xml");
                  
var newElt = this.importNode(newDOM.documentElement, true);
                  
this.appendChild(newElt);
              }
;

          
var xmlDoc=document.implementation.createDocument('','',null);
              xmlDoc.async
=0;

          xmlDoc.loadXML(ServerStr);

          }

 

b,接下来,页面上按位置摆放您的html element.

 

<input type="hidden" id="ServerID" value="" onchange="alert('tst');" />
              
<input type="hidden" id="ServerName" />
              
<div class="div2">
                
<span style=" margin:2px 0 0 15px">
                  
<table border="0" width="100%" id="tabContainer" cellspacing="0" cellpadding="0">
                    
<tr>
                      
<td rowspan="2" valign="top">
                      Select Your Server To Buy Final Fantasy XI
&nbsp;Gil</td>
                      
<td width="200">
                        
<input id="tFirstC" class="inp2" maxlength="20" style="cursor:default;" size="20" onclick="removeAll()" onkeyup="removeAll()" />
                      
</td>
                    
</tr>
                    
<tr>
                      
<td>
                        
<div id="divContainer" style="overflow-x:hidden;overflow-y:auto;text-align:left;line-height:150%;width:180px;height:200px;font-weight:0;font-size: 12px;color:#333333;margin: 0px;padding: 4px;z-index: 1; border-left:1px solid #336699;border-bottom:1px solid #336699;border-right:1px solid #336699;border-top:1px solid #336699;background-color: white;display:none;" />
                      
</td>
                    
</tr>
                  
</table>
                
</span>
              
</div>

 

c. 在上一步看到, input onkeyup时触发了removeAll方法. 实际是清除模拟select option的div.并且重新动态加载.

这与ajax有区别, 因为所需数据在页面加载时已全加载到string里,或者说又加载到了xmldom里.不需要再次到服务器端请求.

在removeAll方法里, 实例化 inputSelection,并进行初始化和进行清除及option item重建.

 

          function removeAll()
          
{

          
var sel = new inputSelection();
          sel.txtObj 
= document.getElementById("tFirstC");
          sel.selObj 
= document.getElementById("divContainer");
          sel.xd     
= xmlDoc;
          sel.selXPath 
= "//Server";
          sel.selAttributeName 
= "name";

          sel.pstIdObj 
= document.getElementById("ServerID");
          sel.pstNameObj 
= document.getElementById("ServerName");

          sel.idIndex 
= 0;
          sel.txtIndex 
= 1;

          sel.callMethod 
= "goURL()";
          sel.clearSEL();
          sel.reBuildSEL();

          }

 

d,最后一步,当页面点击其它位置时,隐藏div

 <body onclick="hideSelection(event)">

          function hideSelection(e)
          {
          var objx=document.getElementById("divContainer");
          var cobj=document.getElementById("tFirstC");
         
          var eobj= e.srcElement ? e.srcElement : e.target;
          if(eobj.id != cobj.id)
              objx.style.display="none";
          }

 

这个东西到现在用起来,还不是很方便,即移植麻烦了一点,等有空时,我把xml数据获取的部分也一起写到inputSelection里.

欢迎进行改进.和提出bug.谢谢.

posted on 2007-11-22 21:01  RedSoft  阅读(6028)  评论(1编辑  收藏  举报