Bug Tracker

Opened 11 years ago

Closed 10 years ago

Last modified 6 years ago

#1294 closed bug (wontfix)

selectedIndex lost after clone() in Internet Explorer

Reported by: jesse Owned by: brandon
Priority: major Milestone: 1.1.4
Component: core Version: 1.1.3
Keywords: Cc:
Blocked by: Blocking:

Description

It seems that after a jQuery clone(), the value of select boxes are lost in IE (but not Firefox). Try this out:

<div>

<select>

<option value="0">one</option> <option value="1" selected='selected'>two</option>

</select>

</div>

$(function(){

$('div').clone(true).appendTo('body');

});

The first option will be selected in the cloned select.

Doing something like this fixes the problem (as long as there is only one select box), though I suspect there needs to be a better fix in jQuery explicitly:

$(function(){

var old = $('div'); var clone = old.clone(true); var select_val = $('select', old).val(); $('select', clone).val(select_val); clone.appendTo('body');

});

Change History (7)

comment:1 Changed 10 years ago by mrtwice99

I have also seen this bug and would greatly appreciate a fix.

comment:2 Changed 10 years ago by brandon

Owner: set to brandon

comment:3 Changed 10 years ago by brandon

Milestone: 1.1.31.1.4
Version: 1.1.21.1.3

comment:4 Changed 10 years ago by brandon

Resolution: fixed
Status: newclosed

Fixed in Rev [2438].

comment:5 Changed 10 years ago by brandon

Actually this bug also exists in the other browsers when the selected attribute isn't set. It also applied to checkboxes which Rev [2439] fixes. Except #769 causes IE6 to loose the checkbox state.

comment:6 Changed 10 years ago by rformato

Resolution: fixed
Status: closedreopened

The bug is fixed but at a very high performance cost.

I wrote this new version:

	clone: function(deep) {
		deep = deep != undefined ? deep : true;
		var $this;
		if (jQuery.browser.msie) {
			$this = this.add(this.find("*"));
                        // Need to remove events on the element and its descendants
			$this.each(function() {
				this._$events = {};
				for (var type in this.$events)
					this._$events[type] = jQuery.extend({},this.$events[type]);
			}).unbind();
		}

		// Do the clone
		var copy = false, r = this.pushStack( jQuery.map( this, function(a){
			if (!copy && deep && ( a.hasChildNodes() || jQuery.nodeName(a,"select") || jQuery.nodeName(a,"input") ) ) copy = true;
			return a.cloneNode( deep );
		}) );

		if (jQuery.browser.msie) {
			$this.each(function() {
				// Add the events back to the original and its descendants
				var events = this._$events;
				for (var type in events)
					for (var handler in events[type])
						jQuery.event.add(this, type, events[type][handler], events[type][handler].data);
				this._$events = null;
			});
		}

		// copy form values over
		if (copy) {
			if (!jQuery.browser.msie)
				$this = this.add(this.find("*"));
			var origInputs = $this.filter('select,input[@type=checkbox]'); 
			if (origInputs.length) {
				var inputs = r.add(r.find('*')).filter('select,input[@type=checkbox]');
				origInputs.each(function(i) {
					if (this.selectedIndex)
						inputs[i].selectedIndex = this.selectedIndex;
					if (this.checked)
						inputs[i].checked = true;
				});
			}
		}

		// Return the cloned set
		return r;
	},

It is still slower but much better when you clone a single element that is not a select or a checkbox.

If using clone(false) there's a very small performance hit, but i've read it is deprecated now

comment:7 Changed 10 years ago by brandon

Resolution: wontfix
Status: reopenedclosed

The fix for this is to expensive for the core and has been removed in 1.2. The workaround is simple. Just copy the selectedIndex from the original.

Note: See TracTickets for help on using tickets.