Получить внешний HTML-код выбранного элемента

792

Я пытаюсь получить HTML-код выбранного объекта с помощью jQuery. Я знаю о .html()функции; проблема в том, что мне нужен HTML, включая выбранный объект (в данном случае строка таблицы, в которой .html()возвращаются только ячейки внутри строки).

Я искал и нашел несколько очень «хакерских» методов клонирования объекта, добавления его во вновь созданный div и т. Д., И т. Д., Но это кажется очень грязным. Есть ли лучший способ, или новая версия jQuery (1.4.2) предлагает какую-либо outerHtmlфункциональность?

Райан
источник
89
Возмутительно, что у jQuery нет средств для подобных вещей. Мне это тоже нужно.
Йозеф Сабл
9
Я отправил запрос на добавление функции со ссылкой на эту ветку, и первоначальный ответ был положительным. bugs.jquery.com/ticket/8142
mindplay.dk
11
Чтобы сэкономить некоторым людям несколько секунд своего времени от опробования решения Улхаса Тускано, оно не работает.
Дейв
73
Ох, что происходит $('div')[0].outerHTML,
Салман фон Аббас
24
@Tuscan означало $ ("# selectorid"). Prop ("outerHTML")
парень mograbi

Ответы:

189

Редактирование 2014 года: вопрос и этот ответ относятся к 2010 году. В то время лучшего решения не было. Теперь многие другие ответы лучше: например, Эрика Ху или Ре Капчи.

Этот сайт, кажется, имеет решение для вас: jQuery: outerHTML | Yelotofu

jQuery.fn.outerHTML = function(s) {
    return s
        ? this.before(s).remove()
        : jQuery("<p>").append(this.eq(0).clone()).html();
};
Дэвид В.
источник
4
Я видел это, но пытался избежать этого, потому что это казалось хакерским и, как будто должен был быть лучший способ, но он работает хорошо. Спасибо.
Райан
359
$ ( '[селектор]') [0] .outerHTML
Дрогон
25
@drogon: имейте в виду, что outerHTMLподдерживается в Firefox только с версии 11 (март 2012 г.).
Блез
8
@PavingWays: в защиту Firefox: outerHTMLэто собственный атрибут, изобретенный Microsoft, а не стандарт W3C. (Интересный факт: innerHTMLстандартизирован только с HTML5 )
Blaise
3
pure jsel.outerHTML || document.createElement('div').appendChild( el.cloneNode( true ) ).parentNode.innerHTML
rab
675

Я считаю, что в настоящее время (5/1/2012) все основные браузеры поддерживают функцию externalHTML. Мне кажется, что этого фрагмента достаточно. Я лично хотел бы запомнить это:

// Gives you the DOM element without the outside wrapper you want
$('.classSelector').html()

// Gives you the outside wrapper as well only for the first element
$('.classSelector')[0].outerHTML

// Gives you the outer HTML for all the selected elements
var html = '';
$('.classSelector').each(function () {
    html += this.outerHTML;
});

//Or if you need a one liner for the previous code
$('.classSelector').get().map(function(v){return v.outerHTML}).join('');

РЕДАКТИРОВАТЬ : Основная статистика поддержки дляelement.outerHTML

