90
90
* - [`val()`](http://api.jquery.com/val/)
91
91
* - [`wrap()`](http://api.jquery.com/wrap/)
92
92
*
93
+ * jqLite also provides a method restoring pre-1.8 insecure treatment of XHTML-like tags.
94
+ * This legacy behavior turns input like `<div /><span />` to `<div></div><span></span>`
95
+ * instead of `<div><span></span></div>` like version 1.8 & newer do. To restore it, invoke:
96
+ * ```js
97
+ * angular.UNSAFE_restoreLegacyJqLiteXHTMLReplacement();
98
+ * ```
99
+ * Note that this only patches jqLite. If you use jQuery 3.5.0 or newer, please read the
100
+ * [jQuery 3.5 upgrade guide](https://jquery.com/upgrade-guide/3.5/) for more details
101
+ * about the workarounds.
102
+ *
93
103
* ## jQuery/jqLite Extras
94
104
* AngularJS also provides the following additional methods and events to both jQuery and jqLite:
95
105
*
@@ -169,20 +179,36 @@ var HTML_REGEXP = /<|&#?\w+;/;
169
179
var TAG_NAME_REGEXP = / < ( [ \w : - ] + ) / ;
170
180
var XHTML_TAG_REGEXP = / < (? ! a r e a | b r | c o l | e m b e d | h r | i m g | i n p u t | l i n k | m e t a | p a r a m ) ( ( [ \w : - ] + ) [ ^ > ] * ) \/ > / gi;
171
181
182
+ // Table parts need to be wrapped with `<table>` or they're
183
+ // stripped to their contents when put in a div.
184
+ // XHTML parsers do not magically insert elements in the
185
+ // same way that tag soup parsers do, so we cannot shorten
186
+ // this by omitting <tbody> or other required elements.
172
187
var wrapMap = {
173
- 'option' : [ 1 , '<select multiple="multiple">' , '</select>' ] ,
174
-
175
- 'thead' : [ 1 , '<table>' , '</table>' ] ,
176
- 'col' : [ 2 , '<table><colgroup>' , '</colgroup></table>' ] ,
177
- 'tr' : [ 2 , '<table><tbody>' , '</tbody></table>' ] ,
178
- 'td' : [ 3 , '<table><tbody><tr>' , '</tr></tbody></table>' ] ,
179
- '_default' : [ 0 , '' , '' ]
188
+ thead : [ 'table' ] ,
189
+ col : [ 'colgroup' , 'table' ] ,
190
+ tr : [ 'tbody' , 'table' ] ,
191
+ td : [ 'tr' , 'tbody' , 'table' ]
180
192
} ;
181
193
182
- wrapMap . optgroup = wrapMap . option ;
183
194
wrapMap . tbody = wrapMap . tfoot = wrapMap . colgroup = wrapMap . caption = wrapMap . thead ;
184
195
wrapMap . th = wrapMap . td ;
185
196
197
+ // Support: IE <10 only
198
+ // IE 9 requires an option wrapper & it needs to have the whole table structure
199
+ // set up in advance; assigning `"<td></td>"` to `tr.innerHTML` doesn't work, etc.
200
+ var wrapMapIE9 = {
201
+ option : [ 1 , '<select multiple="multiple">' , '</select>' ] ,
202
+ _default : [ 0 , '' , '' ]
203
+ } ;
204
+
205
+ for ( var key in wrapMap ) {
206
+ var wrapMapValueClosing = wrapMap [ key ] ;
207
+ var wrapMapValue = wrapMapValueClosing . slice ( ) . reverse ( ) ;
208
+ wrapMapIE9 [ key ] = [ wrapMapValue . length , '<' + wrapMapValue . join ( '><' ) + '>' , '</' + wrapMapValueClosing . join ( '></' ) + '>' ] ;
209
+ }
210
+
211
+ wrapMapIE9 . optgroup = wrapMapIE9 . option ;
186
212
187
213
function jqLiteIsTextNode ( html ) {
188
214
return ! HTML_REGEXP . test ( html ) ;
@@ -203,7 +229,7 @@ function jqLiteHasData(node) {
203
229
}
204
230
205
231
function jqLiteBuildFragment ( html , context ) {
206
- var tmp , tag , wrap ,
232
+ var tmp , tag , wrap , finalHtml ,
207
233
fragment = context . createDocumentFragment ( ) ,
208
234
nodes = [ ] , i ;
209
235
@@ -214,13 +240,30 @@ function jqLiteBuildFragment(html, context) {
214
240
// Convert html into DOM nodes
215
241
tmp = fragment . appendChild ( context . createElement ( 'div' ) ) ;
216
242
tag = ( TAG_NAME_REGEXP . exec ( html ) || [ '' , '' ] ) [ 1 ] . toLowerCase ( ) ;
217
- wrap = wrapMap [ tag ] || wrapMap . _default ;
218
- tmp . innerHTML = wrap [ 1 ] + html . replace ( XHTML_TAG_REGEXP , '<$1></$2>' ) + wrap [ 2 ] ;
243
+ finalHtml = JQLite . legacyXHTMLReplacement ?
244
+ html . replace ( XHTML_TAG_REGEXP , '<$1></$2>' ) :
245
+ html ;
246
+
247
+ if ( msie < 10 ) {
248
+ wrap = wrapMapIE9 [ tag ] || wrapMapIE9 . _default ;
249
+ tmp . innerHTML = wrap [ 1 ] + finalHtml + wrap [ 2 ] ;
250
+
251
+ // Descend through wrappers to the right content
252
+ i = wrap [ 0 ] ;
253
+ while ( i -- ) {
254
+ tmp = tmp . firstChild ;
255
+ }
256
+ } else {
257
+ wrap = wrapMap [ tag ] || [ ] ;
219
258
220
- // Descend through wrappers to the right content
221
- i = wrap [ 0 ] ;
222
- while ( i -- ) {
223
- tmp = tmp . lastChild ;
259
+ // Create wrappers & descend into them
260
+ i = wrap . length ;
261
+ while ( -- i > - 1 ) {
262
+ tmp . appendChild ( window . document . createElement ( wrap [ i ] ) ) ;
263
+ tmp = tmp . firstChild ;
264
+ }
265
+
266
+ tmp . innerHTML = finalHtml ;
224
267
}
225
268
226
269
nodes = concat ( nodes , tmp . childNodes ) ;
0 commit comments