Элементы, добавленные в дерево DOM с помощью `appendChild`, не отображаются в IE6 / 7 (также не запускаются события onclick) - PullRequest
1 голос
/ 06 мая 2011

Рассмотрим следующий код JavaScript, предназначенный для создания таблицы 8x8 внутри контейнера div с id="c":

//first, two shortcut functions
function $id(a){return(a&&a.nodeType)?a:document.getElementById(a);}
function $cr8(a){return document.createElement(a);}

//now the meat    
var ct = $id('c'),
    t = $cr8('table'),
    tr, td,
    row = 8, cols = 8,
    tdclkfn = function () { alert('row: '+this.i+' col: '+this.j); }

for(var i=0;i<row;i++) {
    tr = $cr8('tr');
    for(var j=0;j<cols;j++) {
        td = $cr8('td');
        td.i = i;
        td.j = j;
        td.onclick = tdclkfn;
        tr.appendChild(td);
    }
    t.appendChild(tr);
}
ct.appendChild(t);

. Это работает, как ожидается, в Firefox, Chrome и IE8.Не так много в IE6 / IE7.Как вы можете видеть в этом живом примере , разметка таблицы отсутствует,

Если вы ковыряетесь под капотом, используя Firebug Lite или панель инструментов разработчика IE, выможет обнаружить, что элементы DOM действительно есть, но по какой-то причине они просто не отображаются.Кто-нибудь знает почему?

Я решил посмотреть, что произойдет, если я добавлю ct.innerHTML += '<div/>' в конец вышеупомянутого JavaScript.Presto, это обнаруживается (см. этот обновленный живой пример ).Почему это решает проблему?

Кроме того, функцию, которую я прикрепил к обработчику событий onclick для каждого <td>?Очевидно это не стреляет вообще.Он прикреплен, вы можете вызвать его вручную, но нажав на ячейку?Нет, не в IE6 / 7.Почему?

Я знаю, что могу обойти это, используя симпатичный JS / DOM-фреймворк, но мне действительно было бы интересно узнать, что здесь происходит.

1 Ответ

4 голосов
/ 06 мая 2011

table элементы не могут напрямую содержать tr элементы; IE и другие браузеры с удовольствием справятся с этим при разборе разметки (вставка tbody автоматически; см. Ниже), но, очевидно, IE более привередлив, когда вы манипулируете DOM напрямую.

Если вы добавите туда tbody, IE6 и IE7 будут довольны (отображаются поля, работают обработчики нажатий):

var ct = $id('c'),
    t = $cr8('table'),
    tbody = $cr8('tbody'),
    tr, td,
    row = 8, cols = 8,
    tdclkfn = function () {
        alert('row: '+this.i+' col: '+this.j);
    }

for(var i=0;i<row;i++) {
    tr = $cr8('tr');
    for(var j=0;j<cols;j++) {
        td = $cr8('td');
        td.i = i;
        td.j = j;
        td.onclick = tdclkfn;
        tr.appendChild(td);
    }
    tbody.appendChild(tr);
}
t.appendChild(tbody);
ct.appendChild(t);

Живая копия (на jsbin.com; мне не особо повезло с IE6, IE7 и jsfiddle.net). Ваш оригинальный код здесь для сравнения на том же сайте.

Что касается автоматической вставки tbody, вы можете увидеть это в действии:

HTML:

<table id='theTable'><tr><td>Test</td></tr></table>

(Примечание № tbody.)

JavaScript:

window.onload = function() {
  var elm, markup;

  elm = document.getElementById('theTable');
  markup = ["<ol>"];
  walk(elm);
  markup.push("</ol>");
  display(markup.join(""));

  function walk(node) {
    var child;

    markup.push("<li>");
    markup.push(node.nodeName);
    if (node.nodeType === 1 ||
        node.nodeType === 9 ||
        node.nodeType === 11) {
      markup.push("<ol>");
      for (child = node.firstChild;
           child;
           child = child.nextSibling) {
        walk(child);
      }
      markup.push("</ol>");
    }
    markup.push("</li>");
  }

  function display(markup) {
    var div = document.createElement('div');
    div.innerHTML = markup;
    document.body.appendChild(div);
  }
};

Выход:

  1. Таблица
    1. TBODY
      1. TR
        1. TD
          1. # текст

Обратите внимание на tbody там.

Живая копия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...