先上效果图,可以做这样子的界面。当你还没选择省的时候是这样子的界面
如果选择的话,界面如下:
想不想拥有这样子的效果呢?不好意思,我好像植入广告了。
那么我们先写下HTML代码,这个是我们这个组件渲染的地方。如果这个组件比作是我们这些人的话,那么下面的代码就是我们的家,对不起,我想家了。
<div id='cascade'></div>
下面就是最重要的javascript代码了,我觉得我是用面向对象的写法写的,但不知是不是伪面向对象的。
我先创建一个对象先,其实这个是命名空间。
Mkey = {};
然后因为我们要处理浏览器兼容性的问题,应该当你的浏览器加载你的页面的时候就要去检测当前的用户代理是哪种。我的处理如下:
Mkey.browser = function() {
// 用户代理,即浏览器的版本
var ua = navigator.userAgent.toLowerCase();
var checkNav = function(reg) {
return reg.test(ua);
};
return {
isIE : checkNav(/msie/),
isChrome : checkNav(/\bchrome\b/)
}
}()
对于xml文件,我们可以用ajax去加载xml文件,所以我们再创建一个有关Ajax的方法如下:这个request最重要的是也是有关浏览器兼容的问题,ie总是来捣乱。
Mkey.Ajax = {};
Mkey.Ajax.requset = function(o) {
this.url = o.url || "";
var me = this;
var ieAjax = function() {
xmlDom = new ActiveXObject("Microsoft.XMLDOM");
xmlDom.async = "false"; // false 使用同步加载数据
xmlDom.load(me.url);
return xmlDom;
}, otherAjax = function() {
var xmlDom, xmlhttp = new window.XMLHttpRequest();
// false 使用同步加载数据
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {// 4 = "loaded"
if (xmlhttp.status == 200) {// 200 = OK
o.success(xmlhttp.response);
} else {
alert("Problem retrieving XML data");
}
}
};
xmlhttp.open("GET", me.url, false);
xmlhttp.send(null);
xmlDom = xmlhttp.responseXML;
return xmlDom;
}
return Mkey.browser.isIE ? ieAjax() : otherAjax();
};
我们可以用下面的代码获取xml ,然后用DOM来操作xml,声明下DOM不止可以用到HTML上面的。
var xmlDom = Mkey.Ajax.requset({
url : 'cities.xml'
});
做了很多辅助的工具后,这个就到我们的组件登场了。
Mkey.Cascade = function(config) {
this.xmlDom = config.xmlDom;
this.root = this.xmlDom.documentElement;
this.cofp = {};
// root 的孩子还是有点兼容性问题的 children or childNodes
this.nodeChild = 'child' + this.childNamePostfix();
}
Mkey.Cascade.prototype = {
render : function(ct) {
var ct = document.getElementById(ct);
this.onRender(ct);
this.cities = document.getElementById('cities');
},
onRender : function(ct) {
// 获取省份的结点,还有有关省份数组的长度
var provinceArr = this.root[this.nodeChild], plen = provinceArr.length, me = this;
this._dFragment = document.createDocumentFragment();
ct.innerHTML = '<select id="province"><option>请选择省</option></select><select id="cities"><option>请选择相应省下面的市</option></select>';
this.province = document.getElementById('province');
for (var i = 0; i < plen; i++) {
// 在chrome ie 的子节点有text结点和元素结点,所以要判断
// 我们有34个省份,所以这个要循环34次
if (this.isElementNode(provinceArr[i])) {
var name = provinceArr[i].getAttribute("name");
this.createOption(name, provinceArr[i]);
}
}
this.province.onchange = function() {
// 得到所选的province的名字
var provinceName = me.obtainSelOptionName();
me.cities.length = 1;
var cit = me.cofp[provinceName];
for (var i = 0; i < cit.length; i++) {
if (me.isElementNode(cit[i])) {
var name = cit[i].firstChild.nodeValue;
me.createOption(name);
}
}
me.cities.appendChild(me._dFragment);
};
this.province.appendChild(this._dFragment);
},
createOption : function(name, province) {
var op = document.createElement("option");
if (province)
this.cofp[name] = province[this.nodeChild];
op.appendChild(document.createTextNode(name));
this._dFragment.appendChild(op);
},
obtainSelOptionName : function() {
// 获取所选中的option
return this.province[this.province.selectedIndex].innerHTML;
},
isTextNode : function(el) {
return el.nodeType == 3 ? true : false;
},
isElementNode : function(el) {
return el.nodeType == 1 ? true : false;
},
childNamePostfix : function() {
return (Mkey.browser.isIE || Mkey.browser.isChrome) ? 'Nodes' : 'ren';
}
};
new Mkey.Cascade({xmlDom:xmlDom}).render('cascade');