Эрик Ху
источник
14
@SalmanPK FireFox не поддерживал это свойство до 2011-11-11. bugzilla.mozilla.org/show_bug.cgi?id=92264 Все еще много пользователей зависло на 3.6. Я думаю, что это действительно прекрасный пример того, почему кто-то решил использовать jQuery вместо нативной функциональности.
Люцифер Сэм
8
По данным gs.statcounter.com, @LuciferSam Firefox 3.6 имеет долю мирового рынка ~ 6%. Однако фильтрация результатов по последним 6 месяцам (декабрь '11-май '12) и по США вытесняет их из списка топ-12 (ниже 3). %). Я выбрал это окно, поскольку в этой статье предполагается, что использование FF 3.6 значительно упало после января 2012 года. Учитывая эти данные, я поддерживаю свое решение для более простого кода по сравнению с обратной совместимостью.
Эрик Ху
4
Не могу согласиться больше. Это правильный ответ здесь, а не другие вещи, которые люди предлагают. Элемент, который я выбрал, имеет атрибуты, которые я хочу сохранить, которые теряются другими ответами. Черт, это даже работает в IE!
Мэтью Бониг
Нет. Firefox 11 не был выпущен до 13 марта 2012 года (исправлено сейчас), то есть менее года назад на момент написания этой статьи. Одним из преимуществ jQuery является то, что он поддерживает старые браузеры. Я думаю, что поддержка по крайней мере в течение года является разумной, и некоторые сайты, очевидно, захотят большего (помните, jQuery поддерживает IE6).
Мэтью Флэшен
7
@EricHu statcounter также утверждает, что IE8 имеет 9,3% глобальной доли браузера. Тем не менее, некоторые из моих сайтов близки к отметке 40%. Это все относительно и сильно варьируется от сайта к сайту, Firefox 3.6 все еще составляет примерно 10% на некоторых моих сайтах. Глобальный рынок акций ничего не значит. Все дело в аудитории ваших сайтов.
Джордж Райт
343

Нет необходимости создавать функцию для него. Просто сделайте это так:

$('a').each(function(){
    var s = $(this).clone().wrap('<p>').parent().html();
    console.log(s);
});

(Кстати, в консоли вашего браузера будет отображаться то, что зарегистрировано. Большинство новейших браузеров, начиная с 2009 года, имеют эту функцию.)

Волшебство это на конце:

.clone().wrap('<p>').parent().html();

Клон означает, что вы на самом деле не беспокоите DOM. Запустите его без него, и вы увидите pтеги, вставленные до / после всех гиперссылок (в этом примере), что нежелательно. Так что да, пользуйтесь .clone().

Он работает так, что он берет каждый aтег, создает его клон в ОЗУ, оборачивает pтегами, получает его родитель (то есть pтег), а затем получает его innerHTMLсвойство.

РЕДАКТИРОВАТЬ : принял советы и изменил divтеги на pтеги, потому что он меньше печатает и работает так же.

Volomike
источник
82
Интересно, почему команда jQuery не добавляет метод outerHtml ()?
Донни В.
1
@ Дерек, это не имеет значения. Я использую DIV в качестве оболочки, чтобы получить что-то внутри.
Volomike
11
.clone () обертка ( '<р>') родитель () HTML ()...; Короче
Uğur Gümüşhan
1
Да, меньше нажатий клавиш, и достигается тот же эффект.
Volomike
14
Лучше использовать DIV вместо P для общего решения - не все элементы могут быть заключены в P как действительный HTML.
Blazemonger
149

Как насчет prop('outerHTML'):?

var outerHTML_text = $('#item-to-be-selected').prop('outerHTML');

И установить:

$('#item-to-be-selected').prop('outerHTML', outerHTML_text);

Это сработало для меня.

PS : это добавлено в jQuery 1.6 .

Re Captcha
источник
4
Очень аккуратный и маленький код по сравнению с другими ответами. Q: Имеет ли это те же ограничения externalHTML, как отмечено в других ответах? Это работает в FF <11?
MacroMan
3
Работает хорошо, это может быть просто лучшим решением здесь. Что касается браузеров, то они должны быть такими же совместимыми, как и externalHTLM. Метод prop () в основном просто получает свойство externalHTML.
Том Том
2
Это решение лучше, однако Jquery 1.6.1 был выпущен в 2011 году. Вопрос (и мой ответ) относятся к 2010 году.
Дэвид В.
1
Для меня "$ ('[selector]') [0] .outerHTML;" ни в коем случае не работал, но "$ ('# item-to-be-selected'). prop ('outerHTML');" да!
Эдуардо Лусио
2
. $ ( '# пункт, чтобы быть выбранным') ATTR ( 'outerHTML'); // ** Для более ранних
версий
91

Расширить JQuery:

(function($) {
  $.fn.outerHTML = function() {
    return $(this).clone().wrap('<div></div>').parent().html();
  };
})(jQuery);

И используйте это так: $("#myTableRow").outerHTML();

