动态附加 select 菜单,第一个选项自动禁用 select 第二个选项
Dynamically appended select menu with 1st option disabled automatically selects 2nd option
我遇到了一个奇怪的情况,据我所知,两个应该表现相同的东西表现得完全不同。
如果我在一个页面上有两个 select 菜单,一个静态菜单硬编码在 HTML 中,另一个在运行时附加到正文 JQuery。然后我禁用两个 select 菜单中的第一个选项。当显示两个菜单时,它们的第一个选项按预期被禁用,但是动态附加菜单已自动将值设置为第二个选项,而静态菜单仍然具有第一个 selected。
http://jsfiddle.net/hm3xgkLg/1/
HTML:
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
Javascript:
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function() {
sel.append($("<option>").attr('value',this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
为什么这两个看似相同的 select 菜单表现不同?我希望两者都像静态菜单一样(保留第一个值 selected)这可能吗?
还应该注意的是,我尝试将禁用功能包装在 $(document) 中。准备排除菜单尚未呈现的问题,但没有任何变化。我还尝试使用两个不同的 类 和两个单独的调用来禁用选项,以确保它不会以某种方式发生冲突而没有任何变化。
默认情况下,如果您已将选项 selected
指定给动态 dropdown
的第一个选项,那么它会为您完成:
看看这个DEMO:
$(arr).each(function(key,value) {
if(key==0)
sel.append($("<option>").attr('value',this.val).text(this.text).attr('selected',true));
else
sel.append($("<option>").attr('value',this.val).text(this.text));
});
现在为什么会这样?
对于静态 select
,该元素已存在于 DOM
中,然后您使用 jquery
为第一个 option
添加 disabled
,默认情况下第一个 option
将保留为 selected
。
现在添加动态 select
,因为您要添加它 dynamically
可能不考虑 select
默认情况下第一个 option
,因为它被禁用了!!
即使我觉得这是奇怪的行为,但有时我们需要通过试错来处理这些事情。
Why are these two seemingly identical select menus behaving
differently
这是因为第一个 select
已经是文档的一部分并且已被解析。 As per the spec here:
The initial state has the first option selected..
因此第一个选项是预 selected。稍后当您禁用一个选项时,它不会更改 selection。
示例 1:您可以看到第一个 select
已将 disabled
属性应用于标记中的第一个选项。与第二个 select
.
相比,第二个选项得到预先 selected
<select class="dropMenu">
<option value="1" disabled>First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
在您使用 Javascript 动态添加 select
的情况下,第二个 select
已创建并立即添加到 body
。当这成为 DOM 的一部分时,没有选项,因此不可能有前 selection。稍后当您向其附加选项,然后禁用其中一个选项时,它似乎执行得太快,并且在加载时第一个选项已经被禁用,第二个选项被预 selected .
示例 2:不要将 select
立即附加到 body
。在填充 options
之后附加它。这次第一个 option
将被预先 select 编辑,尽管您稍后更改了 disabled
属性。
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
sel.appendTo('body'); /* <--- append here */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
示例 3:在 disable
和 option
之前添加延迟。这将为您提供获得第一个 option
pre-select 的预期行为,因为它有足够的时间。
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
setTimeout(disable, 1000); /* <--- give some delay here */
function disable() {
$('.dropMenu option:nth-child(1)').prop('disabled', true);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
示例 4:您也可以 select 一个 option
在禁用它们之前显式
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').prop('selected', true); /* <-- select explicitly */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
只需手动select动态添加菜单中的第一个选项:
$('.dropMenu option:nth-child(1)')
.attr('disabled', 'disabled')
.attr('selected', 'selected');
jsfiddle 在这里(我借了你的 :P):
https://jsfiddle.net/z0dzk5nL/1/
编辑
快速更新。 Here 您可以找到 "select" 元素的规范。我已经引用了回答你问题的部分:
If nodes are inserted or nodes are removed causing the list of options
to gain or lose one or more option elements, or if an option element
in the list of options asks for a reset, then, if the select element's
multiple attribute is absent, the user agent must run the first
applicable set of steps from the following list:
If the select element's display size is 1, and no option elements in
the select element's list of options have their selectedness set to
true Set the selectedness of the first option element in the list of
options in tree order that is not disabled, if any, to true.
If two or more option elements in the select element's list of options
have their selectedness set to true Set the selectedness of all but
the last option element with its selectedness set to true in the list
of options in tree order to false.
这里的 fiddle 表明,如果您在附加选项时预先 select 选项,则可以在不丢失 selection 的情况下禁用它(我使用了一个 for 循环而不是 "each" 函数来证明这一点):
jsfiddle.net/xnvbevhm/
(抱歉,我不能 post 超过两个链接,因为我没有足够的声誉 :P)
作为将第一个属性设置为选中的替代方法,使用最短时间(即 1)的 setTimeout 似乎可以使事情按预期运行。不过,我仍在研究其原因。
setTimeout(function() {
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
}, 1);
尝试在 setInterval
中设置您的 $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
,因为您正在创建动态下拉菜单,因此执行和创建需要一些时间,同时您 禁用下拉元素 jquery 将要执行。所以问题来了。
结帐代码片段
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function() {
sel.append($("<option>").attr('value',this.val).text(this.text));
});
setTimeout(function() {
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
}, 1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
我遇到了一个奇怪的情况,据我所知,两个应该表现相同的东西表现得完全不同。
如果我在一个页面上有两个 select 菜单,一个静态菜单硬编码在 HTML 中,另一个在运行时附加到正文 JQuery。然后我禁用两个 select 菜单中的第一个选项。当显示两个菜单时,它们的第一个选项按预期被禁用,但是动态附加菜单已自动将值设置为第二个选项,而静态菜单仍然具有第一个 selected。
http://jsfiddle.net/hm3xgkLg/1/
HTML:
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
Javascript:
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function() {
sel.append($("<option>").attr('value',this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
为什么这两个看似相同的 select 菜单表现不同?我希望两者都像静态菜单一样(保留第一个值 selected)这可能吗?
还应该注意的是,我尝试将禁用功能包装在 $(document) 中。准备排除菜单尚未呈现的问题,但没有任何变化。我还尝试使用两个不同的 类 和两个单独的调用来禁用选项,以确保它不会以某种方式发生冲突而没有任何变化。
默认情况下,如果您已将选项 selected
指定给动态 dropdown
的第一个选项,那么它会为您完成:
看看这个DEMO:
$(arr).each(function(key,value) {
if(key==0)
sel.append($("<option>").attr('value',this.val).text(this.text).attr('selected',true));
else
sel.append($("<option>").attr('value',this.val).text(this.text));
});
现在为什么会这样?
对于静态 select
,该元素已存在于 DOM
中,然后您使用 jquery
为第一个 option
添加 disabled
,默认情况下第一个 option
将保留为 selected
。
现在添加动态 select
,因为您要添加它 dynamically
可能不考虑 select
默认情况下第一个 option
,因为它被禁用了!!
即使我觉得这是奇怪的行为,但有时我们需要通过试错来处理这些事情。
Why are these two seemingly identical select menus behaving differently
这是因为第一个 select
已经是文档的一部分并且已被解析。 As per the spec here:
The initial state has the first option selected..
因此第一个选项是预 selected。稍后当您禁用一个选项时,它不会更改 selection。
示例 1:您可以看到第一个 select
已将 disabled
属性应用于标记中的第一个选项。与第二个 select
.
<select class="dropMenu">
<option value="1" disabled>First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
在您使用 Javascript 动态添加 select
的情况下,第二个 select
已创建并立即添加到 body
。当这成为 DOM 的一部分时,没有选项,因此不可能有前 selection。稍后当您向其附加选项,然后禁用其中一个选项时,它似乎执行得太快,并且在加载时第一个选项已经被禁用,第二个选项被预 selected .
示例 2:不要将 select
立即附加到 body
。在填充 options
之后附加它。这次第一个 option
将被预先 select 编辑,尽管您稍后更改了 disabled
属性。
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
sel.appendTo('body'); /* <--- append here */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
示例 3:在 disable
和 option
之前添加延迟。这将为您提供获得第一个 option
pre-select 的预期行为,因为它有足够的时间。
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
setTimeout(disable, 1000); /* <--- give some delay here */
function disable() {
$('.dropMenu option:nth-child(1)').prop('disabled', true);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
示例 4:您也可以 select 一个 option
在禁用它们之前显式
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').prop('selected', true); /* <-- select explicitly */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
只需手动select动态添加菜单中的第一个选项:
$('.dropMenu option:nth-child(1)')
.attr('disabled', 'disabled')
.attr('selected', 'selected');
jsfiddle 在这里(我借了你的 :P): https://jsfiddle.net/z0dzk5nL/1/
编辑 快速更新。 Here 您可以找到 "select" 元素的规范。我已经引用了回答你问题的部分:
If nodes are inserted or nodes are removed causing the list of options to gain or lose one or more option elements, or if an option element in the list of options asks for a reset, then, if the select element's multiple attribute is absent, the user agent must run the first applicable set of steps from the following list:
If the select element's display size is 1, and no option elements in the select element's list of options have their selectedness set to true Set the selectedness of the first option element in the list of options in tree order that is not disabled, if any, to true.
If two or more option elements in the select element's list of options have their selectedness set to true Set the selectedness of all but the last option element with its selectedness set to true in the list of options in tree order to false.
这里的 fiddle 表明,如果您在附加选项时预先 select 选项,则可以在不丢失 selection 的情况下禁用它(我使用了一个 for 循环而不是 "each" 函数来证明这一点):
jsfiddle.net/xnvbevhm/
(抱歉,我不能 post 超过两个链接,因为我没有足够的声誉 :P)
作为将第一个属性设置为选中的替代方法,使用最短时间(即 1)的 setTimeout 似乎可以使事情按预期运行。不过,我仍在研究其原因。
setTimeout(function() {
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
}, 1);
尝试在 setInterval
中设置您的 $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
,因为您正在创建动态下拉菜单,因此执行和创建需要一些时间,同时您 禁用下拉元素 jquery 将要执行。所以问题来了。
结帐代码片段
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function() {
sel.append($("<option>").attr('value',this.val).text(this.text));
});
setTimeout(function() {
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
}, 1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>