克隆不克隆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); });