Джессика
источник
8
Небольшая проблема с этим решением: вам нужно clone () перед wrap (), в противном случае вы оставляете лишний перенос <div> в документе.
mindplay.dk
1
Спасибо, mindplay.dk - я отредактировал код, чтобы включить ваше предложение ... хороший улов. :)
Джессика
2
Как насчет того, чтобы поменять местами: return $('<div>').append(this.clone()).html();это просто немного более точно.
Джастин Варкентин
2
Сначала вы должны проверить externalHTML и просто использовать его для браузеров, которые его поддерживают
Джеймс Вестгейт,
Это отлично подходит для таких людей, как я, которые любят создавать HTML в ответах AJAX, используя объекты jQuery и функции .appendTo () и .append (). .outerHTML не работает для тех случаев из того, что я видел в моем тестировании. Кто-то еще может захотеть проверить это больше, но у меня нет времени.
Шон Кендл
43

Я согласен с Арпаном (13 декабря 10:59).

Его способ сделать это - НАМНОГО лучший способ сделать это, поскольку вы не используете клон. Метод клонирования занимает очень много времени, если у вас есть дочерние элементы, и никто больше не заботился о том, что IE действительно имеет outerHTMLатрибут (да, IE действительно имеет НЕКОТОРЫЕ полезные приемы).

Но я бы, вероятно, создал его сценарий немного по-другому:

$.fn.outerHTML = function() {
    var $t = $(this);
    if ($t[0].outerHTML !== undefined) {
        return $t[0].outerHTML;
    } else {
        var content = $t.wrap('<div/>').parent().html();
        $t.unwrap();
        return content;
    }
};
Tokimon
источник
2
Это отлично сработало для меня. Из-за ошибки сclone() и textareas мне понадобилось решение без клонирования, и это было точно.
Шпигфорд
5
+1 для использования нативного, outerHTMLгде доступно, так как он поддерживается Chrome в дополнение к Internet Explorer.
Энди Э
9
предупреждение if (! ('outerHTML' в $ t [0])) ("черт возьми, обнови свой браузер");
psycho brm
19

Чтобы быть действительно jQuery-esque, вы можете захотеть outerHTML()быть геттером и сеттером, и его поведение должно быть максимально схожим html():

$.fn.outerHTML = function (arg) {
    var ret;

    // If no items in the collection, return
    if (!this.length)
        return typeof arg == "undefined" ? this : null;
    // Getter overload (no argument passed)
    if (!arg) {
        return this[0].outerHTML || 
            (ret = this.wrap('<div>').parent().html(), this.unwrap(), ret);
    }
    // Setter overload
    $.each(this, function (i, el) {
        var fnRet, 
            pass = el,
            inOrOut = el.outerHTML ? "outerHTML" : "innerHTML";

        if (!el.outerHTML)
            el = $(el).wrap('<div>').parent()[0];

        if (jQuery.isFunction(arg)) { 
            if ((fnRet = arg.call(pass, i, el[inOrOut])) !== false)
                el[inOrOut] = fnRet;
        }
        else
            el[inOrOut] = arg;

        if (!el.outerHTML)
            $(el).children().unwrap();
    });

    return this;
}

Рабочая демонстрация: http://jsfiddle.net/AndyE/WLKAa/

Это позволяет нам передавать аргумент outerHTML, который может быть

  • отменяемая функция - function (index, oldOuterHTML) { }- где возвращаемое значение станет новым HTML для элемента (если falseне возвращено).
  • строка, которая будет установлена ​​вместо HTML каждого элемента.

Для получения дополнительной информации см. Документацию jQuery для html().

Энди Э
источник
Это следует добавить в ядро ​​jQuery, чтобы людям не приходилось об этом думать. Мой единственный вопрос: может ли wrap () / unwrap () быть лучше или хуже, чем clone ()?
IMSoP
1
IMSoP: как правило, перенос / развертывание будет быстрее, потому что клон должен скопировать все дочерние элементы и атрибуты элемента. wrap () создает только один элемент, а unwrap () уничтожает его, все остальные элементы просто перемещаются, что в большинстве случаев является довольно быстрой операцией.
Энди Э,
16

Вы также можете использовать get (Получить элементы DOM, соответствующие объекту jQuery.).

