Mozilla: innerHTML in application/xhtml+xml
26th October 2005 - 03:24
Я тут поковырялся и наплясал (это про «танцы с бубном») такое дело:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test: Mozilla. innerHTML in application/xhtml+xml</title>
<script type="application/x-javascript"><![CDATA[
//~ (c) Владимир Палант
HTMLParagraphElement.prototype.__defineSetter__('innerHTML', function(str){
str = '<innerRoot xmlns="http://www.w3.org/1999/xhtml">' + str + '</innerRoot>';
var nodes = new DOMParser().parseFromString(str, 'text/xml').documentElement;
if ((nodes.tagName == 'parserError') ||
(nodes.namespaceURI == 'http://www.mozilla.org/newlayout/xml/parsererror.xml'))
return;//~ or alert, warning, etc.
while (this.firstChild)
this.removeChild(this.firstChild);
while (nodes.firstChild)
this.appendChild(nodes.firstChild);
});
window.onload = function() {
var d = document.getElementById('debug');
d.innerHTML = '<strong>STRONG <em>EM</em> BR (before)<br/>BR (after)</strong>';
//~ d.innerHTML = 'Just test 1';
//~ d.innerHTML = 'Just <em/> test 2';
//~ d.innerHTML = 'Just <em> test 3 (error, not worked)';
//~ d.innerHTML = '';
}
]]></script>
</head>
<body><p id="debug">..Load..</p></body>
</html>
Т.е. в том же Prototype можно поменять несколько строк (будет ли это работать и нуждается ли там в замене что-то ещё?.. я не проверял):
//~ ajax.js [line 148 in v1.3.1]
} else {
try {
receiver.innerHTML = response;
} catch(e) {
receiver.__defineSetter__('innerHTML', function(str){
...
});
receiver.innerHTML = response;
}
}
Или прикрутить XBL, чтобы не мучить пользователей других браузеров. Как это хозяйство будет вести себя в Safari? Не знаю.
Вопрос лишь в одном: нужны ли Вам приключения на Вашу Ж? Мне — нет. В большинстве случаев.
PS. Писалось под Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4; в Fx 1.5 innerHTML
должен работать.
Categories: dHtml | comments: (2)
Комментарии
1. Julik 26th October 2005 - 03:52
Напиши про это пожалуйста автору Prototype.
Mash:
А оно ему точно надо?
2. Владимир Палант 15th January 2006 - 22:54
Замена содержимого там некорректно реализована — размер массива childNodes меняется во время работы цикла (appendChild удаляет ноды, поскольку нода может иметь только одного родителя). Работает это только потому, что переносится одна нода. Ну и Range для удаления я бы приплетать не стал. Кроме того можно определить setter в более общем виде — для всех HTMLParagraphElement (для HTMLElement его определить не получается, именно там определен innerHTML). Итого у меня получается:
HTMLParagraphElement.prototype.__defineSetter__('innerHTML', function(str){
str = '<innerRoot xmlns="http://www.w3.org/1999/xhtml">' + str + '</innerRoot>';
var nodes = new DOMParser().parseFromString(str, 'text/xml').documentElement;
if ((nodes.tagName == 'parserError') ||
(nodes.namespaceURI == 'http://www.mozilla.org/newlayout/xml/parsererror.xml'))
return;//~ or alert, warning, etc.
while (this.firstChild)
this.removeChild(this.firstChild);
while (nodes.firstChild)
this.appendChild(nodes.firstChild);
});
Аналогично можно было бы и getter определить, для этого есть DOMSerializer. Но в FF 1.5 innerHTML уже и так работает, видимо как раз эмуляцию такого типа и поставили.
Mash:
Ох, совсем плохой был, когда писал. :) Поправил, спасибо.