HTML Select 控制行为

HTML Select control behavior

我正在尝试使 HTML Select 控件在单击(或打开)时显示与选择项目后显示的不同的字符串集。例如,打开时我希望看到 "one"、两个"、"three" 显示为选项。但是如果用户选择两个,我希望将“2”显示为所选项目。我的 onclick 处理程序使用长版本的字符串重新加载 Select 选项列表,onchange 处理程序使用短字符串重新填充控件,然后重新选择所选项目。这在 Firefox 中有效,但在 IE、Safari 或 Chrome。自从我上次在 JavaScript 中享受 编码乐趣 已经将近 10 年了。任何帮助将不胜感激。这是我的代码:

var selectedIndex = -1;
function onChanged() {
  //once selected, replace verbose with terse forms
  var myList = document.getElementById("myList");
  selectedIndex = myList.selectedIndex;
  var optionArray = ["One|1", "Two|2", "Three|3"];
  myList.options.length = 0;
  for (var option in optionArray) {
    var pair = optionArray[option].split("|");
    var newOption = document.createElement("option");
    newOption.value = pair[1];
    newOption.innerHTML = pair[1];
    myList.options.add(newOption);
  }
  myList.selectedIndex = selectedIndex;
}

function onClicked() {
  var myList = document.getElementById("myList");
  var optionArray = ["1|One", "2|Two", "3|Three"];
  myList.options.length = 0;
  for (var option in optionArray) {
    var pair = optionArray[option].split("|");
    var newOption = document.createElement("option");
    newOption.value = pair[1];
    newOption.innerHTML = pair[1]; 
    myList.options.add(newOption);
  }
  if (selectedIndex > -1)
    myList.selectedIndex = selectedIndex;
}
<select id="myList" onchange="onChanged()" onclick="onClicked()">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
</select>

这是时间问题。

变化:

<select id="myList" onchange="onChanged()" onclick="onClicked()">

至:

<select id="myList" onchange="onChanged()" onmousedown="onClicked()">

如果用户打开列表并在未单击的情况下离开列表,除非您在 onmouseout 上也调用 onChanged(),否则列表不会恢复为原始列表。

<select id="myList" onchange="onChanged()" onmousedown="onClicked()" onmouseout="onChanged()">

更新: 为了实现最好的跨浏览器(FF 需要 onfocus,但会破坏 IE)支持,而浏览器不会嗅探我们这个组合:

<select id="myList" onchange="onChanged()" onblur="onChanged()" onfocus="onClicked()" onmousedown="onClicked()">

这也将更正同一事件的第二次选择,但仅在用户点击离开元素之后。


更新:

解决了...我觉得。

我重写了您用来更改选项的函数。由于您删除了所有 option 元素并添加了新的 option 元素,IE 未触发 onchange。如果用户更改了选择索引,这将导致 IE 无法引用。该函数现在仅修改当前 option 元素的值和 innerHTML。我正在使用浏览器嗅探来消除对 FF 的 onmouseout 调用。如果您将光标移动到下拉菜单,FireFox 会调用 onmouseout。这确实会在 FF 中引起副作用。如果用户在 FF 中选择相同的选项,则选项不会 return 到原始状态,直到 onblur 被触发。

演示: http://jsfiddle.net/hopkins_matt/3m1syk6c/

JS:

function changeOptions() {
    var selectedIndex = -1;
    var click = 0;
    var myList = document.getElementById("myList");
    var optionArray = ["One|1", "Two|2", "Three|3"];
    
    var fireFox = /Firefox/i.test(navigator.userAgent);
    console.log(fireFox);
    if (fireFox == false) {
        myList.onmouseout=function(){changeList(false)};
    }
    myList.onblur=function(){changeList(false)};
    myList.onchange=function(){changeList(false)};
    myList.onmousedown=function(){changeList(true)};
    
    function changeList(listOpen) {
        var isListOpen = listOpen;

        if (isListOpen == true) {
            for (i = 0; i < myList.options.length; i++) { 
                var pair = optionArray[i].split("|");
                myList.options[i].value = pair[0];
                myList.options[i].innerHTML = pair[0];
            }
        }
        if (isListOpen == false) {
            for (i = 0; i < myList.options.length; i++) { 
                var pair = optionArray[i].split("|");
                myList.options[i].value = pair[1];
                myList.options[i].innerHTML = pair[1];
            }
        }
    }
}
changeOptions();

HTML:

<select id="myList">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>

另一种方法是让每个选项存储文本的完整版本,并且仅在 selection 后将 selected 项目的显示文本更改为缩写版本。

(function() {
  var valueMap = {
    "1": "One (1)",
    "2": "Two (2)",
    "11": "Eleven (11)",
    "ITAR": "International Traffic in Arms Regulation (ITAR)",
    "ACA": "Affordable Care Act (ACA)",
    "FUBAR": "Fluffed Up Beyond All Recognition (FUBAR)"
  };
  var myList = document.getElementById("myList");
  for (var prop in valueMap) { // populate the dropdown from our object
    var opt = document.createElement("option");
    opt.value = prop;
    opt.text = valueMap[prop];
    myList.add(opt);
  }
  myList.selectedIndex = -1; // nothing selected by default

  myList.addEventListener("change", function() {
    this.options[this.selectedIndex].text = this.options[this.selectedIndex].value;
    this.blur();
  });

  myList.addEventListener("mousedown", function() {
    if (this.selectedIndex > -1) {
      var newValue = valueMap[this.options[this.selectedIndex].value];
      if (this.options[this.selectedIndex].text !== newValue) {
        this.options[this.selectedIndex].text = newValue;
      }
    }
  });
})();
<select id="myList" style="width:6em"></select>

这可以帮助您完成大部分工作,但仍然存在@hopkins-matt 提到的恼人问题;也就是说,如果用户打开下拉列表并且 selects 已经 selected 项目或离开列表而没有 selecting 任何东西, selection将保留文本的长版本。

此方法的另一个缺点是您需要指定 select 元素的宽度以防止其扩展到其隐藏选项元素的最大长度。