Что именно может вызвать ошибку "HIERARCHY_REQUEST_ERR: DOM Exception 3"?

Как именно это относится к jQuery? Я знаю, что библиотека использует встроенные функции javascript для внутреннего использования, но что именно она пытается делать, когда возникает такая проблема?

15 ответов

Решение

Это означает, что вы пытались вставить узел DOM в то место в дереве DOM, куда он не может перейти. Наиболее распространенное место, которое я вижу, это в Safari, которое не позволяет следующее:

document.appendChild(document.createElement('div'));

Вообще, это просто ошибка, когда это было задумано:

document.body.appendChild(document.createElement('div'));

Другие причины, замеченные в дикой природе (обобщено из комментариев):

  • Вы пытаетесь добавить узел к себе
  • Вы пытаетесь добавить нуль к узлу
  • Вы пытаетесь добавить узел к текстовому узлу.
  • Ваш HTML-код недействителен (например, не удалось закрыть целевой узел)
  • Браузер считает, что HTML-код, который вы пытаетесь добавить, является XML (исправьте, добавив <!doctype html> на ваш введенный HTML или указание типа контента при извлечении через XHR)

Если вы получаете эту ошибку из-за jquery ajax, вызовите $.ajax

Затем вам может понадобиться указать, что dataType возвращается с сервера. Я исправил ответ, используя это простое свойство.

$.ajax({
    url: "URL_HERE",
    dataType: "html",
    success: function(response) {
        $('#ELEMENT').html(response);
    }
});

В частности, с помощью jQuery вы можете столкнуться с этой проблемой, если при создании элементов забудете про символы тега html:

 $("#target").append($("div").text("Test"));

Возникнет эта ошибка, потому что вы имели в виду

 $("#target").append($("<div>").text("Test"));

Эта ошибка может возникать, когда вы пытаетесь вставить в DOM узел с недопустимым HTML-кодом, который может быть таким же тонким, как неправильный атрибут, например:

// <input> can have a 'type' attribute
var $input = $('<input/>').attr('type', 'text');
$holder.append($input);  // OK

// <div> CANNOT have a 'type' attribute
var $div = $('<div></div>').attr('type', 'text');
$holder.append($div);   // Error: HIERARCHY_REQUEST_ERR: DOM Exception 3

@ Келли Нортон прав в своем ответе The browser thinks the HTML you are attempting to append is XML и предлагает specifying the content type when fetching via XHR,

Это правда, однако вы иногда используете сторонние библиотеки, которые не собираетесь изменять. Это JQuery UI в моем случае. Тогда вы должны предоставить право Content-Type в ответе вместо переопределения типа ответа на стороне JavaScript. Установите свой Content-Type в text/html и ты в порядке.

В моем случае это было так же просто, как переименование file.xhtml в file.html - сервер приложений имел некоторые расширения для сопоставления типов MIME из коробки. Когда содержимое является динамическим, вы можете установить тип содержимого ответа как-то (например, res.setContentType("text/html") в сервлете API).

Я собираюсь добавить еще один конкретный ответ, потому что это был двухчасовой поиск ответа...

Я пытался вставить тег в документ. HTML был такой:

<map id='imageMap' name='imageMap'>
  <area shape='circle' coords='55,28,5' href='#' title='1687.01 - 0 percentile' />
</map>

Если вы заметили, тег закрыт в предыдущем примере (<area/>). Это не было принято в браузерах Chrome. w3schools, похоже, считает, что он должен быть закрыт, и я не смог найти официальную спецификацию для этого тега, но он точно не работает в Chrome. Firefox не примет это с <area/> или же <area></area> или же <area>, Хром должен иметь <area>, IE принимает что угодно.

В любом случае, эта ошибка может быть из-за того, что ваш HTML неверен.

Если вы столкнулись с этой проблемой при попытке добавить узел в другое окно в Internet Explorer, попробуйте использовать HTML внутри узла вместо самого узла.

myElement.appendChild(myNode.html());

IE не поддерживает добавление узлов в другое окно.

Я знаю, что эта ветка старая, но я столкнулся с другой причиной проблемы, которая может оказаться полезной для других. Я получаю сообщение об ошибке, когда Google Analytics пытается добавить себя в комментарий HTML. Оскорбительный код:

