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:

Ох, совсем плохой был, когда писал. :) Поправил, спасибо.

Комментарии временно отключены.