代码:
/*
 *
 * oSelect v1.0  联动列表类
 *
 * Author: Winder
 * Email: [email protected]
 * Date: 2006/04/30
 * Version: 1.0
 *
 * 调用接口:
 *
 * addOption(text, value, selected) 增加列表选项数据
 * addOptionsArray(arrOptions) 以数组方式批量载入列表选项
 * Link(Select) 联选项到子列表对象
 * Create(ID) 创建列表对象
 * loadXML(xmlFile) 加载XML文件为列表数据
 *
 * 示例:
 * 见后。
 *
 */function oSelect(name, id, action, Options, xmlOptions){
this.name = name; // 列表对象名称
this.id = id; // 列表位置 this.Options = new Array(); //列表选项,多维数组
this.xmlOptions = xmlOptions; //列表选项,加载XML数据 this.index = -1; // 对象关联层次,设置为-1,为使得第一个选项为0
this.Links = new Array(); // 选项关联对象 this.Created = false; // 列表创建标志:默认--未创建;1--原来不存在,新建立;2--原来存在,增加选项的
this.Select = null; // 列表对象
this.parent = null; // 父列表对象
this.child = null; // 子列表对象 this.action = action; // 处理列表对象选项
if ( Options )
this.addOptionsArray( Options );
// 从XML文件中加载选项数据
if ( xmlOptions )
this.loadXML( xmlOptions );
}// 增加选项数据
oSelect.prototype.addOption = function(text, value, selected){
// text 选项文本
// value 选项值
// selected 选项选中状态
if ( !text ) return;
// 变量判断:存在,为空,为0,为false
value = ( value ) ? value : text;
selected = ( selected && selected != "false" ) ? true : false;
this.index += 1; // 关联索引
this.Options[this.index] = Array(text, value, selected);
}
// 以数组方式批量载入列表选项
oSelect.prototype.addOptionsArray = function( arrOptions ){
if ( typeof(arrOptions)=="string" )
arrOptions = new Array(arrOptions);
for ( var i=0; i<arrOptions.length; i++ ){
var aOption = arrOptions[i];
if ( typeof(aOption)=="string" )
aOption = new Array(aOption);
var aText = aOption[0]; // 选项文本
var aValue = aOption[1]; // 选项值
var aSelected = aOption[2]; // 选项选中状态
// 增加选项数据
this.addOption( aText, aValue, aSelected );
// 下一级列表数组
var rOption = aOption[3];
if ( rOption ){
// name
var oID = this.id;
var oAction = this.action;
var _Select = new oSelect( "", oID, oAction );
_Select.addOptionsArray( rOption );
// 关联子列表对象
this.Link( _Select );
}
}
}
// 关联选项到子列表对象
oSelect.prototype.Link = function( oS ){
if ( !oS ) return;
this.Links[this.index] = oS;
}
// 创建列表对象
oSelect.prototype.Create = function( id ){
// 列表位置
this.id = ( id ) ? id : this.id; // 列表名称
var name = this.name;
// 判断该名称对象是否存在
// 已经存在,则采用该列表对象,不再新建立
if ( name && typeof(name)=="object" && name.tagName=="SELECT" ){
var oS = name;
this.Created = 2;
}else if( name && document . getElements ByName( name ) && document . getElements ByName( name )[0] ){
var oS = document . getElements ByName( name )[0];
this.Created = 2;
}else{
var S = "<SELECT";
if ( name )
S += " name='" + name + "'";
S += ">";
S += "</SELECT>";
var oS = document.createElement( S ); // 确定对象位置
if ( typeof( this.id ) == "string" ){
// 得到位置对象
this.id = document.getElementById ( this.id );
}
if( this.id ){
// 在指定位置对象最后插入列表对象
var objS = this.id.insertBefore( oS );
this.Created = 1;
}else if( this.parent && typeof(this.parent) == "object" ){
// 父列表对象存在,作为子列表对象,插入到父对象后面
var objS = this.parent.Select.parentNode.insertBefore( oS );
this.Created = 1;
}else{
// Void
}
} // 设定相关属性定义
// 该类没办法继承给onchange方法,暂且采用SELECT传递类对象
// * 注意 *
oS.__mSelect = this;
// 列表对象
this.Select = oS; // 绑定行为
oS.onchange = this.Change; // 添加列表选项
if ( this.Options.length > 0 )
this.createOptions( );
}// 清除子对象列表
oSelect.prototype.Remove = function(){
var obj = this;
if ( obj ){
// 循环删除下一级列表
var oChild = obj.child;
if ( oChild ){
oChild.Remove( );
} // 判断对象创建状态
// 列表对象已经存在,则先清楚原来列表对象
// 原来列表为:
// 1--原来不存在,新建的
// 2--原来存在,增加选项的
// 其它--还不存在
var isCreated = obj.Created;
if ( isCreated == 2 ){
// 原来存在,增加选项的,重置选项
var oSelect = obj.Select;
var oOptions = oSelect.options;
for ( var i = 0; i < oOptions.length; i ++ ){
var oOption = oOptions[i];
// 以__index属性判断选项是否为类创建
// alert( "oOption:" + oOption.outerHTML );
if ( oOption.__index >= 0 ){
oSelect.remove( i );
// oSelect.options[i] = null;
}
}
}else
// 原来不存在,新建的,则删除对象
obj.Select.removeNode(true);
}
}// 改变列表选项
oSelect.prototype.Change = function(){
// 取得SELECT对象
var sObj = this; // 取得类继承
var thisMe = this.__mSelect; // alert(thisMe.name);
// 获取选项索引  
// * 该处this为select对象
var sIndex = sObj.selectedIndex;
// 当前选项对象
var oOption = sObj.options[sIndex];
// 本类创建的选项索引
var oIndex = oOption.__index;
// alert("sIndex:" + sIndex + "|" + oIndex); // 执行指定函数
if ( thisMe.action ){
try
{
// 执行指定函数
thisMe.action ( sObj.options[sIndex].value );
}
catch ( e )
{
// Void
}
} // 清除子对象
var oChild = thisMe.child;
if ( oChild ){
oChild.Remove(  );
} // 该选项关联对象
var oLink = thisMe.Links[oIndex];
if ( oLink ){
// 设置子对象关联
thisMe.child = oLink;
oLink.parent = thisMe;
// 创建关联对象
oLink.Create();
}
}// 创建列表选项
oSelect.prototype.createOptions = function( ){
var Options = this.Options;
if ( !Options ) return;
if (typeof(Options) == "string")
Options = new Array( Options );
var oS = this.Select;
if ( !oS )
return;
for ( i=0; i<Options.length; i++ ){
var aOption = Options[i];
if ( !aOption ) continue;
if ( typeof(aOption)=="string" )
aOption = new Array(aOption);
var txtText = aOption[0]; //选项文本
var txtValue = aOption[1]; //选项值
txtValue = ( txtValue ) ? txtValue : txtText;
var bSelected = ( aOption[2] ) ? true : false;
var oOption = new Option(txtText.toString(), txtValue.toString());
// oOption.selected = true;
// 选项索引
oOption.__index = i;
oS.options.add(oOption);
oS.options[oS.length-1].selected = bSelected;
}
}

