HTML 只提供了文本框和下拉列表框,没有提供 ComboBox 控件。虽然可以通过并排显示文本框和下拉列表框,并以脚本控制其关联的方法实现,但显示效果的确不理想。于是大家都想办法解决。综合了一下,现有的实现方法有两种思路:
1、用文本框加 Img 或 div 的方法,在点击时通过脚本控制某个层的显示状态。优点是可定义非常好的显示效果,也可实现非常复杂的功能。比如和数据库关联,显示树型的结构或多列的记录结构等。缺点是太复杂,不容易使用控制。
2、用文本框加下拉列表框实现,通过CSS将两个控件组合成 ComboBox 的外观,再用脚本实现联动。优点是简单易用,缺点是只能显示单行的列表,不能实现复杂的功能。
考虑到常用的功能,还是用第 2 种方法较为方便。在网上找了一些,虽然实现了这个效果,但使用起来比较麻烦。比如页面上有很多个这样控件时,工作量就太大了,而且维护修改起来不太方便。还是自己动手吧。
如果网站上有十个网页需要用到 ComboBox 控件,每个页面上又同时有十个存在,我想总不能一个一个的写一百遍吧?而且每一个的内容、宽度、ID都不同,即使将代码复制过去还需要大量的修改,这样的工作量可想而知。所以,这里的关键是如何将其组件化,以使在使用的时候最方便化,并且在修改时只修改组件即可。
那么如何组件化呢?自然而然想到了 HTC !
先来看看最终效果:
实现思路:ComboBox 控件的主要部分还是文本框,下拉列表框只是提供一个侯选的列表。所以我们以文本框为主,由 HTC 负责为其添加下拉列表框。使用时只要为文本框指定一个 combobox 的样式,再多写一个以逗号分隔的字符串作为下拉列表的内容就行了。如:
这个 combobox 样式定义为:
behavior:url(combobox.htc);
}
combobox.htc 内容如下:
<public:attach event="ondocumentready" onevent="init()" />
<public:property name="items"/>
<script type="text/javascript">
function init(){
if(items!=null){
items = items.replace(/(^s*)|(s*$)/g, "");
if (items != '') {
var arritem = items.split(',');
var selcon = document.createElement('select');
selcon.options.add(document.createElement("option"));
for(var i=0;i<arritem.length;i++){
var oOption = document.createElement("option");
var text = arritem[i];
if(text!='')text = text.replace(/(^s*)|(s*$)/g, "");
oOption.text = text;
oOption.value = text;
selcon.options.add(oOption);
}
selcon.style.position = 'absolute';
selcon.style.width = element.clientWidth + 20 + 'px';
selcon.style.clip = 'rect(auto auto auto ' + element.clientWidth + 'px)';
selcon.style.marginTop = '1px';
selcon.onchange=function(){
element.value = this.value;
element.select();
element.focus();
}
var parent = element.parentNode;
parent.insertBefore(selcon,element);
}
}
}
</script>
</public:component>
所有需要使用 ComboBox 的地方,使用普通的文本框即可,只要定义样式为 combobox,并且 items 属性不为空,它就会显示为下拉框。是不是很好用呀?! 而且再为它定义方法,就很容易实现列表的添加修改和删除功能了。
不过不要高兴的太早,HTC虽然是个好东西,但目前只有 IE 支持,也就是说,在非 IE 浏览器里显示的还是一个正常的文本框。
即然如此,那就用另外一种方法来解决兼容性问题。将下面的函数 ComboBox 在 window.onload 里调用即可,它会查找所有样式为 combobox 的文本框,并为它们添加下拉列表
var inputs = document.getElementsByTagName('input');
var comboboxs = new Array;
for(var i=0;i<inputs.length;i++){
var item = inputs[i];
if(item.type == 'text' && item.className == 'combobox')
comboboxs[comboboxs.length] = item;
}
if(comboboxs.length>0){
for(var i=0;i<comboboxs.length;i++){
var combobox = comboboxs[i];
var items = combobox.getAttribute('items');
if (items != null) {
items = items.replace(/(^s*)|(s*$)/g, "");
if (items != '') {
var arritem = items.split(',');
var selcon = document.createElement('select');
selcon.options.add(document.createElement("option"));
for (var j = 0; j < arritem.length; j++) {
var oOption = document.createElement("option");
var text = arritem[j];
if (text != '')
text = text.replace(/(^s*)|(s*$)/g, "");
oOption.text = text;
oOption.value = text;
selcon.options.add(oOption);
}
selcon.style.position = 'absolute';
selcon.style.width = combobox.clientWidth + 20 + 'px';
selcon.style.clip = 'rect(auto auto auto ' + combobox.clientWidth + 'px)';
if(document.all && window.external)selcon.style.marginTop = '1px';
selcon.onchange = function(){
var input = this.nextSibling;
input.value = this.value;
input.select();
input.focus();
}
var parent = combobox.parentNode;
parent.insertBefore(selcon, combobox);
}
}
}
}
};
实现过程:
怎样将文本框和下拉列表组合?
从理论上讲,只要将文本框和下拉列表框“紧紧的”并排挤在一起,并将下拉列表框的宽度减小到只留下一个下拉箭头,就和 ComboBox 的外观相同了。
但是,在 IE 中,下拉列表框的宽度减小了,点击下拉箭头展开的列表的宽度也跟着减小了,看不到内容了;而在非 IE 中,下拉列表框的宽度小于下拉箭头的宽度时就会隐藏下拉箭头,也不是我们想要的效果,所以不能用这种方法。
好在 CSS 中提供了 clip 的样式,它可以设置对象的可视区域,而且可视区域外的部分是透明的。这样就符合我们的要求了:将下拉列表框除下拉箭头外都隐藏起来!
但当把 clip 样式赋给下拉列表框后,却没有任何效果!原来, clip 样式只会在 position 样式的为 absolute ,即对象为绝对定位方式时才会起作用。
当赋予下拉列表框绝对定位样式后,需要把它的代码放在文本框代码之前,这样两个控件就会重合,再把下拉列表框的宽度定为文本框加上下拉箭头的宽度,再将文本框宽度的部分隐藏,就完美组合成了 ComboBox 控件。
清楚了组合方法,代码就容易写了。动态创建下拉列表框,插入文本框前面,再设置样式,添加事件以实现两个控件关联。上面两种方法的基本代码相同,都是这一过程。
HTC 方法在 IE6、IE7下测试通过;没有 IE 5.5 无法测试,IE 5.5 以下版本不支持 HTC
函数方法在 IE6、IE7、Opera 9.2、Firefox 1.5、Firefox 2.0下测试通过。

本文介绍了一种在HTML中实现ComboBox控件的方法,通过文本框与下拉列表的组合及脚本控制,实现在IE和非IE浏览器上的兼容显示。
576

被折叠的 条评论
为什么被折叠?



