JQuery после того, как метод не работает с вновь созданными элементами

Насколько я могу судить, следующий код должен работать, создавая элемент <div>, а затем создавая элемент <p>; выражение должно приводить к созданию объекта jQuery с двумя элементами:

$("<div>first element content</div>").after("<p>second element content</p>");

Однако, я получаю совсем другое. Документация (см. заголовок "Вставка отключенных узлов DOM" ) сообщает мне, что приведенный выше код должен приводить к созданию объекта jQuery, захватывая как фрагменты HTML, так и строя два элемента DOM. Но, что я получил, в нескольких разных версиях jQuery, все выше 1.4, является объектом jQuery только с 1 node. Тем не менее, следующий код работает просто отлично, возвращая (я считаю,) правильный объект jQuery, два элемента внутри:

$("<div></div>").after("<p>second element content</p>");

И этот пример также работает:

$("<div></div>").after("<p>second element content</p>").after("<p>third element content</p>");

Кажется, что метод .after() работает отлично, если созданный первый DOM node пуст, но не тогда, когда он отсутствует (независимо от содержимого последующих узлов DOM, присоединенных к нему).

Мне что-то не хватает о внутренних функциях jQuery, причудливых проблемах DOM и/или особенностях JavaScript, или это просто ошибка jQuery, которая сохранялась с версии 1.4 на 1.7?

(Вот скудный JSFiddle, демонстрирующий проблему довольно ясно.)

Ответ 1

Это была известная ошибка в jQuery < 1,9. См. http://bugs.jquery.com/ticket/8759

В jQuery >= 1.9 следует отметить следующую информацию из руководства по обновлению:

До 1.9, .after(), .before() и .replaceWith() будут пытаться добавлять или изменять узлы в текущем наборе jQuery, если первый node в наборе не был связан с документом, а в тех случаи возвращают новый набор jQuery, а не оригинальный набор. Это создало несколько несоответствий и неполадок - метод мог или не мог возвращать новый результат в зависимости от его аргументов! Начиная с 1.9, эти методы всегда возвращают исходный немодифицированный набор и пытаются использовать .after(), .before() или .replaceWith() на node без родительского эффекта, т.е. Ни набор, ни узлы он содержит изменения.

Ответ 2

Используйте add() для добавления объектов в коллекцию. Я использую after() больше в элементах DOM, которые уже существуют или кэшируются в переменной, но большую часть времени, если вы работаете с динамической разметкой, более практично использовать эквивалентный insertAfter().

$("<div>first element content</div>").add("<p>second element content</p>");

EDIT:

Это работает...

var $el = $('<div/>', {
    text: 'hey there'
}).after('<p>Lorem</p>');

Ответ 3

Я обнаружил, что у меня по-прежнему возникали проблемы с .add() вместо .after(), поэтому еще один простой способ обойти эту ошибку - сделать броский элемент-обертку, .append() элементы-братья и использовать .html(), чтобы просто получить внутреннее содержимое обертки.

Пример:

$('body').append(
    $('<span/>').append(
        $("<div>first element content</div>")
    ).append(
        $("<p>second element content</p>")
    ).html()
);

Это добавит <div> и <p>, но отменит внешний <span>. Я обнаружил, что обычно это нормально работает с .append(), но может иметь проблемы с .appendTo()