Skip to content

Commit a74320f

Browse files
committed
Manipulation: privatize buildFragment() function
Fixes gh-2224
1 parent 6d7ef56 commit a74320f

File tree

8 files changed

+199
-157
lines changed

8 files changed

+199
-157
lines changed

src/core/parseHTML.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ define([
22
"../core",
33
"../var/document",
44
"./var/rsingleTag",
5+
"../manipulation/buildFragment",
56

67
// This is the only module that needs core/support
7-
"./support",
8-
9-
// buildFragment
10-
"../manipulation"
11-
], function( jQuery, document, rsingleTag, support ) {
8+
"./support"
9+
], function( jQuery, document, rsingleTag, buildFragment, support ) {
1210

1311
// data: string of html
1412
// context (optional): If specified, the fragment will be created in this context,
@@ -36,7 +34,7 @@ jQuery.parseHTML = function( data, context, keepScripts ) {
3634
return [ context.createElement( parsed[1] ) ];
3735
}
3836

39-
parsed = jQuery.buildFragment( [ data ], context, scripts );
37+
parsed = buildFragment( [ data ], context, scripts );
4038

4139
if ( scripts && scripts.length ) {
4240
jQuery( scripts ).remove();

src/manipulation.js

Lines changed: 13 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ define([
44
"./var/push",
55
"./core/access",
66
"./manipulation/var/rcheckableType",
7+
"./manipulation/var/rtagName",
8+
"./manipulation/var/rscriptType",
9+
"./manipulation/wrapMap",
10+
"./manipulation/getAll",
11+
"./manipulation/setGlobalEval",
12+
"./manipulation/buildFragment",
713
"./manipulation/support",
14+
815
"./data/var/dataPriv",
916
"./data/var/dataUser",
1017

@@ -13,49 +20,18 @@ define([
1320
"./traversing",
1421
"./selector",
1522
"./event"
16-
], function( jQuery, concat, push, access, rcheckableType, support, dataPriv, dataUser ) {
23+
], function( jQuery, concat, push, access,
24+
rcheckableType, rtagName, rscriptType,
25+
wrapMap, getAll, setGlobalEval, buildFragment, support,
26+
dataPriv, dataUser ) {
1727

1828
var
1929
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
20-
rtagName = /<([\w:-]+)/,
21-
rhtml = /<|&#?\w+;/,
2230
rnoInnerhtml = /<(?:script|style|link)/i,
2331
// checked="checked" or checked
2432
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
25-
rscriptType = /^$|\/(?:java|ecma)script/i,
2633
rscriptTypeMasked = /^true\/(.*)/,
27-
rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
28-
29-
// We have to close these tags to support XHTML (#13200)
30-
wrapMap = {
31-
32-
// Support: IE9
33-
option: [ 1, "<select multiple='multiple'>", "</select>" ],
34-
35-
thead: [ 1, "<table>", "</table>" ],
36-
37-
// Some of the following wrappers are not fully defined, because
38-
// their parent elements (except for "table" element) could be omitted
39-
// since browser parsers are smart enough to auto-insert them
40-
41-
// Support: Android 2.3
42-
// Android browser doesn't auto-insert colgroup
43-
col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
44-
45-
// Auto-insert "tbody" element
46-
tr: [ 2, "<table>", "</table>" ],
47-
48-
// Auto-insert "tbody" and "tr" elements
49-
td: [ 3, "<table>", "</table>" ],
50-
51-
_default: [ 0, "", "" ]
52-
};
53-
54-
// Support: IE9
55-
wrapMap.optgroup = wrapMap.option;
56-
57-
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
58-
wrapMap.th = wrapMap.td;
34+
rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
5935

6036
function manipulationTarget( elem, content ) {
6137
if ( jQuery.nodeName( elem, "table" ) &&
@@ -84,18 +60,6 @@ function restoreScript( elem ) {
8460
return elem;
8561
}
8662

87-
// Mark scripts as having already been evaluated
88-
function setGlobalEval( elems, refElements ) {
89-
var i = 0,
90-
l = elems.length;
91-
92-
for ( ; i < l; i++ ) {
93-
dataPriv.set(
94-
elems[ i ], "globalEval", !refElements || dataPriv.get( refElements[ i ], "globalEval" )
95-
);
96-
}
97-
}
98-
9963
function cloneCopyEvent( src, dest ) {
10064
var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
10165

@@ -130,20 +94,6 @@ function cloneCopyEvent( src, dest ) {
13094
}
13195
}
13296

133-
function getAll( context, tag ) {
134-
// Support: IE9-11+
135-
// Use typeof to avoid zero-argument method invocation on host objects (#15151)
136-
var ret = typeof context.getElementsByTagName !== "undefined" ?
137-
context.getElementsByTagName( tag || "*" ) :
138-
typeof context.querySelectorAll !== "undefined" ?
139-
context.querySelectorAll( tag || "*" ) :
140-
[];
141-
142-
return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
143-
jQuery.merge( [ context ], ret ) :
144-
ret;
145-
}
146-
14797
// Fix IE bugs, see support tests
14898
function fixInput( src, dest ) {
14999
var nodeName = dest.nodeName.toLowerCase();
@@ -205,94 +155,6 @@ jQuery.extend({
205155
return clone;
206156
},
207157

208-
buildFragment: function( elems, context, scripts, selection, ignored ) {
209-
var elem, tmp, tag, wrap, contains, j,
210-
fragment = context.createDocumentFragment(),
211-
nodes = [],
212-
i = 0,
213-
l = elems.length;
214-
215-
for ( ; i < l; i++ ) {
216-
elem = elems[ i ];
217-
218-
if ( elem || elem === 0 ) {
219-
220-
// Add nodes directly
221-
if ( jQuery.type( elem ) === "object" ) {
222-
// Support: Android<4.1, PhantomJS<2
223-
// push.apply(_, arraylike) throws on ancient WebKit
224-
jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
225-
226-
// Convert non-html into a text node
227-
} else if ( !rhtml.test( elem ) ) {
228-
nodes.push( context.createTextNode( elem ) );
229-
230-
// Convert html into DOM nodes
231-
} else {
232-
tmp = tmp || fragment.appendChild( context.createElement("div") );
233-
234-
// Deserialize a standard representation
235-
tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
236-
wrap = wrapMap[ tag ] || wrapMap._default;
237-
tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
238-
239-
// Descend through wrappers to the right content
240-
j = wrap[ 0 ];
241-
while ( j-- ) {
242-
tmp = tmp.lastChild;
243-
}
244-
245-
// Support: Android<4.1, PhantomJS<2
246-
// push.apply(_, arraylike) throws on ancient WebKit
247-
jQuery.merge( nodes, tmp.childNodes );
248-
249-
// Remember the top-level container
250-
tmp = fragment.firstChild;
251-
252-
// Ensure the created nodes are orphaned (#12392)
253-
tmp.textContent = "";
254-
}
255-
}
256-
}
257-
258-
// Remove wrapper from fragment
259-
fragment.textContent = "";
260-
261-
i = 0;
262-
while ( (elem = nodes[ i++ ]) ) {
263-
264-
// Skip elements already in the context collection (trac-4087)
265-
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
266-
if ( ignored ) {
267-
ignored.push( elem );
268-
}
269-
continue;
270-
}
271-
272-
contains = jQuery.contains( elem.ownerDocument, elem );
273-
274-
// Append to fragment
275-
tmp = getAll( fragment.appendChild( elem ), "script" );
276-
277-
// Preserve script evaluation history
278-
if ( contains ) {
279-
setGlobalEval( tmp );
280-
}
281-
282-
// Capture executables
283-
if ( scripts ) {
284-
j = 0;
285-
while ( (elem = tmp[ j++ ]) ) {
286-
if ( rscriptType.test( elem.type || "" ) ) {
287-
scripts.push( elem );
288-
}
289-
}
290-
}
291-
}
292-
293-
return fragment;
294-
},
295-
296158
cleanData: function( elems ) {
297159
var data, elem, type,
298160
special = jQuery.event.special,
@@ -500,7 +362,7 @@ jQuery.fn.extend({
500362
}
501363

502364
if ( l ) {
503-
fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this, ignored );
365+
fragment = buildFragment( args, this[ 0 ].ownerDocument, false, this, ignored );
504366
first = fragment.firstChild;
505367

506368
if ( fragment.childNodes.length === 1 ) {

src/manipulation/buildFragment.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
define([
2+
"../core",
3+
"./var/rtagName",
4+
"./var/rscriptType",
5+
"./wrapMap",
6+
"./getAll",
7+
"./setGlobalEval"
8+
], function( jQuery, rtagName, rscriptType, wrapMap, getAll, setGlobalEval ) {
9+
10+
var rhtml = /<|&#?\w+;/;
11+
12+
function buildFragment( elems, context, scripts, selection, ignored ) {
13+
var elem, tmp, tag, wrap, contains, j,
14+
fragment = context.createDocumentFragment(),
15+
nodes = [],
16+
i = 0,
17+
l = elems.length;
18+
19+
for ( ; i < l; i++ ) {
20+
elem = elems[ i ];
21+
22+
if ( elem || elem === 0 ) {
23+
24+
// Add nodes directly
25+
if ( jQuery.type( elem ) === "object" ) {
26+
// Support: Android<4.1, PhantomJS<2
27+
// push.apply(_, arraylike) throws on ancient WebKit
28+
jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
29+
30+
// Convert non-html into a text node
31+
} else if ( !rhtml.test( elem ) ) {
32+
nodes.push( context.createTextNode( elem ) );
33+
34+
// Convert html into DOM nodes
35+
} else {
36+
tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
37+
38+
// Deserialize a standard representation
39+
tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
40+
wrap = wrapMap[ tag ] || wrapMap._default;
41+
tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
42+
43+
// Descend through wrappers to the right content
44+
j = wrap[ 0 ];
45+
while ( j-- ) {
46+
tmp = tmp.lastChild;
47+
}
48+
49+
// Support: Android<4.1, PhantomJS<2
50+
// push.apply(_, arraylike) throws on ancient WebKit
51+
jQuery.merge( nodes, tmp.childNodes );
52+
53+
// Remember the top-level container
54+
tmp = fragment.firstChild;
55+
56+
// Ensure the created nodes are orphaned (#12392)
57+
tmp.textContent = "";
58+
}
59+
}
60+
}
61+
62+
// Remove wrapper from fragment
63+
fragment.textContent = "";
64+
65+
i = 0;
66+
while ( ( elem = nodes[ i++ ] ) ) {
67+
68+
// Skip elements already in the context collection (trac-4087)
69+
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
70+
if ( ignored ) {
71+
ignored.push( elem );
72+
}
73+
continue;
74+
}
75+
76+
contains = jQuery.contains( elem.ownerDocument, elem );
77+
78+
// Append to fragment
79+
tmp = getAll( fragment.appendChild( elem ), "script" );
80+
81+
// Preserve script evaluation history
82+
if ( contains ) {
83+
setGlobalEval( tmp );
84+
}
85+
86+
// Capture executables
87+
if ( scripts ) {
88+
j = 0;
89+
while ( ( elem = tmp[ j++ ] ) ) {
90+
if ( rscriptType.test( elem.type || "" ) ) {
91+
scripts.push( elem );
92+
}
93+
}
94+
}
95+
}
96+
97+
return fragment;
98+
}
99+
100+
return buildFragment;
101+
});

src/manipulation/getAll.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
define([
2+
"../core"
3+
], function( jQuery ) {
4+
5+
function getAll( context, tag ) {
6+
// Support: IE9-11+
7+
// Use typeof to avoid zero-argument method invocation on host objects (#15151)
8+
var ret = typeof context.getElementsByTagName !== "undefined" ?
9+
context.getElementsByTagName( tag || "*" ) :
10+
typeof context.querySelectorAll !== "undefined" ?
11+
context.querySelectorAll( tag || "*" ) :
12+
[];
13+
14+
return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
15+
jQuery.merge( [ context ], ret ) :
16+
ret;
17+
}
18+
19+
return getAll;
20+
});

src/manipulation/setGlobalEval.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
define([
2+
"../data/var/dataPriv"
3+
], function( dataPriv ) {
4+
5+
// Mark scripts as having already been evaluated
6+
function setGlobalEval( elems, refElements ) {
7+
var i = 0,
8+
l = elems.length;
9+
10+
for ( ; i < l; i++ ) {
11+
dataPriv.set(
12+
elems[ i ],
13+
"globalEval",
14+
!refElements || dataPriv.get( refElements[ i ], "globalEval" )
15+
);
16+
}
17+
}
18+
19+
return setGlobalEval;
20+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
define(function() {
2+
return ( /^$|\/(?:java|ecma)script/i );
3+
});

src/manipulation/var/rtagName.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
define(function() {
2+
return ( /<([\w:-]+)/ );
3+
});

0 commit comments

Comments
 (0)