2010/09/14

[JavaScript] 在<select>中替換<option>的方式(KB 276228)

在網頁的設計中, 常會用到連動式的下拉式選單, 或是因為某個事件, 而置換掉下拉式選單中的選項.
但在 Microsoft 官網有提到一個問題: http://support.microsoft.com/kb/276228/zh-tw 
也就是, 不要用 innerHTML 去置換 <select> 中的 <option>.
以 jQuery 的用法來說, 很多人會使用以下的寫法:
// clear all options
$("#myFavorList").find('option').remove();
// append new options
$("#myFavorList").append('<option value=1>Yahoo</option>');
$("#myFavorList").append('<option value=2>PCHome</option>');
$("#myFavorList").append('<option value=3>Code Project</option>');
以下兩張圖是在 IE7 上執行的結果:
Before change --> After change

可以發現, 如果原本的選項長度不長(ex: N/A), 利用 jQuery 的 .append() 會造成顯示上的問題. (不過 IE8 看不到這個效果)
因為 jQuery 的 .append() 使用到了 innerHTML 去設定內容.
若要解決這個顯示上的問題,  我目前知道的是以下三種做法:

  1. 如 KB 所建議的, 將置換的層級拉高, 連 <select> 也換掉.
  2. 在選項設計上, 一開始就要給一個最長的選項, 強迫瀏覽器事先呈現足夠長度的選項.
    但這在實務上不見得可行, 因為一般會想要動態置換下拉式選單的選項, 其背後的資料就是不固定的.
  3. 使用  KB 說明的傳統做法: (這邊我包裝了一下 option 的資料)
    var lstMyFavorList = document.getElementById("myFavorList");
    var myOptions = {
        1 : 'Yahoo', 
        2 : 'PCHome',
        3 : 'Code Project' 
    }; 
    $.each(myOptions, function(val, text) { 
        var myOption = document.createElement("OPTION");
        myOption.text = text;
        myOption.value = val;
        lstMyFavorList.add(myOption);
    }); 
    結果就會如下圖正常地依選項的資料長度做較佳的呈現:
    Use traditional DOM

後記:
在測試上, 目前 IE8 或 FireFox 其實都可以正常呈現 innerHTML 後的選項, 有問題的是 IE7 .
但以開發者的角度來說, 不太能夠要求所有的使用者都使用我們希望的瀏覽器來瀏覽網頁, 所以還是要慎用可能會造成問題的寫法.

沒有留言: