mirror of
https://github.com/jquery/jquery.git
synced 2025-01-10 18:24:24 +00:00
Manipulation: privatize buildFragment() function
Fixes gh-2224
This commit is contained in:
parent
6d7ef56ed3
commit
a74320fca8
@ -2,13 +2,11 @@ define([
|
||||
"../core",
|
||||
"../var/document",
|
||||
"./var/rsingleTag",
|
||||
"../manipulation/buildFragment",
|
||||
|
||||
// This is the only module that needs core/support
|
||||
"./support",
|
||||
|
||||
// buildFragment
|
||||
"../manipulation"
|
||||
], function( jQuery, document, rsingleTag, support ) {
|
||||
"./support"
|
||||
], function( jQuery, document, rsingleTag, buildFragment, support ) {
|
||||
|
||||
// data: string of html
|
||||
// context (optional): If specified, the fragment will be created in this context,
|
||||
@ -36,7 +34,7 @@ jQuery.parseHTML = function( data, context, keepScripts ) {
|
||||
return [ context.createElement( parsed[1] ) ];
|
||||
}
|
||||
|
||||
parsed = jQuery.buildFragment( [ data ], context, scripts );
|
||||
parsed = buildFragment( [ data ], context, scripts );
|
||||
|
||||
if ( scripts && scripts.length ) {
|
||||
jQuery( scripts ).remove();
|
||||
|
@ -4,7 +4,14 @@ define([
|
||||
"./var/push",
|
||||
"./core/access",
|
||||
"./manipulation/var/rcheckableType",
|
||||
"./manipulation/var/rtagName",
|
||||
"./manipulation/var/rscriptType",
|
||||
"./manipulation/wrapMap",
|
||||
"./manipulation/getAll",
|
||||
"./manipulation/setGlobalEval",
|
||||
"./manipulation/buildFragment",
|
||||
"./manipulation/support",
|
||||
|
||||
"./data/var/dataPriv",
|
||||
"./data/var/dataUser",
|
||||
|
||||
@ -13,49 +20,18 @@ define([
|
||||
"./traversing",
|
||||
"./selector",
|
||||
"./event"
|
||||
], function( jQuery, concat, push, access, rcheckableType, support, dataPriv, dataUser ) {
|
||||
], function( jQuery, concat, push, access,
|
||||
rcheckableType, rtagName, rscriptType,
|
||||
wrapMap, getAll, setGlobalEval, buildFragment, support,
|
||||
dataPriv, dataUser ) {
|
||||
|
||||
var
|
||||
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
|
||||
rtagName = /<([\w:-]+)/,
|
||||
rhtml = /<|&#?\w+;/,
|
||||
rnoInnerhtml = /<(?:script|style|link)/i,
|
||||
// checked="checked" or checked
|
||||
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
|
||||
rscriptType = /^$|\/(?:java|ecma)script/i,
|
||||
rscriptTypeMasked = /^true\/(.*)/,
|
||||
rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
|
||||
|
||||
// We have to close these tags to support XHTML (#13200)
|
||||
wrapMap = {
|
||||
|
||||
// Support: IE9
|
||||
option: [ 1, "<select multiple='multiple'>", "</select>" ],
|
||||
|
||||
thead: [ 1, "<table>", "</table>" ],
|
||||
|
||||
// Some of the following wrappers are not fully defined, because
|
||||
// their parent elements (except for "table" element) could be omitted
|
||||
// since browser parsers are smart enough to auto-insert them
|
||||
|
||||
// Support: Android 2.3
|
||||
// Android browser doesn't auto-insert colgroup
|
||||
col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
|
||||
|
||||
// Auto-insert "tbody" element
|
||||
tr: [ 2, "<table>", "</table>" ],
|
||||
|
||||
// Auto-insert "tbody" and "tr" elements
|
||||
td: [ 3, "<table>", "</table>" ],
|
||||
|
||||
_default: [ 0, "", "" ]
|
||||
};
|
||||
|
||||
// Support: IE9
|
||||
wrapMap.optgroup = wrapMap.option;
|
||||
|
||||
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
|
||||
wrapMap.th = wrapMap.td;
|
||||
rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
|
||||
|
||||
function manipulationTarget( elem, content ) {
|
||||
if ( jQuery.nodeName( elem, "table" ) &&
|
||||
@ -84,18 +60,6 @@ function restoreScript( elem ) {
|
||||
return elem;
|
||||
}
|
||||
|
||||
// Mark scripts as having already been evaluated
|
||||
function setGlobalEval( elems, refElements ) {
|
||||
var i = 0,
|
||||
l = elems.length;
|
||||
|
||||
for ( ; i < l; i++ ) {
|
||||
dataPriv.set(
|
||||
elems[ i ], "globalEval", !refElements || dataPriv.get( refElements[ i ], "globalEval" )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function cloneCopyEvent( src, dest ) {
|
||||
var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
|
||||
|
||||
@ -130,20 +94,6 @@ function cloneCopyEvent( src, dest ) {
|
||||
}
|
||||
}
|
||||
|
||||
function getAll( context, tag ) {
|
||||
// Support: IE9-11+
|
||||
// Use typeof to avoid zero-argument method invocation on host objects (#15151)
|
||||
var ret = typeof context.getElementsByTagName !== "undefined" ?
|
||||
context.getElementsByTagName( tag || "*" ) :
|
||||
typeof context.querySelectorAll !== "undefined" ?
|
||||
context.querySelectorAll( tag || "*" ) :
|
||||
[];
|
||||
|
||||
return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
|
||||
jQuery.merge( [ context ], ret ) :
|
||||
ret;
|
||||
}
|
||||
|
||||
// Fix IE bugs, see support tests
|
||||
function fixInput( src, dest ) {
|
||||
var nodeName = dest.nodeName.toLowerCase();
|
||||
@ -205,94 +155,6 @@ jQuery.extend({
|
||||
return clone;
|
||||
},
|
||||
|
||||
buildFragment: function( elems, context, scripts, selection, ignored ) {
|
||||
var elem, tmp, tag, wrap, contains, j,
|
||||
fragment = context.createDocumentFragment(),
|
||||
nodes = [],
|
||||
i = 0,
|
||||
l = elems.length;
|
||||
|
||||
for ( ; i < l; i++ ) {
|
||||
elem = elems[ i ];
|
||||
|
||||
if ( elem || elem === 0 ) {
|
||||
|
||||
// Add nodes directly
|
||||
if ( jQuery.type( elem ) === "object" ) {
|
||||
// Support: Android<4.1, PhantomJS<2
|
||||
// push.apply(_, arraylike) throws on ancient WebKit
|
||||
jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
|
||||
|
||||
// Convert non-html into a text node
|
||||
} else if ( !rhtml.test( elem ) ) {
|
||||
nodes.push( context.createTextNode( elem ) );
|
||||
|
||||
// Convert html into DOM nodes
|
||||
} else {
|
||||
tmp = tmp || fragment.appendChild( context.createElement("div") );
|
||||
|
||||
// Deserialize a standard representation
|
||||
tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
|
||||
wrap = wrapMap[ tag ] || wrapMap._default;
|
||||
tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
|
||||
|
||||
// Descend through wrappers to the right content
|
||||
j = wrap[ 0 ];
|
||||
while ( j-- ) {
|
||||
tmp = tmp.lastChild;
|
||||
}
|
||||
|
||||
// Support: Android<4.1, PhantomJS<2
|
||||
// push.apply(_, arraylike) throws on ancient WebKit
|
||||
jQuery.merge( nodes, tmp.childNodes );
|
||||
|
||||
// Remember the top-level container
|
||||
tmp = fragment.firstChild;
|
||||
|
||||
// Ensure the created nodes are orphaned (#12392)
|
||||
tmp.textContent = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove wrapper from fragment
|
||||
fragment.textContent = "";
|
||||
|
||||
i = 0;
|
||||
while ( (elem = nodes[ i++ ]) ) {
|
||||
|
||||
// Skip elements already in the context collection (trac-4087)
|
||||
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
|
||||
if ( ignored ) {
|
||||
ignored.push( elem );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
contains = jQuery.contains( elem.ownerDocument, elem );
|
||||
|
||||
// Append to fragment
|
||||
tmp = getAll( fragment.appendChild( elem ), "script" );
|
||||
|
||||
// Preserve script evaluation history
|
||||
if ( contains ) {
|
||||
setGlobalEval( tmp );
|
||||
}
|
||||
|
||||
// Capture executables
|
||||
if ( scripts ) {
|
||||
j = 0;
|
||||
while ( (elem = tmp[ j++ ]) ) {
|
||||
if ( rscriptType.test( elem.type || "" ) ) {
|
||||
scripts.push( elem );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
},
|
||||
|
||||
cleanData: function( elems ) {
|
||||
var data, elem, type,
|
||||
special = jQuery.event.special,
|
||||
@ -500,7 +362,7 @@ jQuery.fn.extend({
|
||||
}
|
||||
|
||||
if ( l ) {
|
||||
fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this, ignored );
|
||||
fragment = buildFragment( args, this[ 0 ].ownerDocument, false, this, ignored );
|
||||
first = fragment.firstChild;
|
||||
|
||||
if ( fragment.childNodes.length === 1 ) {
|
||||
|
101
src/manipulation/buildFragment.js
Normal file
101
src/manipulation/buildFragment.js
Normal file
@ -0,0 +1,101 @@
|
||||
define([
|
||||
"../core",
|
||||
"./var/rtagName",
|
||||
"./var/rscriptType",
|
||||
"./wrapMap",
|
||||
"./getAll",
|
||||
"./setGlobalEval"
|
||||
], function( jQuery, rtagName, rscriptType, wrapMap, getAll, setGlobalEval ) {
|
||||
|
||||
var rhtml = /<|&#?\w+;/;
|
||||
|
||||
function buildFragment( elems, context, scripts, selection, ignored ) {
|
||||
var elem, tmp, tag, wrap, contains, j,
|
||||
fragment = context.createDocumentFragment(),
|
||||
nodes = [],
|
||||
i = 0,
|
||||
l = elems.length;
|
||||
|
||||
for ( ; i < l; i++ ) {
|
||||
elem = elems[ i ];
|
||||
|
||||
if ( elem || elem === 0 ) {
|
||||
|
||||
// Add nodes directly
|
||||
if ( jQuery.type( elem ) === "object" ) {
|
||||
// Support: Android<4.1, PhantomJS<2
|
||||
// push.apply(_, arraylike) throws on ancient WebKit
|
||||
jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
|
||||
|
||||
// Convert non-html into a text node
|
||||
} else if ( !rhtml.test( elem ) ) {
|
||||
nodes.push( context.createTextNode( elem ) );
|
||||
|
||||
// Convert html into DOM nodes
|
||||
} else {
|
||||
tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
|
||||
|
||||
// Deserialize a standard representation
|
||||
tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
|
||||
wrap = wrapMap[ tag ] || wrapMap._default;
|
||||
tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
|
||||
|
||||
// Descend through wrappers to the right content
|
||||
j = wrap[ 0 ];
|
||||
while ( j-- ) {
|
||||
tmp = tmp.lastChild;
|
||||
}
|
||||
|
||||
// Support: Android<4.1, PhantomJS<2
|
||||
// push.apply(_, arraylike) throws on ancient WebKit
|
||||
jQuery.merge( nodes, tmp.childNodes );
|
||||
|
||||
// Remember the top-level container
|
||||
tmp = fragment.firstChild;
|
||||
|
||||
// Ensure the created nodes are orphaned (#12392)
|
||||
tmp.textContent = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove wrapper from fragment
|
||||
fragment.textContent = "";
|
||||
|
||||
i = 0;
|
||||
while ( ( elem = nodes[ i++ ] ) ) {
|
||||
|
||||
// Skip elements already in the context collection (trac-4087)
|
||||
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
|
||||
if ( ignored ) {
|
||||
ignored.push( elem );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
contains = jQuery.contains( elem.ownerDocument, elem );
|
||||
|
||||
// Append to fragment
|
||||
tmp = getAll( fragment.appendChild( elem ), "script" );
|
||||
|
||||
// Preserve script evaluation history
|
||||
if ( contains ) {
|
||||
setGlobalEval( tmp );
|
||||
}
|
||||
|
||||
// Capture executables
|
||||
if ( scripts ) {
|
||||
j = 0;
|
||||
while ( ( elem = tmp[ j++ ] ) ) {
|
||||
if ( rscriptType.test( elem.type || "" ) ) {
|
||||
scripts.push( elem );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
return buildFragment;
|
||||
});
|
20
src/manipulation/getAll.js
Normal file
20
src/manipulation/getAll.js
Normal file
@ -0,0 +1,20 @@
|
||||
define([
|
||||
"../core"
|
||||
], function( jQuery ) {
|
||||
|
||||
function getAll( context, tag ) {
|
||||
// Support: IE9-11+
|
||||
// Use typeof to avoid zero-argument method invocation on host objects (#15151)
|
||||
var ret = typeof context.getElementsByTagName !== "undefined" ?
|
||||
context.getElementsByTagName( tag || "*" ) :
|
||||
typeof context.querySelectorAll !== "undefined" ?
|
||||
context.querySelectorAll( tag || "*" ) :
|
||||
[];
|
||||
|
||||
return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
|
||||
jQuery.merge( [ context ], ret ) :
|
||||
ret;
|
||||
}
|
||||
|
||||
return getAll;
|
||||
});
|
20
src/manipulation/setGlobalEval.js
Normal file
20
src/manipulation/setGlobalEval.js
Normal file
@ -0,0 +1,20 @@
|
||||
define([
|
||||
"../data/var/dataPriv"
|
||||
], function( dataPriv ) {
|
||||
|
||||
// Mark scripts as having already been evaluated
|
||||
function setGlobalEval( elems, refElements ) {
|
||||
var i = 0,
|
||||
l = elems.length;
|
||||
|
||||
for ( ; i < l; i++ ) {
|
||||
dataPriv.set(
|
||||
elems[ i ],
|
||||
"globalEval",
|
||||
!refElements || dataPriv.get( refElements[ i ], "globalEval" )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return setGlobalEval;
|
||||
});
|
3
src/manipulation/var/rscriptType.js
Normal file
3
src/manipulation/var/rscriptType.js
Normal file
@ -0,0 +1,3 @@
|
||||
define(function() {
|
||||
return ( /^$|\/(?:java|ecma)script/i );
|
||||
});
|
3
src/manipulation/var/rtagName.js
Normal file
3
src/manipulation/var/rtagName.js
Normal file
@ -0,0 +1,3 @@
|
||||
define(function() {
|
||||
return ( /<([\w:-]+)/ );
|
||||
});
|
35
src/manipulation/wrapMap.js
Normal file
35
src/manipulation/wrapMap.js
Normal file
@ -0,0 +1,35 @@
|
||||
define(function() {
|
||||
|
||||
// We have to close these tags to support XHTML (#13200)
|
||||
var wrapMap = {
|
||||
|
||||
// Support: IE9
|
||||
option: [ 1, "<select multiple='multiple'>", "</select>" ],
|
||||
|
||||
thead: [ 1, "<table>", "</table>" ],
|
||||
|
||||
// Some of the following wrappers are not fully defined, because
|
||||
// their parent elements (except for "table" element) could be omitted
|
||||
// since browser parsers are smart enough to auto-insert them
|
||||
|
||||
// Support: Android 2.3
|
||||
// Android browser doesn't auto-insert colgroup
|
||||
col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
|
||||
|
||||
// Auto-insert "tbody" element
|
||||
tr: [ 2, "<table>", "</table>" ],
|
||||
|
||||
// Auto-insert "tbody" and "tr" elements
|
||||
td: [ 3, "<table>", "</table>" ],
|
||||
|
||||
_default: [ 0, "", "" ]
|
||||
};
|
||||
|
||||
// Support: IE9
|
||||
wrapMap.optgroup = wrapMap.option;
|
||||
|
||||
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
|
||||
wrapMap.th = wrapMap.td;
|
||||
|
||||
return wrapMap;
|
||||
});
|
Loading…
Reference in New Issue
Block a user