采用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
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.谢谢.