解决方案 »

  1.   

    // 加载选项XML文件
    oSelect.prototype.loadXML = function( xmlFile ){
    var oXml = new ECMXml( ); // 同步请求选项数据
    var oData = oXml.LoadXML( xmlFile );
    this.loadOptionsXML( oData );
    /*
    // 异步请求选项数据
    oXml.Ajax( xmlFile, this.loadOptionsXML, this );
    */
    }// 解析XML数据加载为选项
    oSelect.prototype.loadOptionsXML = function( xmlData, thisSelect ){
    var thisS = ( thisSelect ) ? thisSelect[0] : this;
    if ( !xmlData )
    return;
    var oRoot = xmlData.documentElement;
    if ( !oRoot )
    return;
    // 加载对象标志,用于对选项XML数据的分析规则
    // 1、必须先加载列表,才能加载选项
    // 2、子列表必须与某一选项关联,即鼻祖在加载某一选项后加载
    // 初始列表对象已经由类创建
    thisS._loadSelect = true;
    thisS._loadOption = false; // 加载数据
    thisS.loadOption( oRoot, thisS);
    }// 加载XML节点为选项数据
    oSelect.prototype.loadOption = function( oData, thisSelect ){
    var thisS = ( thisSelect ) ? thisSelect : this; if ( !oData ) return;
    var oTagName = oData.tagName;
    // 列表标签
    if ( oTagName == "SELECT" ){
    var oName = oData.getAttribute("name");
    var oID = oData.getAttribute("id");
    oID = ( oID ) ? oID : thisS.id ;
    var oAction = oData.getAttribute("action");
    oAction = ( oAction ) ? oAction : thisS.action;
    if ( thisS._loadSelect && !thisS._loadOption ){
    // 列表已经存在
    oName = ( oName ) ? oName : thisS.name ;
    thisS.name = oName;
    thisS.id = oID;
    thisS.action = oAction;
    }else{
    if ( thisS._loadOption ){
    // 已经存在选项,则关联到子列表
    var _Select = new oSelect( oName, oID, oAction );
    thisS.Link( _Select );
    thisS = _Select;
    thisS._loadSelect = true;
    thisS._loadOption = false;
    }else{
    // 新建立列表
    /* 这种情况应当是不允许存在,因为这样没办法把本类返回,未进一步严格测试。 */
    var _Select = new oSelect( oName, oID, oAction );
    thisS = _Select;
    thisS._loadSelect = true;
    thisS._loadOption = false;
    }
    }
    }
    // 选项标签
    if ( oTagName == "OPTION" ){
    if ( thisS._loadSelect ){
    // 列表已经存在,则加载选项
    var oText = oData.getAttribute("text");
    oText = ( oText ) ? oText : oData.text ;
    var oValue = oData.getAttribute("value");
    var oSelected = oData.getAttribute("selected");
    // 加载选项
    thisS.addOption( oText, oValue, oSelected );
    thisS._loadOption = true;
    }else{
    // 列表不存在,无法加载选项,忽略本节点
    }
    }
    // 递归读取子节点
    var oChilds = oData.childNodes;
    for (var i = 0; i < oChilds.length; i++) {
    var oChild = oChilds[i];
    thisS.loadOption( oChild, thisS );
    }
    }/*
     * XML 操作类
     * 引用并修改至FCKeditor中的FCKXml类
     * LoadXML(url) 以同步请求载入XML文件
     * LAjax(url, call) 以异步请求载入XML文件
     */
    function ECMXml()
    {
    this.Error = false ;
    }// 同步请求方式载入XML文件
    ECMXml.prototype.LoadXML = function( url )
    {
    this.url = url; var oXmlHttp = this.CreateXMLHttp( ); if ( !oXmlHttp )
    {
    this.Error = true ;
    return ;
    } oXmlHttp.open( "GET", this.url, false ) ; oXmlHttp.send( null ) ;

    if ( oXmlHttp.status == 200 || oXmlHttp.status == 304 )
    this.DOMDocument = oXmlHttp.responseXML ;
    else if ( oXmlHttp.status == 0 && oXmlHttp.readyState == 4 )
    {
    this.DOMDocument = this.CreateXMLDoc( ) ;
    // this.DOMDocument.async = false ;
    // this.DOMDocument.resolveExternals = false ;
    // this.DOMDocument.loadXML( oXmlHttp.responseText ) ;
    try{
    this.DOMDocument.load( this.url );
    }catch( e ){
    this.Error = true ;
    this.DOMDocument = null;
    }
    }
    else
    {
    this.Error = true ;
    alert( 'Error loading "' + this.url + '"' ) ;
    }
    return this.DOMDocument;
    }// 异步请求方式载入XML文件
    ECMXml.prototype.Ajax = function( url, call )
    {
    this.url = url;
    this.Error = false ;
    this.call = call;
    this.arguments = new Array();
    var j = 0;
    for ( i = 2; i < arguments.length; i ++)
        {
    this.arguments[j] = arguments[i];
    j += 1;
    }
    var varArguments = this.arguments; // return; var oXmlHttp = this.CreateXMLHttp( ); if ( !oXmlHttp )
    {
    this.Error = true ;
    return ;
    }
    this.oXmlHttp = oXmlHttp; oXmlHttp.onreadystatechange = function () {
    ECMXml._OnReadyStateChange(oXmlHttp, call, varArguments );
    }; oXmlHttp.open( "GET", this.url, true ) ; // 发送数据
    oXmlHttp.send( null );
    /*
    window.setTimeout(function () {
    oXmlHttp.send(null);
    }, 10);
    */
    }// 监听XML文档对象状态,响应请求事件
    ECMXml._OnReadyStateChange = function( xmlHttp, funCall )
    {
    if (xmlHttp.readyState == 4) {
    if (xmlHttp.status == 200) {
    // 额外参数传递
    var varArguments = arguments[2];
    funCall( xmlHttp.responseXML, varArguments);
    } else {
    // Void
    }
    }
    }// 创建XmlHttp请求
    ECMXml.prototype.CreateXMLHttp = function( )
    {
        try { return new ActiveXObject("Msxml2.XMLHTTP");    } catch(e) {}
        try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
        try { return new XMLHttpRequest();                   } catch(e) {}
        return null;
    }// 创建对象
    ECMXml.prototype.CreateXMLDoc = function( )
    {
        try { return new ActiveXObject("MSXML2.DOMDocument");    } catch(e) {}
        try { return new ActiveXObject("Microsoft.XmlDom");      } catch(e) {}
    try { return document.implementation.createDocument( '', '', null ); } catch(e) {}
        return null;
    }
    // 获取XML数据
    ECMXml.prototype.GetXml = function( )
    {
    return this.DOMDocument;
    }
      

  2.   

    // 使用例子<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE> oSelect v1.0 </TITLE>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <META NAME="Generator" CONTENT="EditPlus">
    <META NAME="Author" CONTENT="winder">
    <META NAME="Keywords" CONTENT="联动列表 类">
    <META NAME="Description" CONTENT="联动列表类">
    <script type="text/javascript" language="JavaScript 1.2" src="oSelect.js"></script>
    </HEAD><BODY><SELECT name="SNAME">
    <option value="OK">已经</option>
    </SELECT>
    <SELECT name="SNAME2">
    <option value="OK2">已经</option>
    </SELECT>
    <span id="SID">
    </span><script type="text/javascript" language="JavaScript 1.2">
    /*
     * 使用例子
     */
    /*
    // 数据定义方式一:
    var mySelect =
    [
    //格式:[选项, 选项值, 默认状态:true--选中]
    ['选项1.1', '1.1', false,
    [
    ['选项2.1', '2.1', true],
    ['选项2.2', '2.2', '',
    [
    ['选项3.1', '3.1', ''],
    ['选项3.2', '3.2', true]
    ]
    ],
    ['选项2.3', '2.3', '']
    ]
    ],
    ['选项1.2', '1.2', true],
    ['选项1.3', '1.3', '']
    ];
    */// 数据定义方式二:
    var mySelect = new Array();
    mySelect[0] = Array('选项1.1', '1.1', false);
    mySelect[0][3] = Array();
    mySelect[0][3][0] = Array('选项2.1', '2.1', true);
    mySelect[0][3][1] = Array('选项2.2', '2.2', '');
    mySelect[0][3][1][3] = Array();
    mySelect[0][3][1][3][0] = Array('选项3.1', '3.1', '');
    mySelect[0][3][1][3][1] = Array('选项3.2', '3.2', true);
    mySelect[0][3][2] = Array('选项2.3', '2.3', '');
    mySelect[1] = Array('选项1.2', '1.2', true);
    mySelect[2] = Array('选项1.3', '1.3');// 例子一
    // var S = new oSelect(SNAME, 'SID', mySelect);
    // S.Create( ); // 输出创建// 例子二
    /*
    var S = new oSelect('SNAME');
    var O = S.addOption("---", "");
    var O = S.addOption("Text", "Value");
    var S1 = new oSelect( 'SNAME2');
    var O1 = S1.addOption("选项2.1", "2.1");
    S.Link( S1 );
    S.action = isS; // 对象onchange 执行函数
    S.Create( "SID" ); // 输出创建
    */// 例子三
    /*
    var S = new oSelect('SNAME');
    S.addOptionsArray(mySelect); // 载入Select选项数组
    S.action = isS; // 对象onchange 执行函数
    S.Create( "SID" ); // 输出创建
    */// 例子四
    var S = new oSelect('SNAME');
    S.action = isS; // 对象onchange 执行函数
    S.loadXML( 'S.xml' + '?time=' + new Date().getTime() ); // 载入Select选项XML文件
    S.Create( "SID" ); // 输出创建function isS( s ){
    alert( s );
    }
    </script></BODY>
    </HTML>
      

  3.   

    to:y7967
    谢谢!另,
    由于:本论坛提示我,document . getElements ByName (去掉空格会给论坛带来伤害),
    所以,复制使用,需要将document . getElements ByName中的空格去除。希望:
    希望各位共同:
    1、完善功能;
    2、优化结构、性能;
    3、触类旁通,交流、讨论有关知识。
    S.xml的格式
    ===========================================
    <?xml version="1.0" encoding="gb2312" ?>
    <SELECT name="cit">
    <SELECT>
    <OPTION value="1.1" selected="true">选项1.1</OPTION>
    <OPTION value="1.2" text="选项1.2">
    <SELECT name="">
    <OPTION value="2.1" text="选项2.1" selected="false">
    <SELECT name="">
    <OPTION value="3.1" text="选项3.1" selected="false">
    </OPTION>
    <OPTION value="3.2">选项3.2</OPTION>
    <OPTION value="3.3" selected="true">选项3.3</OPTION>
    <OPTION value="3.4" selected="false">选项3.4</OPTION>
    </SELECT>
    </OPTION>
    <OPTION value="2.2" text="选项2.2">
    <SELECT name="">
    <OPTION value="3.2.1" text="选项3.2.1" selected="false">
    </OPTION>
    <OPTION value="3.2.2">选项3.2.2</OPTION>
    <OPTION value="3.2.3" selected="true">选项3.2.3</OPTION>
    <OPTION value="3.2.4" selected="false">选项3.2.4</OPTION>
    </SELECT>
    </OPTION>
    <OPTION value="2.3" selected="true">选项2.3</OPTION>
    <OPTION value="2.4" selected="true">选项2.4</OPTION>
    </SELECT>
    </OPTION>
    <OPTION value="1.3">选项1.3</OPTION>
    </SELECT>
    </SELECT>
      

  4.   

    下载地址:http://www.yhxjsj.gov.cn/Winder/oSelect.rar
      

  5.   

    这个不是一般人能看得懂的!看看这个吧http://community.csdn.net/Expert/topic/4745/4745332.xml?temp=.9202692
      

  6.   

    楼上,你那句话说的也太过了吧,其实原理很简单,用xpath选择id罢了
      

  7.   

    谢谢各位,大家能不能就其中的优化作一些探讨?
    To:JK_10000
    我也觉得有点长。
    因为提供了多个数据载入接口,导致方法比较多,能否:
    1、就实现方法上提供一些指导?
    2、就程序实现上和算法上提供一些优化的建议?
    谢谢!