например:

$('div').get(0).outerHTML;//return "<div></div>"

Как метод расширения:

jQuery.fn.outerHTML = function () {
  return this.get().map(function (v) {
    return v.outerHTML
  }).join()
};

Или

jQuery.fn.outerHTML = function () {
  return $.map(this.get(), function (v) {
    return v.outerHTML
  }).join()
};

Множественный выбор и возврат внешнего HTML всех найденных элементов.

$('input').outerHTML()

возвращение:

'<input id="input1" type="text"><input id="input2" type="text">'
М.Дж. Вакили
источник
11

Чтобы сделать полный плагин jQuery as .outerHTML, добавьте следующий скрипт в любой файл js и включите после jQuery в свой заголовок:

обновление Новая версия имеет лучший контроль, а также более дружественный сервис jQuery Selector! :)

;(function($) {
    $.extend({
        outerHTML: function() {
            var $ele = arguments[0],
                args = Array.prototype.slice.call(arguments, 1)
            if ($ele && !($ele instanceof jQuery) && (typeof $ele == 'string' || $ele instanceof HTMLCollection || $ele instanceof Array)) $ele = $($ele);
            if ($ele.length) {
                if ($ele.length == 1) return $ele[0].outerHTML;
                else return $.map($("div"), function(ele,i) { return ele.outerHTML; });
            }
            throw new Error("Invalid Selector");
        }
    })
    $.fn.extend({
        outerHTML: function() {
            var args = [this];
            if (arguments.length) for (x in arguments) args.push(arguments[x]);
            return $.outerHTML.apply($, args);
        }
    });
})(jQuery);

Это позволит вам не только получить externalHTML одного элемента, но даже получить возврат из Array сразу нескольких элементов! и может использоваться в обоих стандартных стилях jQuery как таковых:

$.outerHTML($("#eleID")); // will return outerHTML of that element and is 
// same as
$("#eleID").outerHTML();
// or
$.outerHTML("#eleID");
// or
$.outerHTML(document.getElementById("eleID"));

Для нескольких элементов

$("#firstEle, .someElesByClassname, tag").outerHTML();

Примеры фрагментов:

SpYk3HH
источник
9

Вы также можете просто сделать это таким образом

document.getElementById(id).outerHTML

где id - это идентификатор элемента, который вы ищете

Энди
источник
4
$("#" + id).attr("id")невероятно излишним. Если у вас уже есть идентификатор в переменной, почему вы используете селектор jquery для извлечения элемента из dom, а затем запрашиваете его атрибут ID?
Сэм Дюфель
7

Я использовал решение Джессики (отредактированное Джошем), чтобы получить externalHTML для работы в Firefox. Проблема, однако, в том, что мой код ломался, потому что ее решение обернуло элемент в DIV. Добавление еще одной строки кода решило эту проблему.

Следующий код дает вам externalHTML, оставляя дерево DOM без изменений.

$jq.fn.outerHTML = function() {
    if ($jq(this).attr('outerHTML'))
        return $jq(this).attr('outerHTML');
    else
    {
    var content = $jq(this).wrap('<div></div>').parent().html();
        $jq(this).unwrap();
        return content;
    }
}

И используйте это так: $ ("# myDiv"). OuterHTML ();

Надеюсь, кто-то найдет это полезным!

Арпан Дхандхания
источник
1
Просто используйте .clone, как подсказывает @mindplay в своем комментарии - это проще
Ярин
4

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

var row = $(".myRow").last().clone();
$(".myRow").last().after(row);

.myrowэто имя класса <tr>. Он создает копию последней строки и вставляет ее как новую последнюю строку. Это также работает в IE7 , в то время как [0].outerHTMLметод не разрешает присваивания в ie7

Стефан Букхолт
источник
3

node.cloneNode () вряд ли выглядит как взлом. Вы можете клонировать узел и добавить его к любому желаемому родительскому элементу, а также манипулировать им, манипулируя отдельными свойствами, вместо того, чтобы, например, запускать регулярные выражения на нем или добавлять его в DOM, а затем манипулировать им после слов.

