javascript省市地区联动【素材】

资源源码下载地址:http://download.csdn.net/source/2689287

 

最新版本请到https://github.com/oxcow/ProvCitySelected下载。

 

利用js读取xml文件,通过xpath表达式获取所要数据,封装实现联动菜单。

整个过程使用OOP思想进行处理。主要包含5个对象:

  1. HtmlSelect对象。该对象为页面下拉标签对象;
  2. ProvinceAndCityLink对象。该对象为联动菜单基类对象。
  3. Province对象。该对象继承自ProvinceAndCityLink对象,为 下拉菜单对象。
  4. City对象。该对象继承自ProvinceAndCityLink对象,为 下拉菜单对象。
  5. Area对象。该对象继承自ProvinceAndCityLink对象,为地区 下拉菜单对象。

类图如下:javascript省市地区联动【素材】

主代码如下:/** * html select 标签类 * * @param {string} * sId 标签id * @param {string} * sName 标签 name * @param {string} * sVal 标签值 * @constructor * @returns {HtmlSelect} */ function HtmlSelect(sId, sName, sVal) { this.id = sId; this.name = sName; this.val = sVal; this.select = this.createSelect_(); } /** * 创建select元素 * @private * @returns {Element} select element */ HtmlSelect.prototype.createSelect_ = function() { var oSelect = document.createElement("select"); oSelect.setAttribute("id", this.id); oSelect.setAttribute("name", this.name); return oSelect; }; /** * 创建并添加 option 元素 * * @param {string} * sVal option 元素 value * @param {string} * sText option 元素 显示值 * @returns {Element} option element */ HtmlSelect.prototype.addOption = function(sVal, sText) { /** * 创建option方法1<br/> * 使用该方法IE6/FF下,默认selected不会出现错位 */ var option = document.createElement("option"); option.appendChild(document.createTextNode(sText)); option.setAttribute('value', sVal); if (this.val && sVal == this.val) { option.setAttribute('selected', 'selected'); } this.select.appendChild(option); /** * 创建option方法2<br/> * 使用该方法IE6下,默认selected会出现错位 */ // var option = null; // if (this.val && sVal == this.val) { // option = new Option(sText, sVal, true, true); // } else { // option = new Option(sText, sVal, false, false); // } // try { // this.select.add(option, null); // standards compliant // } catch (ex) { // this.select.add(option); // IE only // } /** * 创建option方法2<br/> * 使用该方法IE6下,默认selected会出现错位 */ // var option = document.createElement("option"); // option.value = sVal; // option.text = sText; // if (this.val && sVal == this.val) { // option.setAttribute('selected', 'true'); // } // //this.select.appendChild(option);IE6下此时不可用appendChild添加 // try { // this.select.add(option, null); // standards compliant // } catch (ex) { // this.select.add(option); // IE only // } }; /** * 清除 select 元素下所有的 option 元素 * */ HtmlSelect.prototype.cleanOptions = function() { if (this.select && this.select.options.length != 0) { for ( var i = this.select.options.length - 1; i >= 0; i--) { this.select.remove(this.select.options[i]); } } }; /** * 显示select标签在页面中 * * @param {string} * offset select元素父节点id */ HtmlSelect.prototype.showHtml = function(offset) { var op = document.getElementById(offset); op.appendChild(this.select); }; /** * 省市地区联动菜单类 * * @param {string} * sOffset 位置 * @param {string} * sName 菜单名 * @param {string} * sVal 菜单值 * @constructor * @returns {ProvinceAndCityLink} */ function ProvinceAndCityLink(sOffset, sName, sVal) { this.xml = loadxml(); this.offset = sOffset; this.id = "id_" + (new Date()).getTime(); this.name = sName; this.val = sVal; /** * @type {HtmlSelect} */ this.htmlSelect = new HtmlSelect(this.id, this.name, this.val); } /** * 初始化数据并显示在页面指定元素中 * * @param {string} * xPath xPath表达式 */ ProvinceAndCityLink.prototype.init = function(xPath) { var xmlData = this.xml.documentElement.selectNodes(xPath); if (!this.val && xmlData[0]) {// 如果没有默认值,则将第一个元素设置为默认值 this.val = xmlData[0].getAttribute("name"); this.htmlSelect.val = this.val; } for ( var i = 0; i < xmlData.length; i++) { this.htmlSelect.addOption(xmlData[i].getAttribute("name"), xmlData[i].getAttribute("name")); } this.htmlSelect.showHtml(this.offset); }; /** * 联动菜单onchange事件 * * @param {string} * xPath 新数据 xPath 表达式 * @returns */ ProvinceAndCityLink.prototype.change = function(xPath) { var oLink = ProvinceAndCityLink["link_" + this.id];// 获取onchange方法的绑定对象 oLink.htmlSelect.cleanOptions(); var sXpath = oLink.xPath.replace("&var", this.value);// 替换xPath中的变量部分 var xmlData = oLink.xml.documentElement.selectNodes(sXpath); for ( var i = 0; i < xmlData.length; i++) { oLink.htmlSelect.addOption(xmlData[i].getAttribute("name"), xmlData[i].getAttribute("name")); } var oLinkedLink = ProvinceAndCityLink["link_" + oLink.id];// 获取被绑定对象onchange绑定的对象 if (oLinkedLink) { oLinkedLink.htmlSelect.cleanOptions(); var data = xmlData[0].childNodes; for ( var j = 0; j < data.length; j++) { if (data[j].nodeType == 1) {// ELEMENT_NODE oLinkedLink.htmlSelect.addOption(data[j] .getAttribute("name"), data[j].getAttribute("name")); } } } }; /** * 省份下拉对象 * * @param {string} * sOffset 显示位置 * @param {string} * sName 变量名 * @param {string} * sVal 变量值 * @constructor * @extends {ProvinceAndCityLink} * @returns {Province} */ function Province(sOffset, sName, sVal) { ProvinceAndCityLink.call(this, sOffset, sName, sVal); this.xPath = "//province"; this.init(this.xPath); } Province.prototype = new ProvinceAndCityLink(); /** * 省市联动 * * @param {City} * oCity 联动市对象 */ Province.prototype.linkCity = function(oCity) { oCity.xPath = "//province[@name='&var']/city"; ProvinceAndCityLink["link_" + this.id] = oCity;// 指定当前province绑定的city this.htmlSelect.select.onchange = this.change; if (this.val) { var sXpath = oCity.xPath.replace("&var", this.val); oCity.init(sXpath); } }; /** * 市下拉对象 * * @param {string} * sOffset 显示位置 * @param {string} * sName 变量名 * @param {string} * sVal 变量值 * @param {boolean|undefined|null} * isInit * <ul> * 是否初始数据。默认为false。 * <li>如果只是构造单独的市下拉菜单,则需要设置该变量为true</li> * <li>如果是构造联动菜单,则需要将该变量设置为false</li> * </ul> * @constructor * @extends {ProvinceAndCityLink} * @returns {City} */ function City(sOffset, sName, sVal, isInit) { ProvinceAndCityLink.call(this, sOffset, sName, sVal); this.xPath = "//city"; if (isInit) { this.init(this.xPath); } } City.prototype = new ProvinceAndCityLink(); /** * 市区联动 * * @param {Area} * oArea 区对象 */ City.prototype.linkArea = function(oArea) { oArea.xPath = "//city[@name='&var']/country"; ProvinceAndCityLink["link_" + this.id] = oArea;// // 指定当前city绑定的area this.htmlSelect.select.onchange = this.change; if (this.val) { oArea.htmlSelect.cleanOptions(); var sXpath = oArea.xPath.replace("&var", this.val); oArea.init(sXpath); } }; /** * 地区下拉对象 * * @param {string} * sOffset 显示位置 * @param {string} * sName 变量名 * @param {string} * sVal 变量值 * @param {boolean|undefined|null} * isInit * <ul> * 是否初始数据。默认为false。 * <li>如果只是构造单独地区下拉菜单,则需要设置该变量为true</li> * <li>如果是构造联动菜单,则需要将该变量设置为false</li> * </ul> * @constructor * @extends {ProvinceAndCityLink} * @returns {Area} */ function Area(sOffset, sName, sVal, isInit) { ProvinceAndCityLink.call(this, sOffset, sName, sVal); this.xPath = "//country"; if (isInit) { this.init(this.xPath); } } Area.prototype = new ProvinceAndCityLink();

页面调用html代码:<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>省市区联动菜单</title> <mce:script type="text/javascript" src="loadxml.js" mce_src="loadxml.js"></mce:script> <mce:script type="text/javascript" src="C_area.js" mce_src="C_area.js"></mce:script> <mce:script type="text/javascript"><!-- window.onload = function() { //单独取省(无默认值) var singleProN = new Province('single_pro_n', 'sp1'); //单独取省(有默认值) var singleProY = new Province('single_pro_y', 'sp2', '吉林省'); //单独取市(无默认值) var singleCityN = new City('single_cit_n', 'sc1', '', true); //单独取市(有默认值) var singleCityY = new City('single_cit_y', 'sc2', '天津辖区', true); // 信息量大,因此在加载的时候比较慢,不过FF相对于IE比较快 //单独取地区(无默认值) var singleAreaN = new Area('single_area_n', 'sa1', '', true); //单独取地区(有默认值) var singleAreaY = new Area('single_area_y', 'sa2', '海淀区', true); //省市联动(无默认值) var pcProN = new Province('pc_p_n', 'pcp1'); var pcCityN = new City('pc_c_n', 'pcc1'); pcProN.linkCity(pcCityN); //省市联动(有默认值) var pcProY = new Province('pc_p_y', 'pcp2', "江苏省"); var pcCityY = new City('pc_c_y', 'pcc2', "常州市"); pcProY.linkCity(pcCityY); //市地区联动(无默认值) var caCityN = new City('ca_c_n', 'cac1', '', true); var caAreaN = new Area('ca_a_n', 'caa1'); caCityN.linkArea(caAreaN); //市地区联动(有默认值) var caCityY = new City('ca_c_y', 'cac2', "唐山市", true); var caAreaY = new Area('ca_a_y', 'caa2', '丰南区'); caCityY.linkArea(caAreaY); //省市地区联动(无默认值) var lp = new Province('lp', 'lp'); var lc = new City('lc', 'lc'); var la = new Area('la', 'la', '', false); lp.linkCity(lc); lc.linkArea(la); //省市地区联动(有默认值) var lp1 = new Province('lp1', 'lp1', '湖南省'); var lc1 = new City('lc1', 'lc1', '湘潭市'); var la1 = new Area('la1', 'la1', '', false); lp1.linkCity(lc1); lc1.linkArea(la1); } // --></mce:script> </head> <body> <fieldset><legend>单独取省</legend> 无默认值: <span id="single_pro_n"></span> 有默认值: <span id="single_pro_y"></span></fieldset> <br /> <fieldset><legend>单独取市</legend> 无默认值: <span id="single_cit_n"></span> 有默认值: <span id="single_cit_y"></span></fieldset> <br /> <fieldset><legend>单独取地区</legend> 无默认值: <span id="single_area_n"></span> 有默认值: <span id="single_area_y"></span></fieldset> <br /> <fieldset><legend>省市联动</legend> 无默认值: <span id="pc_p_n"></span><span id="pc_c_n"></span> 有默认值: <span id="pc_p_y"></span><span id="pc_c_y"></span> </fieldset> <br /> <fieldset><legend>市地区联动</legend> 无默认值: <span id="ca_c_n"></span><span id="ca_a_n"></span> 有默认值: <span id="ca_c_y"></span><span id="ca_a_y"></span> </fieldset> <br /> <fieldset><legend>市地区联动</legend> 无默认值: <span id="lp"></span><span id="lc"></span> <span id="la"></span> 有默认值: <span id="lp1"></span><span id="lc1"></span><span id="la1"></span></fieldset> </body> </html>