document.documentElement.firstChild.appendChild(ga);

Это вызывало ошибку, потому что моим первым элементом был комментарий HTML (а именно код шаблона Dreamweaver).

<!-- #BeginTemplate "/Templates/default.dwt.php" -->

Я изменил нарушающий код на что-то, по общему признанию, не пуленепробиваемое, но лучше

document.documentElement.firstChild.nodeType===1 ? document.documentElement.firstChild.appendChild(ga) : document.documentElement.lastChild.appendChild(ga);

Вы можете увидеть эти вопросы

Получение HIERARCHY_REQUEST_ERR при использовании Javascript для рекурсивной генерации вложенного списка

или же

JQuery UI Диалог с обратной передачей кнопки ASP.NET

Вывод

когда вы пытаетесь использовать функцию append, вы должны использовать новую переменную, как в этом примере

jQuery(function() {
   var dlg = jQuery("#dialog").dialog({ 
                        draggable: true, 
                        resizable: true, 
                        show: 'Transfer', 
                        hide: 'Transfer', 
                        width: 320, 
                        autoOpen: false, 
                        minHeight: 10, 
                        minwidth: 10 
          });
  dlg.parent().appendTo(jQuery("form:first"));
});

В приведенном выше примере использует var "dlg" для запуска функции appendTo. Тогда ошибка "HIERARCHY_REQUEST_ERR" больше не будет появляться.

Эта ОШИБКА произошла со мной в IE9, когда я попытался динамически присоединить Child к объекту, который уже существовал в окне A. Окно A создаст дочернее окно B. В окне B после некоторого действия пользователя будет запущена функция и выполнит appendChild на элемент формы в окне A, используя window.opener.document.getElementById('formElement').appendChild(input);

Это может привести к ошибке. То же самое с созданием элемента ввода с использованием document.createElement('input'); в дочернем окне, передавая его в качестве параметра window.opener Окно А, и там сделать добавление. Только если бы я создал элемент ввода в том же окне, в которое я собирался добавить его, он успешно завершился бы без ошибок.

Таким образом, мой вывод (пожалуйста, проверьте): ни один элемент не может быть создан динамически (используя document.createElement) в одном окне, а затем добавляется (используя .appendChild) к элементу в другом окне (не предпринимая, возможно, особого дополнительного шага, который я пропустил, чтобы убедиться, что он не считается XML или чем-то еще). Это терпит неудачу в IE9 и выдает ошибку, в FF это работает хорошо все же.

PS. Я не использую jQuery.

Я столкнулся с этой ошибкой при использовании дополнения Google Chrome Sidewiki. Отключение это решило проблему для меня.

Я получаю эту ошибку в IE9, если у меня отключена опция отладки скриптов (Internet Explorer). Если я включаю отладку сценария, я не вижу ошибки, и страница работает нормально. Это кажется странным, что исключение DOM связано с включенной или отключенной отладкой.

Другая причина, по которой это может появиться, заключается в том, что вы добавляете данные до того, как элемент готов, например

<body>

<script>
document.body.appendChild(foo);
</script>

</body>
</html>

В этом случае вам нужно переместить скрипт после. Не совсем уверен, что это кошерно, но перемещение скрипта после тела, похоже, не помогает:/

Вместо перемещения скрипта вы также можете добавлять в обработчик событий.

Просто для справки.

IE будет блокировать добавление любого элемента, созданного в другом контексте окна, из контекста окна, к которому добавляется элемент.

например

var childWindow = window.open('somepage.html');

//will throw the exception in IE
childWindow.document.body.appendChild(document.createElement('div'));

//will not throw exception in IE
childWindow.document.body.appendChild(childWindow.document.createElement('div'));

Я еще не понял, как создать элемент dom с помощью jQuery, используя другой контекст окна.

Я получил эту ошибку, потому что я забыл клонировать свой элемент.

// creates an error
clone = $("#thing");
clone.appendTo("#somediv");

// does not
clone = $("#thing").clone();
clone.appendTo("#somediv");
Другие вопросы по тегам