Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Ensure `Element#update` works with string content that includes a LIN…

…K tag in Internet Explorer. [#264 state:resolved] (Tobias H. Michaelsen, Andrew Dupont)
  • Loading branch information...
commit 7c26a1e7cf891d74e2d2c32b238979e44e3cee19 1 parent e65e921
@savetheclocktower savetheclocktower authored
Showing with 60 additions and 4 deletions.
  1. +2 −0  CHANGELOG
  2. +41 −4 src/dom/dom.js
  3. +17 −0 test/unit/dom_test.js
View
2  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)
View
45 src/dom/dom.js
@@ -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"),
@@ -582,6 +597,7 @@ Element.Methods = {
s = null;
return isBuggy;
})();
+
function update(element, content) {
element = $(element);
@@ -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);
@@ -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();
@@ -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;
}
View
17 test/unit/dom_test.js
@@ -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'));
Please sign in to comment.
Something went wrong with that request. Please try again.