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 元素的宽度以防止其扩展到其隐藏选项元素的最大长度。
我正在尝试使 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 元素的宽度以防止其扩展到其隐藏选项元素的最大长度。