Bug Tracker

Opened 10 years ago

Closed 10 years ago

Last modified 5 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 changed from 1.1.3 to 1.1.4
  • Version changed from 1.1.2 to 1.1.3

comment:4 Changed 10 years ago by brandon

  • Resolution set to fixed
  • Status changed from new to closed

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 deleted
  • Status changed from closed to reopened

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 set to wontfix
  • Status changed from reopened to closed

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.