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
b9b5c23fd7
commit
63c1414a54
@ -1,13 +1,11 @@
|
||||
define([
|
||||
"../core",
|
||||
"./var/rsingleTag",
|
||||
"../manipulation/buildFragment",
|
||||
|
||||
// This is the only module that needs core/support
|
||||
"./support",
|
||||
|
||||
// buildFragment
|
||||
"../manipulation"
|
||||
], function( jQuery, rsingleTag, support ) {
|
||||
"./support"
|
||||
], function( jQuery, rsingleTag, buildFragment, support ) {
|
||||
|
||||
// data: string of html
|
||||
// context (optional): If specified, the fragment will be created in this context,
|
||||
@ -35,7 +33,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,17 @@ define([
|
||||
"./var/push",
|
||||
"./var/deletedIds",
|
||||
"./core/access",
|
||||
|
||||
"./manipulation/var/rcheckableType",
|
||||
"./manipulation/var/rtagName",
|
||||
"./manipulation/var/rscriptType",
|
||||
"./manipulation/var/rleadingWhitespace",
|
||||
"./manipulation/var/nodeNames",
|
||||
"./manipulation/createSafeFragment",
|
||||
"./manipulation/wrapMap",
|
||||
"./manipulation/getAll",
|
||||
"./manipulation/setGlobalEval",
|
||||
"./manipulation/buildFragment",
|
||||
"./manipulation/support",
|
||||
|
||||
"./core/init",
|
||||
@ -12,96 +22,22 @@ define([
|
||||
"./traversing",
|
||||
"./selector",
|
||||
"./event"
|
||||
], function( jQuery, concat, push, deletedIds, access, rcheckableType, support ) {
|
||||
], function( jQuery, concat, push, deletedIds, access,
|
||||
rcheckableType, rtagName, rscriptType, rleadingWhitespace, nodeNames,
|
||||
createSafeFragment, wrapMap, getAll, setGlobalEval,
|
||||
buildFragment, support ) {
|
||||
|
||||
function createSafeFragment( document ) {
|
||||
var list = nodeNames.split( "|" ),
|
||||
safeFrag = document.createDocumentFragment();
|
||||
|
||||
if ( safeFrag.createElement ) {
|
||||
while ( list.length ) {
|
||||
safeFrag.createElement(
|
||||
list.pop()
|
||||
);
|
||||
}
|
||||
}
|
||||
return safeFrag;
|
||||
}
|
||||
|
||||
var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|" +
|
||||
"details|dialog|figcaption|figure|footer|header|hgroup|main|" +
|
||||
"mark|meter|nav|output|picture|progress|section|summary|template|time|video",
|
||||
rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
|
||||
rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
|
||||
rleadingWhitespace = /^\s+/,
|
||||
var rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
|
||||
rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ),
|
||||
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 = {
|
||||
option: [ 1, "<select multiple='multiple'>", "</select>" ],
|
||||
|
||||
// Support: IE8
|
||||
param: [ 1, "<object>", "</object>" ],
|
||||
|
||||
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>" ],
|
||||
|
||||
// IE8 can't serialize link, script, style, or any html5 (NoScope) tags,
|
||||
// unless wrapped in a div with non-breaking characters in front of it.
|
||||
_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
|
||||
},
|
||||
safeFragment = createSafeFragment( document ),
|
||||
fragmentDiv = safeFragment.appendChild( document.createElement("div") );
|
||||
|
||||
wrapMap.optgroup = wrapMap.option;
|
||||
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
|
||||
wrapMap.th = wrapMap.td;
|
||||
|
||||
function getAll( context, tag ) {
|
||||
var elems, elem,
|
||||
i = 0,
|
||||
found = typeof context.getElementsByTagName !== "undefined" ?
|
||||
context.getElementsByTagName( tag || "*" ) :
|
||||
typeof context.querySelectorAll !== "undefined" ?
|
||||
context.querySelectorAll( tag || "*" ) :
|
||||
undefined;
|
||||
|
||||
if ( !found ) {
|
||||
for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
|
||||
if ( !tag || jQuery.nodeName( elem, tag ) ) {
|
||||
found.push( elem );
|
||||
} else {
|
||||
jQuery.merge( found, getAll( elem, tag ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
|
||||
jQuery.merge( [ context ], found ) :
|
||||
found;
|
||||
}
|
||||
|
||||
// Manipulating tables requires a tbody
|
||||
function manipulationTarget( elem, content ) {
|
||||
if ( jQuery.nodeName( elem, "table" ) &&
|
||||
@ -128,21 +64,7 @@ function restoreScript( elem ) {
|
||||
return elem;
|
||||
}
|
||||
|
||||
// Mark scripts as having already been evaluated
|
||||
function setGlobalEval( elems, refElements ) {
|
||||
var elem,
|
||||
i = 0;
|
||||
for ( ; (elem = elems[i]) != null; i++ ) {
|
||||
jQuery._data(
|
||||
elem,
|
||||
"globalEval",
|
||||
!refElements || jQuery._data( refElements[i], "globalEval" )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function cloneCopyEvent( src, dest ) {
|
||||
|
||||
if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
|
||||
return;
|
||||
}
|
||||
@ -278,107 +200,6 @@ jQuery.extend({
|
||||
return clone;
|
||||
},
|
||||
|
||||
buildFragment: function( elems, context, scripts, selection, ignored ) {
|
||||
var j, elem, contains,
|
||||
tmp, tag, wrap,
|
||||
l = elems.length,
|
||||
|
||||
// Ensure a safe fragment
|
||||
safe = createSafeFragment( context ),
|
||||
nodes = [],
|
||||
i = 0;
|
||||
|
||||
for ( ; i < l; i++ ) {
|
||||
elem = elems[ i ];
|
||||
|
||||
if ( elem || elem === 0 ) {
|
||||
|
||||
// Add nodes directly
|
||||
if ( jQuery.type( elem ) === "object" ) {
|
||||
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 || safe.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;
|
||||
}
|
||||
|
||||
// Manually add leading whitespace removed by IE
|
||||
if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
|
||||
nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
|
||||
}
|
||||
|
||||
jQuery.merge( nodes, tmp.childNodes );
|
||||
|
||||
// Fix #12392 for WebKit and IE > 9
|
||||
tmp.textContent = "";
|
||||
|
||||
// Fix #12392 for oldIE
|
||||
while ( tmp.firstChild ) {
|
||||
tmp.removeChild( tmp.firstChild );
|
||||
}
|
||||
|
||||
// Remember the top-level container for proper cleanup
|
||||
tmp = safe.lastChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fix #11356: Clear elements from fragment
|
||||
if ( tmp ) {
|
||||
safe.removeChild( tmp );
|
||||
}
|
||||
|
||||
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( safe.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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp = null;
|
||||
|
||||
return safe;
|
||||
},
|
||||
|
||||
cleanData: function( elems, /* internal */ acceptData ) {
|
||||
var elem, type, id, data,
|
||||
i = 0,
|
||||
@ -626,7 +447,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 ) {
|
||||
|
118
src/manipulation/buildFragment.js
Normal file
118
src/manipulation/buildFragment.js
Normal file
@ -0,0 +1,118 @@
|
||||
define([
|
||||
"../core",
|
||||
"./var/rtagName",
|
||||
"./var/rscriptType",
|
||||
"./var/rleadingWhitespace",
|
||||
"./createSafeFragment",
|
||||
"./wrapMap",
|
||||
"./getAll",
|
||||
"./setGlobalEval",
|
||||
"./support"
|
||||
], function( jQuery, rtagName, rscriptType, rleadingWhitespace,
|
||||
createSafeFragment, wrapMap, getAll, setGlobalEval, support ) {
|
||||
|
||||
var rhtml = /<|&#?\w+;/;
|
||||
|
||||
function buildFragment( elems, context, scripts, selection, ignored ) {
|
||||
var j, elem, contains,
|
||||
tmp, tag, wrap,
|
||||
l = elems.length,
|
||||
|
||||
// Ensure a safe fragment
|
||||
safe = createSafeFragment( context ),
|
||||
nodes = [],
|
||||
i = 0;
|
||||
|
||||
for ( ; i < l; i++ ) {
|
||||
elem = elems[ i ];
|
||||
|
||||
if ( elem || elem === 0 ) {
|
||||
|
||||
// Add nodes directly
|
||||
if ( jQuery.type( elem ) === "object" ) {
|
||||
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 || safe.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;
|
||||
}
|
||||
|
||||
// Manually add leading whitespace removed by IE
|
||||
if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
|
||||
nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
|
||||
}
|
||||
|
||||
jQuery.merge( nodes, tmp.childNodes );
|
||||
|
||||
// Fix #12392 for WebKit and IE > 9
|
||||
tmp.textContent = "";
|
||||
|
||||
// Fix #12392 for oldIE
|
||||
while ( tmp.firstChild ) {
|
||||
tmp.removeChild( tmp.firstChild );
|
||||
}
|
||||
|
||||
// Remember the top-level container for proper cleanup
|
||||
tmp = safe.lastChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fix #11356: Clear elements from fragment
|
||||
if ( tmp ) {
|
||||
safe.removeChild( tmp );
|
||||
}
|
||||
|
||||
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( safe.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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp = null;
|
||||
|
||||
return safe;
|
||||
}
|
||||
|
||||
return buildFragment;
|
||||
});
|
20
src/manipulation/createSafeFragment.js
Normal file
20
src/manipulation/createSafeFragment.js
Normal file
@ -0,0 +1,20 @@
|
||||
define([
|
||||
"./var/nodeNames"
|
||||
], function( nodeNames ) {
|
||||
|
||||
function createSafeFragment( document ) {
|
||||
var list = nodeNames.split( "|" ),
|
||||
safeFrag = document.createDocumentFragment();
|
||||
|
||||
if ( safeFrag.createElement ) {
|
||||
while ( list.length ) {
|
||||
safeFrag.createElement(
|
||||
list.pop()
|
||||
);
|
||||
}
|
||||
}
|
||||
return safeFrag;
|
||||
}
|
||||
|
||||
return createSafeFragment;
|
||||
});
|
33
src/manipulation/getAll.js
Normal file
33
src/manipulation/getAll.js
Normal file
@ -0,0 +1,33 @@
|
||||
define([
|
||||
"../core"
|
||||
], function( jQuery ) {
|
||||
|
||||
function getAll( context, tag ) {
|
||||
var elems, elem,
|
||||
i = 0,
|
||||
found = typeof context.getElementsByTagName !== "undefined" ?
|
||||
context.getElementsByTagName( tag || "*" ) :
|
||||
typeof context.querySelectorAll !== "undefined" ?
|
||||
context.querySelectorAll( tag || "*" ) :
|
||||
undefined;
|
||||
|
||||
if ( !found ) {
|
||||
for ( found = [], elems = context.childNodes || context;
|
||||
( elem = elems[i] ) != null;
|
||||
i++
|
||||
) {
|
||||
if ( !tag || jQuery.nodeName( elem, tag ) ) {
|
||||
found.push( elem );
|
||||
} else {
|
||||
jQuery.merge( found, getAll( elem, tag ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
|
||||
jQuery.merge( [ context ], found ) :
|
||||
found;
|
||||
}
|
||||
|
||||
return getAll;
|
||||
});
|
19
src/manipulation/setGlobalEval.js
Normal file
19
src/manipulation/setGlobalEval.js
Normal file
@ -0,0 +1,19 @@
|
||||
define([
|
||||
"../core"
|
||||
], function( jQuery ) {
|
||||
|
||||
// Mark scripts as having already been evaluated
|
||||
function setGlobalEval( elems, refElements ) {
|
||||
var elem,
|
||||
i = 0;
|
||||
for ( ; ( elem = elems[i] ) != null; i++ ) {
|
||||
jQuery._data(
|
||||
elem,
|
||||
"globalEval",
|
||||
!refElements || jQuery._data( refElements[i], "globalEval" )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return setGlobalEval;
|
||||
});
|
5
src/manipulation/var/nodeNames.js
Normal file
5
src/manipulation/var/nodeNames.js
Normal file
@ -0,0 +1,5 @@
|
||||
define(function() {
|
||||
return "abbr|article|aside|audio|bdi|canvas|data|datalist|" +
|
||||
"details|dialog|figcaption|figure|footer|header|hgroup|main|" +
|
||||
"mark|meter|nav|output|picture|progress|section|summary|template|time|video";
|
||||
});
|
3
src/manipulation/var/rleadingWhitespace.js
Normal file
3
src/manipulation/var/rleadingWhitespace.js
Normal file
@ -0,0 +1,3 @@
|
||||
define(function() {
|
||||
return ( /^\s+/ );
|
||||
});
|
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:-]+)/ );
|
||||
});
|
40
src/manipulation/wrapMap.js
Normal file
40
src/manipulation/wrapMap.js
Normal file
@ -0,0 +1,40 @@
|
||||
define([
|
||||
"./support"
|
||||
], function( support ) {
|
||||
|
||||
// We have to close these tags to support XHTML (#13200)
|
||||
var wrapMap = {
|
||||
option: [ 1, "<select multiple='multiple'>", "</select>" ],
|
||||
|
||||
// Support: IE8
|
||||
param: [ 1, "<object>", "</object>" ],
|
||||
|
||||
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>" ],
|
||||
|
||||
// IE8 can't serialize link, script, style, or any html5 (NoScope) tags,
|
||||
// unless wrapped in a div with non-breaking characters in front of it.
|
||||
_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
|
||||
};
|
||||
|
||||
// Support: IE8-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