Bug Tracker

Ticket #1294 (closed bug: wontfix)

Opened 7 years ago

Last modified 3 years ago

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:
Blocking: Blocked by:

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

comment:1 Changed 7 years ago by mrtwice99

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

comment:2 Changed 7 years ago by brandon

  • Owner set to brandon

comment:3 Changed 7 years ago by brandon

  • Version changed from 1.1.2 to 1.1.3
  • Milestone changed from 1.1.3 to 1.1.4

comment:4 Changed 7 years ago by brandon

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

Fixed in Rev [2438].

comment:5 Changed 7 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 7 years ago by rformato

  • Status changed from closed to reopened
  • Resolution fixed deleted

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 7 years ago by brandon

  • Status changed from reopened to closed
  • Resolution set to wontfix

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.