克隆不克隆select值

我没有想到,但是下面的testing在克隆值检查上失败了:

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"); }); 

这是正确的吗?

经过进一步的研究,我在JQuery bug跟踪系统中发现了这个票据,它解释了这个错误并提供了解决方法。 显然,克隆select值太昂贵,所以他们不会修复它。

https://bugs.jquery.com/ticket/1294

我使用克隆方法是在一个通用的方法,任何东西都可能被克隆,所以我不知道什么时候或是否会有一个select来设置值。 所以我添加了以下内容:

 var selects = $(cloneSourceId).find("select"); $(selects).each(function(i) { var select = this; $(clone).find("select").eq(i).val($(select).val()); }); 

以下是jQuery的克隆方法的固定版本:

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); 

从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); 

只testing一下,但似乎工作。

我的做法有点不同。

而不是在克隆过程中修改select,我只是在页面上观看每个select change事件,然后,如果值被改变,我添加需要selected属性select<option>所以它变成<option selected="selected"> 。 由于select现在标记在<option>的标记中,所以在您将.clone()它时将被传递。

唯一的代码你需要:

 //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 }); 

现在,您可以复制select任何你想要的方式,它也会复制它的值。

 $("#my-select").clone(); //will have selected value copied 

我认为这个解决scheme不太定制,所以如果你稍后修改某些东西,你的代码将会中断,那么你就不用担心了。

如果您不希望将其应用于页面上的每个select,则可以在第一行更改select器,如:

 $(document).on("change", "select.select-to-watch", function(){ 

是。 这是因为 “select”DOM节点的“selected”属性与选项的“selected”属性不同。 jQuery不会以任何方式修改选项的属性。

试试这个:

 $('option', select).get(1).setAttribute('selected', 'selected'); // starting from 0 ^ 

如果你真的对val函数的工作感兴趣,你可能需要检查一下

 alert($.fn.val) 

克隆<select>不会复制<option>上的value=属性。 所以Mark的插件在任何情况下都不起作用。

要修复,请克隆<select>之前执行此操作:

 var $origOpts = $('option', this); var $clonedOpts = $('option', $clone); $origOpts.each(function(i) { $clonedOpts.eq(i).val($(this).val()); }); 

克隆哪个<select>选项的不同方法,在jQuery 1.6.1 + …

 // instead of: $clonedSelects.eq(i).val($(this).val()); // use this: $clonedSelects.eq(i).prop('selectedIndex', $(this).prop('selectedIndex')); 

后者允许您设置selectedIndex 设置<option>值。

简化chief7的答案:

 var cloned_form = original_form.clone() original_form.find('select').each(function(i) { cloned_form.find('select').eq(i).val($(this).val()) }) 

再次,这里是jQuery票: http : //bugs.jquery.com/ticket/1294

如果你只是需要select的值,序列化的forms或类似的东西,这对我的作品:

 $clonedForm.find('theselect').val($origForm.find('theselect').val()); 

经过1个小时的尝试不同的解决scheme,没有工作,我确实创造了这个简单的解决scheme

 $clonedItem.find('select option').removeAttr('selected'); $clonedItem.find('select option[value="' + $originaItem.find('select').val() + '"]').attr('selected', 'true'); 

@ pie6k显示一个好主意。

它解决了我的问题。 我改变它有点小:

 $(document).on("change", "select", function(){ var val = $(this).val(); $(this).find("option[value=" + val + "]").attr("selected",true); });