jQuery 克隆不是克隆选择值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/742810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clone isn't cloning select values
提问by chief7
I didn't expect it but the following test fails on the cloned value check:
我没想到,但以下测试在克隆值检查中失败:
test("clone should retain values of select", function() {
var select = $("<select>").append($("<option>")
.val("1"))
.append($("<option>")
.val("2"));
$(select).val("2");
equals($(select).find("option:selected").val(), "2", "expect 2");
var clone = $(select).clone();
equals($(clone).find("option:selected").val(), "2", "expect 2");
});
Is this right?
这是正确的吗?
回答by chief7
After further research I found this ticket in the JQuery bug tracker system which explains the bug and provides a work around. Apparently, it is too expensive to clone the select values so they won't fix it.
经过进一步研究,我在 JQuery 错误跟踪器系统中找到了这张票,它解释了错误并提供了解决方法。显然,克隆选择值太昂贵了,所以他们不会修复它。
https://bugs.jquery.com/ticket/1294
https://bugs.jquery.com/ticket/1294
My use of the clone method was in a generic method where anything might be cloned so I'm not sure when or if there will be a select to set the value on. So I added the following:
我对 clone 方法的使用是在一个通用方法中,任何东西都可能被克隆,所以我不确定何时或是否会有一个选择来设置值。所以我添加了以下内容:
var selects = $(cloneSourceId).find("select");
$(selects).each(function(i) {
var select = this;
$(clone).find("select").eq(i).val($(select).val());
});
回答by Novalis
Here's a fixed version of the clone method for jQuery:
这是 jQuery 的 clone 方法的固定版本:
https://github.com/spencertipping/jquery.fix.clone
https://github.com/spencertipping/jquery.fix.clone
// Textarea and select clone() bug workaround | Spencer Tipping
// Licensed under the terms of the MIT source code license
// Motivation.
// jQuery's clone() method works in most cases, but it fails to copy the value of textareas and select elements. This patch replaces jQuery's clone() method with a wrapper that fills in the
// values after the fact.
// An interesting error case submitted by Piotr Przyby?: If two <select> options had the same value, the clone() method would select the wrong one in the cloned box. The fix, suggested by Piotr
// and implemented here, is to use the selectedIndex property on the <select> box itself rather than relying on jQuery's value-based val().
(function (original) {
jQuery.fn.clone = function () {
var result = original.apply(this, arguments),
my_textareas = this.find('textarea').add(this.filter('textarea')),
result_textareas = result.find('textarea').add(result.filter('textarea')),
my_selects = this.find('select').add(this.filter('select')),
result_selects = result.find('select').add(result.filter('select'));
for (var i = 0, l = my_textareas.length; i < l; ++i) $(result_textareas[i]).val($(my_textareas[i]).val());
for (var i = 0, l = my_selects.length; i < l; ++i) result_selects[i].selectedIndex = my_selects[i].selectedIndex;
return result;
};
}) (jQuery.fn.clone);
回答by mpen
Made a plugin out of chief7's answer:
从 Chief7 的回答中制作了一个插件:
(function($,undefined) {
$.fn.cloneSelects = function(withDataAndEvents, deepWithDataAndEvents) {
var $clone = this.clone(withDataAndEvents, deepWithDataAndEvents);
var $origSelects = $('select', this);
var $clonedSelects = $('select', $clone);
$origSelects.each(function(i) {
$clonedSelects.eq(i).val($(this).val());
});
return $clone;
}
})(jQuery);
Only tested it briefly, but it seems to work.
只是简单地测试了它,但它似乎有效。
回答by pie6k
My approach is a little different.
我的方法有点不同。
Instead of modifying selects during cloning, I'm just watching every select
on page for change
event, and then, if value is changed I add needed selected
attribute to selected <option>
so it becomes <option selected="selected">
. As selection is now marked in <option>
's markup, it will be passed when you'll .clone()
it.
我没有在克隆期间修改选择,而是查看select
页面上的每个change
事件,然后,如果值发生更改,我将需要的selected
属性添加到 selected 中<option>
,使其变为<option selected="selected">
. 由于选择现在已在<option>
的标记中标记,因此它将在您需要时通过.clone()
。
The only code you need:
您需要的唯一代码:
//when ANY select on page changes its value
$(document).on("change", "select", function(){
var val = $(this).val(); //get new value
//find selected option
$("option", this).removeAttr("selected").filter(function(){
return $(this).attr("value") == val;
}).first().attr("selected", "selected"); //add selected attribute to selected option
});
And now, you can copy select any way you want and it'll have it's value copied too.
现在,您可以按照您想要的任何方式复制选择,并且它的值也会被复制。
$("#my-select").clone(); //will have selected value copied
I think this solution is less customso you don't need to worry if your code will break if you'll modify something later.
我认为此解决方案不太自定义,因此您无需担心如果您稍后修改某些内容,您的代码是否会中断。
If you don't want it to be applied to every select on page, you can change selector on the first line like:
如果您不想将其应用于页面上的每个选择,您可以在第一行更改选择器,例如:
$(document).on("change", "select.select-to-watch", function(){
回答by jamesvl
Cloning a <select>
does notcopy the value=
property on <option>
s. So Mark's plugin does not work in all cases.
克隆<select>
并不能复制value=
的财产<option>
秒。所以 Mark 的插件并不适用于所有情况。
To fix, do this beforecloning the <select>
values:
要修复,请在克隆<select>
值之前执行此操作:
var $origOpts = $('option', this);
var $clonedOpts = $('option', $clone);
$origOpts.each(function(i) {
$clonedOpts.eq(i).val($(this).val());
});
A different way to clone which <select>
option is selected, in jQuery 1.6.1+...
<select>
在 jQuery 1.6.1+ 中克隆选择了哪个选项的不同方法...
// instead of:
$clonedSelects.eq(i).val($(this).val());
// use this:
$clonedSelects.eq(i).prop('selectedIndex', $(this).prop('selectedIndex'));
The latter allows you to set the <option>
values aftersetting the selectedIndex
.
后者允许您设置的<option>
值后设置selectedIndex
。
回答by user123444555621
Yes. This is becausethe 'selected' property of a 'select' DOM node differs from the 'selected' attribute of the options. jQuery does not modify the options' attributes in any way.
是的。这是因为“select”DOM 节点的“selected”属性不同于选项的“selected”属性。jQuery 不会以任何方式修改选项的属性。
Try this instead:
试试这个:
$('option', select).get(1).setAttribute('selected', 'selected');
// starting from 0 ^
If you're really interested in how the val function works, you may want to examine
如果您真的对 val 函数的工作方式感兴趣,您可能需要检查
alert($.fn.val)
回答by Collin Anderson
Simplification of chief7's answer:
简化 Chief7 的回答:
var cloned_form = original_form.clone()
original_form.find('select').each(function(i) {
cloned_form.find('select').eq(i).val($(this).val())
})
Again, here's the jQuery ticket: http://bugs.jquery.com/ticket/1294
同样,这是 jQuery 票证:http: //bugs.jquery.com/ticket/1294
回答by Hilary Okoro
$(document).on("change", "select", function(){
original = $("#original");
clone = $(original.clone());
clone.find("select").val(original.find("select").val());
});
回答by David Antelo
just reporting back. For some godly unknown reason, and even though this was the first thing I tested, and I haven't changed my code whatsoever, now the
刚回来汇报。出于某种神圣的未知原因,即使这是我测试的第一件事,而且我还没有更改我的代码,但现在
$("#selectTipoIntervencion1").val($("#selectTipoIntervencion0").val());
approach is working. I have no idea why or if it will stop working again as soon as I change something, but I'm gonna go with this for now. Thanks everybody for the help!
方法正在起作用。我不知道为什么或者一旦我改变某些东西它是否会再次停止工作,但我现在要继续这样做。感谢大家的帮助!
回答by Galley
@pie6k show an good idea.
@pie6k 展示了一个好主意。
It solved my problem. I change it a little small:
它解决了我的问题。我稍微改了一下:
$(document).on("change", "select", function(){
var val = $(this).val();
$(this).find("option[value=" + val + "]").attr("selected",true);
});