Speed up & compatibility improvements for new clone mechanism in IE.
This commit is contained in:
parent
8b33e23ea0
commit
1a3fd3329d
3 changed files with 62 additions and 22 deletions
|
@ -193,28 +193,20 @@ jQuery.fn.extend({
|
||||||
// from the original. In order to get around this, we use some
|
// from the original. In order to get around this, we use some
|
||||||
// proprietary methods to clear the events. Thanks to MooTools
|
// proprietary methods to clear the events. Thanks to MooTools
|
||||||
// guys for this hotness.
|
// guys for this hotness.
|
||||||
var srcElements = jQuery(this).find('*').andSelf();
|
|
||||||
jQuery(clone).find('*').andSelf().each(function (i, clone) {
|
|
||||||
// We do not need to do anything for non-Elements
|
|
||||||
if (this.nodeType !== 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearAttributes removes the attributes, but also
|
// Using Sizzle here is crazy slow, so we use getElementsByTagName
|
||||||
// removes the attachEvent events
|
// instead
|
||||||
clone.clearAttributes();
|
var srcElements = this.getElementsByTagName("*"),
|
||||||
|
destElements = clone.getElementsByTagName("*");
|
||||||
|
|
||||||
// mergeAttributes only merges back on the original attributes,
|
// Weird iteration because IE will replace the length property
|
||||||
// not the events
|
// with an element if you are cloning the body and one of the
|
||||||
clone.mergeAttributes(srcElements[i]);
|
// elements on the page has a name or id of "length"
|
||||||
|
for ( var i = 0; srcElements[i]; ++i ) {
|
||||||
|
cloneFixAttributes( srcElements[i], destElements[i] );
|
||||||
|
}
|
||||||
|
|
||||||
// IE6-8 fail to clone children inside object elements that use
|
cloneFixAttributes( this, clone );
|
||||||
// the proprietary classid attribute value (rather than the type
|
|
||||||
// attribute) to identify the type of content to display
|
|
||||||
if (clone.nodeName.toLowerCase() === 'object') {
|
|
||||||
clone.outerHTML = srcElements[i].outerHTML;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
|
@ -355,7 +347,7 @@ jQuery.fn.extend({
|
||||||
root(this[i], first) :
|
root(this[i], first) :
|
||||||
this[i],
|
this[i],
|
||||||
i > 0 || results.cacheable || this.length > 1 ?
|
i > 0 || results.cacheable || this.length > 1 ?
|
||||||
fragment.cloneNode(true) :
|
jQuery(fragment).clone(true)[0] :
|
||||||
fragment
|
fragment
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -402,6 +394,46 @@ function cloneCopyEvent(orig, ret) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cloneFixAttributes(src, dest) {
|
||||||
|
// We do not need to do anything for non-Elements
|
||||||
|
if ( dest.nodeType !== 1 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeName = dest.nodeName.toLowerCase();
|
||||||
|
|
||||||
|
// clearAttributes removes the attributes, which we don't want,
|
||||||
|
// but also removes the attachEvent events, which we *do* want
|
||||||
|
dest.clearAttributes();
|
||||||
|
|
||||||
|
// mergeAttributes, in contrast, only merges back on the
|
||||||
|
// original attributes, not the events
|
||||||
|
dest.mergeAttributes(src);
|
||||||
|
|
||||||
|
// IE6-8 fail to clone children inside object elements that use
|
||||||
|
// the proprietary classid attribute value (rather than the type
|
||||||
|
// attribute) to identify the type of content to display
|
||||||
|
if ( nodeName === "object" ) {
|
||||||
|
dest.outerHTML = src.outerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE6-? fails to persist the checked state of a cloned checkbox
|
||||||
|
// or radio button
|
||||||
|
else if ( nodeName === "input" && src.checked ) {
|
||||||
|
dest.defaultChecked = dest.checked = src.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE6-? fails to return the selected option to the default selected
|
||||||
|
// state when cloning options
|
||||||
|
else if ( nodeName === "option" ) {
|
||||||
|
dest.selected = src.defaultSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event data gets referenced instead of copied if the expando
|
||||||
|
// gets copied too
|
||||||
|
dest.removeAttribute( jQuery.expando );
|
||||||
|
}
|
||||||
|
|
||||||
jQuery.buildFragment = function( args, nodes, scripts ) {
|
jQuery.buildFragment = function( args, nodes, scripts ) {
|
||||||
var fragment, cacheable, cacheresults,
|
var fragment, cacheable, cacheresults,
|
||||||
doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
|
doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
|
||||||
|
|
|
@ -382,7 +382,7 @@ test("append(Function) with incoming value", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("append the same fragment with events (Bug #6997, 5566)", function () {
|
test("append the same fragment with events (Bug #6997, 5566)", function () {
|
||||||
expect(2 + (document.fireEvent ? 1 : 0));
|
expect(4 + (document.fireEvent ? 1 : 0));
|
||||||
stop(1000);
|
stop(1000);
|
||||||
|
|
||||||
var element;
|
var element;
|
||||||
|
@ -413,6 +413,14 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
|
||||||
|
|
||||||
jQuery("#listWithTabIndex li").before(element);
|
jQuery("#listWithTabIndex li").before(element);
|
||||||
jQuery("#listWithTabIndex li.test6997").eq(1).click();
|
jQuery("#listWithTabIndex li.test6997").eq(1).click();
|
||||||
|
|
||||||
|
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
|
||||||
|
|
||||||
|
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
|
||||||
|
|
||||||
|
element = jQuery("<input type='checkbox'>").attr('checked', 'checked');
|
||||||
|
|
||||||
|
equals( element.clone().is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
|
||||||
});
|
});
|
||||||
|
|
||||||
test("appendTo(String|Element|Array<Element>|jQuery)", function() {
|
test("appendTo(String|Element|Array<Element>|jQuery)", function() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue