prototype: Make Element#insert standard-compliant. Fixes an issue in FF3b2 when inserting HTML or text inside DOM nodes which aren't (yet) appended to the document.
This commit is contained in:
parent
f553d2210e
commit
b4735bca7c
@ -1,5 +1,7 @@
|
||||
*SVN*
|
||||
|
||||
* Make Element#insert standard-compliant. Fixes an issue in FF3b2 when inserting HTML or text inside DOM nodes which aren't (yet) appended to the document. [Tobie Langel]
|
||||
|
||||
* Add some missing semicolons to the source tree. Closes #10659. [Richard Quadling]
|
||||
|
||||
* Ensure Ajax.Response#getHeader returns null for missing headers in Opera. [Tobie Langel]
|
||||
|
101
src/dom.js
101
src/dom.js
@ -119,24 +119,28 @@ Element.Methods = {
|
||||
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
|
||||
insertions = {bottom:insertions};
|
||||
|
||||
var content, t, range;
|
||||
var content, insert, tagName, childNodes;
|
||||
|
||||
for (position in insertions) {
|
||||
content = insertions[position];
|
||||
position = position.toLowerCase();
|
||||
t = Element._insertionTranslations[position];
|
||||
insert = Element._insertionTranslations[position];
|
||||
|
||||
if (content && content.toElement) content = content.toElement();
|
||||
if (Object.isElement(content)) {
|
||||
t.insert(element, content);
|
||||
insert(element, content);
|
||||
continue;
|
||||
}
|
||||
|
||||
content = Object.toHTML(content);
|
||||
|
||||
range = element.ownerDocument.createRange();
|
||||
t.initializeRange(element, range);
|
||||
t.insert(element, range.createContextualFragment(content.stripScripts()));
|
||||
tagName = ((position == 'before' || position == 'after')
|
||||
? element.parentNode : element).tagName.toUpperCase();
|
||||
|
||||
childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
|
||||
|
||||
if (position == 'top' || position == 'after') childNodes.reverse();
|
||||
childNodes.each(insert.curry(element));
|
||||
|
||||
content.evalScripts.bind(content).defer();
|
||||
}
|
||||
@ -663,46 +667,6 @@ Element._attributeTranslations = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (!document.createRange || Prototype.Browser.Opera) {
|
||||
Element.Methods.insert = function(element, insertions) {
|
||||
element = $(element);
|
||||
|
||||
if (Object.isString(insertions) || Object.isNumber(insertions) ||
|
||||
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
|
||||
insertions = { bottom: insertions };
|
||||
|
||||
var t = Element._insertionTranslations, content, position, pos, tagName;
|
||||
|
||||
for (position in insertions) {
|
||||
content = insertions[position];
|
||||
position = position.toLowerCase();
|
||||
pos = t[position];
|
||||
|
||||
if (content && content.toElement) content = content.toElement();
|
||||
if (Object.isElement(content)) {
|
||||
pos.insert(element, content);
|
||||
continue;
|
||||
}
|
||||
|
||||
content = Object.toHTML(content);
|
||||
tagName = ((position == 'before' || position == 'after')
|
||||
? element.parentNode : element).tagName.toUpperCase();
|
||||
|
||||
if (t.tags[tagName]) {
|
||||
var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
|
||||
if (position == 'top' || position == 'after') fragments.reverse();
|
||||
fragments.each(pos.insert.curry(element));
|
||||
}
|
||||
else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
|
||||
|
||||
content.evalScripts.bind(content).defer();
|
||||
}
|
||||
|
||||
return element;
|
||||
};
|
||||
}
|
||||
|
||||
if (Prototype.Browser.Opera) {
|
||||
Element.Methods.getStyle = Element.Methods.getStyle.wrap(
|
||||
function(proceed, element, style) {
|
||||
@ -992,45 +956,25 @@ Element._returnOffset = function(l, t) {
|
||||
|
||||
Element._getContentFromAnonymousElement = function(tagName, html) {
|
||||
var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
|
||||
div.innerHTML = t[0] + html + t[1];
|
||||
t[2].times(function() { div = div.firstChild });
|
||||
if (t) {
|
||||
div.innerHTML = t[0] + html + t[1];
|
||||
t[2].times(function() { div = div.firstChild });
|
||||
} else div.innerHTML = html;
|
||||
return $A(div.childNodes);
|
||||
};
|
||||
|
||||
Element._insertionTranslations = {
|
||||
before: {
|
||||
adjacency: 'beforeBegin',
|
||||
insert: function(element, node) {
|
||||
element.parentNode.insertBefore(node, element);
|
||||
},
|
||||
initializeRange: function(element, range) {
|
||||
range.setStartBefore(element);
|
||||
}
|
||||
before: function(element, node) {
|
||||
element.parentNode.insertBefore(node, element);
|
||||
},
|
||||
top: {
|
||||
adjacency: 'afterBegin',
|
||||
insert: function(element, node) {
|
||||
element.insertBefore(node, element.firstChild);
|
||||
},
|
||||
initializeRange: function(element, range) {
|
||||
range.selectNodeContents(element);
|
||||
range.collapse(true);
|
||||
}
|
||||
top: function(element, node) {
|
||||
element.insertBefore(node, element.firstChild);
|
||||
},
|
||||
bottom: {
|
||||
adjacency: 'beforeEnd',
|
||||
insert: function(element, node) {
|
||||
element.appendChild(node);
|
||||
}
|
||||
bottom: function(element, node) {
|
||||
element.appendChild(node);
|
||||
},
|
||||
after: {
|
||||
adjacency: 'afterEnd',
|
||||
insert: function(element, node) {
|
||||
element.parentNode.insertBefore(node, element.nextSibling);
|
||||
},
|
||||
initializeRange: function(element, range) {
|
||||
range.setStartAfter(element);
|
||||
}
|
||||
after: function(element, node) {
|
||||
element.parentNode.insertBefore(node, element.nextSibling);
|
||||
},
|
||||
tags: {
|
||||
TABLE: ['<table>', '</table>', 1],
|
||||
@ -1042,7 +986,6 @@ Element._insertionTranslations = {
|
||||
};
|
||||
|
||||
(function() {
|
||||
this.bottom.initializeRange = this.top.initializeRange;
|
||||
Object.extend(this.tags, {
|
||||
THEAD: this.tags.TBODY,
|
||||
TFOOT: this.tags.TBODY,
|
||||
|
@ -596,6 +596,22 @@
|
||||
assertEqual('test1337', getInnerHTML('element-insertions-main'));
|
||||
}},
|
||||
|
||||
testNewElementInsert: function() {with(this) {
|
||||
var container = new Element('div');
|
||||
element = new Element('div');
|
||||
container.insert(element);
|
||||
|
||||
element.insert({ before: '<p>a paragraph</p>' });
|
||||
assertEqual('<p>a paragraph</p><div></div>', getInnerHTML(container));
|
||||
element.insert({ after: 'some text' });
|
||||
assertEqual('<p>a paragraph</p><div></div>some text', getInnerHTML(container));
|
||||
|
||||
element.insert({ top: '<p>a paragraph</p>' });
|
||||
assertEqual('<p>a paragraph</p>', getInnerHTML(element));
|
||||
element.insert('some text');
|
||||
assertEqual('<p>a paragraph</p>some text', getInnerHTML(element));
|
||||
}},
|
||||
|
||||
testInsertionBackwardsCompatibility: function() {with(this) {
|
||||
new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before');
|
||||
assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing before'));
|
||||
|
Loading…
Reference in New Issue
Block a user