Skip to content

Commit

Permalink
Ensure Element#update works with string content that includes a LIN…
Browse files Browse the repository at this point in the history
…K tag in Internet Explorer. [#264 state:resolved] (Tobias H. Michaelsen, Andrew Dupont)
  • Loading branch information
savetheclocktower committed Nov 2, 2010
1 parent e65e921 commit 7c26a1e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -1,3 +1,5 @@
* Ensure `Element#update` works with string content that includes a LINK tag in Internet Explorer. [#264 state:resolved] (Tobias H. Michaelsen, Andrew Dupont)

* Treat a 304 HTTP status as a successful response. [#331 state:resolved] (Kenneth Kin Lum, Andrew Dupont)

* 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)
Expand Down
45 changes: 41 additions & 4 deletions src/dom/dom.js
Expand Up @@ -568,6 +568,21 @@ Element.Methods = {
return true;
}
})();

var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
try {
var el = document.createElement('div');
el.innerHTML = "<link>";
var isBuggy = (el.childNodes.length === 0);
el = null;
return isBuggy;
} catch(e) {
return true;
}
})();

var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;

var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
var s = document.createElement("script"),
Expand All @@ -582,6 +597,7 @@ Element.Methods = {
s = null;
return isBuggy;
})();


function update(element, content) {
element = $(element);
Expand Down Expand Up @@ -610,7 +626,7 @@ Element.Methods = {
return element;
}

if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
if (ANY_INNERHTML_BUGGY) {
if (tagName in Element._insertionTranslations.tags) {
while (element.firstChild) {
element.removeChild(element.firstChild);
Expand All @@ -619,6 +635,16 @@ Element.Methods = {
.each(function(node) {
element.appendChild(node)
});
} else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
// IE barfs when inserting a string that beings with a LINK
// element. The workaround is to add any content to the beginning
// of the string; we'll be inserting a text node (see
// Element._getContentFromAnonymousElement below).
while (element.firstChild) {
element.removeChild(element.firstChild);
}
var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
nodes.each(function(node) { element.appendChild(node) });
}
else {
element.innerHTML = content.stripScripts();
Expand Down Expand Up @@ -2966,11 +2992,22 @@ Element._returnOffset = function(l, t) {
return result;
};

Element._getContentFromAnonymousElement = function(tagName, html) {
Element._getContentFromAnonymousElement = function(tagName, html, force) {
var div = new Element('div'),
t = Element._insertionTranslations.tags[tagName];
if (t) {
div.innerHTML = t[0] + html + t[1];

var workaround = false;
if (t) workaround = true;
else if (force) {
workaround = true;
t = ['', '', 0];
}

if (workaround) {
// Adding a text node to the beginning of the string (then removing it)
// fixes an issue in Internet Explorer. See Element#update above.
div.innerHTML = '&nbsp;' + t[0] + html + t[1];
div.removeChild(div.firstChild);
for (var i = t[2]; i--; ) {
div = div.firstChild;
}
Expand Down
17 changes: 17 additions & 0 deletions test/unit/dom_test.js
Expand Up @@ -362,6 +362,23 @@ new Test.Unit.Runner({
select.update('<option value="3">option 3</option><option selected="selected">option 4</option>');
this.assertEqual('option 4', select.getValue());
},

testElementUpdateWithLinkTag: function() {
var div = new Element('div');
div.update('<link rel="stylesheet" />');
this.assertEqual(1, div.childNodes.length);
var link = div.down('link');
this.assert(link);
this.assert(link.rel === 'stylesheet');

div.update('<p><link rel="stylesheet"></p>')
this.assertEqual(1, div.childNodes.length);
this.assertEqual(1, div.firstChild.childNodes.length);

var link = div.down('link');
this.assert(link);
this.assert(link.rel === 'stylesheet');
},

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

0 comments on commit 7c26a1e

Please sign in to comment.