Skip to content

Commit 7c26a1e

Browse files
Ensure Element#update works with string content that includes a LINK tag in Internet Explorer. [prototypejs#264 state:resolved] (Tobias H. Michaelsen, Andrew Dupont)
1 parent e65e921 commit 7c26a1e

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Ensure `Element#update` works with string content that includes a LINK tag in Internet Explorer. [#264 state:resolved] (Tobias H. Michaelsen, Andrew Dupont)
2+
13
* Treat a 304 HTTP status as a successful response. [#331 state:resolved] (Kenneth Kin Lum, Andrew Dupont)
24

35
* Handle sparse arrays properly in `Array#_each` to match behavior with browsers' built-in `Array#forEach` (and ES5). [#790 state:resolved] (Andriy Tyurnikov, Yaffle, Andrew Dupont)

src/dom/dom.js

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,21 @@ Element.Methods = {
568568
return true;
569569
}
570570
})();
571+
572+
var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
573+
try {
574+
var el = document.createElement('div');
575+
el.innerHTML = "<link>";
576+
var isBuggy = (el.childNodes.length === 0);
577+
el = null;
578+
return isBuggy;
579+
} catch(e) {
580+
return true;
581+
}
582+
})();
583+
584+
var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
585+
TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
571586

572587
var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
573588
var s = document.createElement("script"),
@@ -582,6 +597,7 @@ Element.Methods = {
582597
s = null;
583598
return isBuggy;
584599
})();
600+
585601

586602
function update(element, content) {
587603
element = $(element);
@@ -610,7 +626,7 @@ Element.Methods = {
610626
return element;
611627
}
612628

613-
if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
629+
if (ANY_INNERHTML_BUGGY) {
614630
if (tagName in Element._insertionTranslations.tags) {
615631
while (element.firstChild) {
616632
element.removeChild(element.firstChild);
@@ -619,6 +635,16 @@ Element.Methods = {
619635
.each(function(node) {
620636
element.appendChild(node)
621637
});
638+
} else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
639+
// IE barfs when inserting a string that beings with a LINK
640+
// element. The workaround is to add any content to the beginning
641+
// of the string; we'll be inserting a text node (see
642+
// Element._getContentFromAnonymousElement below).
643+
while (element.firstChild) {
644+
element.removeChild(element.firstChild);
645+
}
646+
var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
647+
nodes.each(function(node) { element.appendChild(node) });
622648
}
623649
else {
624650
element.innerHTML = content.stripScripts();
@@ -2966,11 +2992,22 @@ Element._returnOffset = function(l, t) {
29662992
return result;
29672993
};
29682994

2969-
Element._getContentFromAnonymousElement = function(tagName, html) {
2995+
Element._getContentFromAnonymousElement = function(tagName, html, force) {
29702996
var div = new Element('div'),
29712997
t = Element._insertionTranslations.tags[tagName];
2972-
if (t) {
2973-
div.innerHTML = t[0] + html + t[1];
2998+
2999+
var workaround = false;
3000+
if (t) workaround = true;
3001+
else if (force) {
3002+
workaround = true;
3003+
t = ['', '', 0];
3004+
}
3005+
3006+
if (workaround) {
3007+
// Adding a text node to the beginning of the string (then removing it)
3008+
// fixes an issue in Internet Explorer. See Element#update above.
3009+
div.innerHTML = '&nbsp;' + t[0] + html + t[1];
3010+
div.removeChild(div.firstChild);
29743011
for (var i = t[2]; i--; ) {
29753012
div = div.firstChild;
29763013
}

test/unit/dom_test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,23 @@ new Test.Unit.Runner({
362362
select.update('<option value="3">option 3</option><option selected="selected">option 4</option>');
363363
this.assertEqual('option 4', select.getValue());
364364
},
365+
366+
testElementUpdateWithLinkTag: function() {
367+
var div = new Element('div');
368+
div.update('<link rel="stylesheet" />');
369+
this.assertEqual(1, div.childNodes.length);
370+
var link = div.down('link');
371+
this.assert(link);
372+
this.assert(link.rel === 'stylesheet');
373+
374+
div.update('<p><link rel="stylesheet"></p>')
375+
this.assertEqual(1, div.childNodes.length);
376+
this.assertEqual(1, div.firstChild.childNodes.length);
377+
378+
var link = div.down('link');
379+
this.assert(link);
380+
this.assert(link.rel === 'stylesheet');
381+
},
365382

366383
testElementUpdateWithDOMNode: function() {
367384
$('testdiv').update(new Element('div').insert('bla'));

0 commit comments

Comments
 (0)