為 SELECT.options 物件增加或刪除選項的方法在各瀏覽器中的支援情況不同
DOM 2 HTML 中分別定義了 HTMLSelectElement、HTMLOptionsCollection 和 HTMLOptionElement 介面,它們分別定義了若干屬性和方法來獲知或操作 SELECT 及 OPTION 元素。
HTMLSelectElement 介面定義了以下屬性及方法:
- length: 獲取 SELECT 元素中 OPTION 的數量;
- options: 獲取 SELECT 包含的 OPTION 元素集合,其返回值型別為 HTMLOptionsCollection;
- add(element, before): 向 SELECT 中新增一個 OPTION,引數 element 指定要新增的 OPTION 物件,before 指定了插入到哪個 OPTION 之前,如果值為 'null',則插入 SELECT 尾部;
- remove(index): 從 SELECT 中刪除一個 OPTION,引數 index 指定了要刪除的 OPTION 索引。
HTMLOptionsCollection 介面是一個 OPTION 節點列表,可以通過索引或某個 OPTION 節點的 name 或 id 屬性訪問該 OPTION。 它定義了 'length' 屬性,用來獲取當前 OPTION 節點列表的長度,作用同 HTMLSelectElement 的 'length' 屬性。
問題描述
各瀏覽器對標準的支援有差異,並且他們實現了非標準的新增和刪除 OPTION 元素的方法,在使用這些方法時,可能造成相容性問題。
造成的影響
如果使用了存在相容性問題的新增或刪除 OPTION 元素的方法,將可能導致指令碼異常,功能不可用。
受影響的瀏覽器
所有瀏覽器 |
---|
問題分析
除了標準提到的方法外,各瀏覽還實現了另外幾種新增、刪除 OPTION 元素的方法,各瀏覽器對這些方法的支援程度不一致。
非標準的新增 OPTION 的方法:
- select.add(option):SELECT 物件的方法,直接插入引數 option 到尾部;
- select.add(option, index):在指定的 OPTION 列表索引 index 之前插入引數 option;
- options.add(option, before):OPTION 節點列表(實現 HTMLOptionsCollection)的方法,效果同 HTMLSelectElement.add;
- options.add(option):同第一個方法;
- options.add(option, index):同第二個方法;
- options[index] = option:直接在 OPTION 節點列表上新增元素。
非標準的刪除 OPTION 的方法:
- select.remove(option):SELECT 物件的方法,刪除引數指定的 OPTION 物件;
- options.remove(index):OPTION 節點列表的方法,同 HTMLSelectElement.remove;
- options.remove(option):同第一個方法;
- options[index] = null:直接在 OPTION 節點列表上設定元素為 null。
-
分析以下程式碼:
- <styletype="text/css">select {height:100px;}</style>
- <table>
- <tbody>
- <tr>
- <td>
- <selectid="s1"multiple="multiple">
- <optionvalue="1">111</option>
- <optionvalue="2">222</option>
- </select>
- </td>
- <td>
- <selectid="s2"multiple="multiple">
- <optionvalue="1">111</option>
- </select>
- </td>
- <td>
- <selectid="s3"multiple="multiple">
- <optionvalue="1">111</option>
- <optionvalue="2">222</option>
- </select>
- </td>
- <td>
- <selectid="s4"multiple="multiple">
- <optionvalue="1">111</option>
- </select>
- </td>
- <td>
- <selectid="s5"multiple="multiple">
- <optionvalue="1">111</option>
- </select>
- </td>
- </tr>
- <tr>
- <td><buttontype="button"onclick="remove(1);">select.remove(index)</button></td>
- <td><buttontype="button"onclick="remove(2);">select.remove(option)</button></td>
- <td><buttontype="button"onclick="remove(3);">options.remove(index)</button></td>
- <td><buttontype="button"onclick="remove(4);">options.remove(option)</button></td>
- <td><buttontype="button"onclick="remove(5);">options[index] = null</button></td>
- </tr>
- </tbody>
- </table>
- <divstyle="border:2px solid;padding:3px;width:800px;"id="info"></div>
- <script type="text/javascript">
- function $(id){return document.getElementById(id);}
- function newOpt(text, val){returnnew Option(text, val);} 1
- function info(method, msg){$("info").innerHTML += "<strong>" + method + "</strong> : " + msg + "<br />";}
- //建立n個 OPTION 物件
- var opt1 = newOpt("select.add(option, null)", 2),
- opt2 = newOpt("select.add(option)", 2),
- opt3 = newOpt("options.add(option, null)", 2),
- opt4 = newOpt("options.add(option)", 2),
- opt5 = newOpt("options[index] = option", 2),
- opt6 = newOpt("select.add(option, option)", 2),
- opt7 = newOpt("select.add(option, index)", 2),
- opt8 = newOpt("options.add(option, option)", 2),
- opt9 = newOpt("options.add(option, index)", 2),
- s1 = $("s1"),
- s2 = $("s2"),
- s3 = $("s3"),
- s4 = $("s4"),
- s5 = $("s5");
- //使用n種方法新增 OPTION 到 SELECT 中
- try { s1.add(opt1, null); } catch(e) { info("select.add(option, null)", e) }
- try { s2.add(opt2); } catch(e) { info("select.add(option)", e) }
- try { s3.options.add(opt3, null); } catch(e) { info("options.add(option, null)", e) }
- try { s4.options.add(opt4); } catch(e) { info("options.add(option)", e) }
- try { s5.options[1] = opt5; } catch(e) { info("options[index] = option", e) }
- try { s1.add(opt6, s1.lastChild); } catch(e) { info("select.add(option, option)", e) }
- try { s1.add(opt7, 1); } catch(e) { info("select.add(option, index)", e) }
- try { s3.options.add(opt8, s3.lastChild); } catch(e) { info("options.add(option, option)", e) }
- try { s3.options.add(opt9, 1); } catch(e) { info("options.add(option, index)", e) }
- function remove(type){
- var method = "";
- try {
- switch(type) {
- case 1 :
- method = "s1.remove(0)";
- break;
- case 2 :
- method = "s2.remove(s2.firstChild)";
- break;
- case 3 :
- method = "s3.options.remove(0)";
- break;
- case 4 :
- method = "s4.options.remove(s4.firstChild)";
- break;
- case 5 :
- method = "s5.options[1] = null";
- break;
- }
- eval(method);
- } catch (e) {
- info(method, e);
- }
- }
- </script>
上述程式碼首先使用了標準及非標準方法向各 SELECT 元素中添加了 OPTION,然後點選各按鈕使用各種刪除方法刪除 OPTION, 根據丟擲的異常資訊,我們可以辨別出哪些方法在瀏覽器中不支援,彙總測試結果如下表:2
type method IE6 IE7 IE8(Q) IE8(S) Opera Firefox Chrome Safari add OPTION select.add(option, null) N Y Y Y select.add(option, option) N Y Y Y select.add(option, index) Y Y N N3 select.add(option) Y Y N Y options.add(option, null) N Y N4 N4 options.add(option, option) N Y N N options.add(option, index) Y Y Y Y options.add(option) Y Y Y Y options[index] = option Y Y Y Y remove OPTION select.remove(index) Y Y Y Y select.remove(option) Y Y Y Y options.remove(index) Y Y N Y options.remove(option) Y Y N Y options[index] = null Y Y Y Y 注1:這裡使用 new Option(text, value) 的方式建立新的 OPTION 物件,也可以使用 new Option([text[, value[, defaultSelected[, selected]]]]) 或 document.createElement("option") 建立。建立 OPTION 物件的方法於本文測試結果無影響。
注2:Y 表示支援該方法,N 表示不支援。
注3:並沒有實現在指定索引前插入 OPTION 的功能,只是實現了向 SELECT 元素尾部插入元素。
注4:並不是向 SELECT 元素的尾部插入 OPTION,而是插入到 SELECT 的首部。
解決方案
1. 在新增 OPTION 元素時
- 如果需要向指定索引前插入 OPTION,可以使用 options.add(option, index);
- 如果需要向 SELECT 尾部新增 OPTION,可以使用 options.add(option);
- 如果需要向指定索引處新增(或更改) OPTION,可以使用 options[index] = option。
2. 在刪除 OPTION 元素時
- 如果想刪除指定索引處的 OPTION 元素,可以使用 select.remove(index) 或 options[index] = null;
- 如果想刪除某個指定的 OPTION 元素,可以使用 select.remove(option);
- 如果想刪除 SELECT 中所有 OPTION,可以使用 select.length = 0 或 options.length = 0。