Тем не менее, вы также можете перебирать атрибуты элемента, чтобы создать его представление в виде строки HTML. Кажется вероятным, что именно так будет реализована любая функция externalHTML, если бы jQuery ее добавил.

Бен Регенспан
источник
3

Я использовал решение Volomike, обновленное Джессикой. Просто добавил проверку, чтобы увидеть, существует ли элемент, и сделал его пустым, если его нет.

jQuery.fn.outerHTML = function() {
return $(this).length > 0 ? $(this).clone().wrap('<div />').parent().html() : '';
};

Конечно, используйте это как:

$('table#buttons').outerHTML();
Иван Чаер
источник
3

Вы можете найти хороший вариант .outerHTML () здесь https://github.com/darlesson/jquery-outerhtml .

В отличие от .html (), который возвращает только HTML-содержимое элемента, эта версия .outerHTML () возвращает выбранный элемент и его HTML-содержимое или заменяет его как метод .replaceWith (), но с той разницей, которая позволяет заменяющему HTML наследоваться цепочка

Примеры также можно увидеть в URL выше.

Darlesson
источник
2

Обратите внимание, что решение Джоша работает только для одного элемента.

Можно утверждать, что «внешний» HTML действительно имеет смысл, только когда у вас есть один элемент, но есть ситуации, когда имеет смысл взять список элементов HTML и превратить их в разметку.

Расширяя решение Джоша, оно будет обрабатывать несколько элементов:

(function($) {
  $.fn.outerHTML = function() {
    var $this = $(this);
    if ($this.length>1)
      return $.map($this, function(el){ return $(el).outerHTML(); }).join('');
    return $this.clone().wrap('<div/>').parent().html();
  }
})(jQuery);

Изменить: исправлена ​​еще одна проблема с решением Джоша, см. Комментарий выше.

mindplay.dk
источник
1
Большинство jQuery-методов «getter» возвращают данные только для первого элемента, поэтому было бы более целесообразно сопоставить это поведение.
Энди Э
Мне кажется, я четко сформулировал, почему это так работает? Это может привести к уродливому / сложному коду, когда у вас есть список элементов - если по какой-то причине вам нужна разметка только для первого элемента, просто используйте: first в вашем селекторе.
mindplay.dk
Конечно, точно так же, как вы могли бы просто использовать карту с решением всех остальных, чтобы получить HTML из нескольких элементов. Все, что я говорил, это то, что более согласованно поведение стандартных методов jQuery.
Энди Э,
2

Я сделал этот простой тест, где externalHTML - это решение Tokimon (без клона), а outerHTML2 - решение Jessica (клон)

console.time("outerHTML");
for(i=0;i<1000;i++)
 {                 
  var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML();
 }                 
console.timeEnd("outerHTML");

console.time("outerHTML2");

 for(i=0;i<1000;i++)
 {                 
   var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML2();
  }                 
  console.timeEnd("outerHTML2");

и результат в моем браузере Chromium (Версия 20.0.1132.57 (0)) был

externalHTML: 81
мс externalHTML2: 439 мс

но если мы используем решение Tokimon без встроенной функции externalHTML (которая теперь поддерживается, вероятно, почти во всех браузерах)

мы получили

externalHTML: 594ms
ВнешнийHTML2: 332ms

и в реальных примерах будет больше циклов и элементов, поэтому идеальная комбинация будет

$.fn.outerHTML = function() 
{
  $t = $(this);
  if( "outerHTML" in $t[0] ) return $t[0].outerHTML; 
  else return $t.clone().wrap('<p>').parent().html(); 
}

поэтому метод клонирования на самом деле быстрее, чем метод wrap / unwrap
(jquery 1.7.2)

Петар
источник
2

Вот очень оптимизированный внешний плагин externalHTML для jquery: ( http://jsperf.com/outerhtml-vs-jquery-clone-hack/5 => 2 других фрагмента быстрого кода не совместимы с некоторыми браузерами, такими как FF <11)

(function($) {

  var DIV = document.createElement("div"),
      outerHTML;

  if ('outerHTML' in DIV) {
    outerHTML = function(node) {
      return node.outerHTML;
    };
  } else {
    outerHTML = function(node) {
      var div = DIV.cloneNode();
      div.appendChild(node.cloneNode(true));
      return div.innerHTML;
    };
  }

  $.fn.outerHTML = function() {
    return this.length ? outerHTML(this[0]) : void(0);
  };

})(jQuery);

@ Andy E => Я не согласен с тобой. externalHMTL не нуждается в геттере и сеттере: jQuery уже дает нам «replaceWith» ...

@mindplay => Почему вы присоединяетесь ко всем externalHTML? jquery.html возвращает только HTML-содержимое элемента FIRST.

(Извините, не хватает репутации, чтобы писать комментарии)

gtournie
источник
2

Коротко и сладко.

[].reduce($('.x'), function(i,v) {return i+v.outerHTML}, '')

или событие более сладкое с помощью функций стрелок

[].reduce.call($('.x'), (i,v) => i+v.outerHTML, '')

или вообще без jQuery

[].reduce.call(document.querySelectorAll('.x'), (i,v) => i+v.outerHTML, '')

или если вам не нравится этот подход, проверьте

$('.x').get().reduce((i,v) => i+v.outerHTML, '')
rolacja
источник
2

Это довольно просто с ванильным JavaScript ...

document.querySelector('#selector')
падуб
источник
1

Это отлично подходит для изменения элементов в dom, но НЕ работает, например, при передаче html-строки в jquery следующим образом:

$('<div id="foo">Some <span id="blog">content</span></div>').find('#blog').outerHTML();

После некоторых манипуляций я создал функцию, которая позволяет работать с вышеупомянутым, т.е. для строк html:

$.fn.htmlStringOuterHTML = function() {     
    this.parent().find(this).wrap('<div/>');        
    return this.parent().html();
};
inspiraller
источник
1

$.html = el => $("<div>"+el+"</div>").html().trim();

evandrix
источник
0

Я столкнулся с этим, когда искал ответ на свою проблему, которая заключалась в том, что я пытался удалить строку таблицы, а затем добавить ее обратно внизу таблицы (поскольку я динамически создавал строки данных, но хотел показать «Добавить новый» Запись 'типа строки внизу).

У меня была та же проблема, в том, что она возвращала innerHtml, поэтому отсутствовали теги TR, которые содержали идентификатор этой строки и означали, что невозможно повторить процедуру.

Ответ, который я нашел, состоял в том, что remove()функция jquery на самом деле возвращает удаляемый элемент как объект. Итак, удалить и заново добавить строку было так просто, как это ...

var a = $("#trRowToRemove").remove();            
$('#tblMyTable').append(a);  

Если вы не удаляете объект, но хотите скопировать его в другое место, используйте clone()функцию.

тусклый
источник
0

Плагин jQuery в качестве сокращения, чтобы напрямую получить весь элемент HTML:

jQuery.fn.outerHTML = function () {
    return jQuery('<div />').append(this.eq(0).clone()).html();
};

И используйте это так: $(".element").outerHTML();

Sky Yip
источник
-2
$("#myNode").parent(x).html(); 

Где «x» - номер узла, начиная с 0 в качестве первого, должен получить нужный вам узел, если вы пытаетесь получить конкретный. Если у вас есть дочерние узлы, вам действительно нужно поставить ID на тот, который вы хотите, чтобы просто сосредоточиться на этом. Использование этой методологии и отсутствие «х» отлично сработало для меня.

vapcguy
источник
1
Люди голосуют за это, хотите оставить комментарий? У меня есть код, перейдите к РОДИТЕЛЯМ, а затем получите HTML содержимое, а не просто делайте с .html()данным элементом. Это работает, и я хотел бы объяснить, почему это не так.
vapcguy
-4

Простое решение

var myself = $('#div').children().parent();
Zeeshan
источник
-12
$("#myTable").parent().html();

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

Это то, что вы после?

inkedmn
источник
25
На самом деле нет, потому что если у этого родителя есть другие дети, он тоже получит этот html.
Дэвид В.
1
...что он сказал. Я ищу сам элемент, а не его и других детей его родителей. Как это получило два голоса?
Райан