Получить внешний HTML-код выбранного элемента
Я пытаюсь получить HTML-код выбранного объекта с помощью jQuery. Я знаю о .html()
функция; проблема в том, что мне нужен HTML, включая выбранный объект (в данном случае строка таблицы, где .html()
возвращает только ячейки внутри строки).
Я искал вокруг и нашел несколько очень "хакерских" методов клонирования объекта, добавления его во вновь созданный div и т. Д., И т. Д., Но это кажется действительно грязным. Есть ли лучший способ, или новая версия jQuery (1.4.2) предлагает какой-либо outerHtml
функциональность?
31 ответ
Редактирование 2014 года: вопрос и этот ответ относятся к 2010 году. В то время лучшего решения не было. Теперь многие другие ответы лучше: например, Эрика Ху или Ре Капчи.
Этот сайт, похоже, имеет решение для вас: jQuery: outerHTML | Yelotofu
jQuery.fn.outerHTML = function(s) {
return s
? this.before(s).remove()
: jQuery("<p>").append(this.eq(0).clone()).html();
};
Я считаю, что в настоящее время (1/1/2012) все основные браузеры поддерживают функцию externalHTML. Мне кажется, что этого фрагмента достаточно. Я лично хотел бы запомнить это:
// Gives you the DOM element without the outside wrapper you want
$('.classSelector').html()
// Gives you the outside wrapper as well
$('.classSelector')[0].outerHTML
РЕДАКТИРОВАТЬ: Основная статистика поддержки для element.outerHTML
- Firefox (Gecko): 11 .... Дата выхода 2012-03-13
- Chrome: 0,2............... Дата выхода 2008-09-02
- Internet Explorer 4.0... Выпущен 1997
- Опера 7 ...................... Дата выхода 2003-01-28
- Safari 1.3................... выпущен 2006-01-12
Нет необходимости создавать функцию для него. Просто сделайте это так:
$('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
теги, потому что он меньше печатает и работает так же.
Как насчет: prop('outerHTML')
?
var outerHTML_text = $('#item-to-be-selected').prop('outerHTML');
И установить:
$('#item-to-be-selected').prop('outerHTML', outerHTML_text);
Это сработало для меня.
PS: это добавлено в jQuery 1.6.
Расширить JQuery:
(function($) {
$.fn.outerHTML = function() {
return $(this).clone().wrap('<div></div>').parent().html();
};
})(jQuery);
И используйте это так: $("#myTableRow").outerHTML();
Я согласен с Арпаном (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;
}
};
Чтобы быть действительно 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()
,
Вы также можете использовать get (Получить элементы DOM, соответствующие объекту jQuery.).
например:
$('div').get(0).outerHTML;//return "<div></div>"
Как метод расширения:
jQuery.fn.outerHTML = function () {
return this.get().map(function (v) {
return v.outerHTML
})
};
Или же
jQuery.fn.outerHTML = function () {
return $.map(this.get(), function (v) {
return v.outerHTML
})
};
Множественный выбор и возврат массива html.
$('input').outerHTML()
вернуть:
["<input id="input1" type="text">", "<input id="input2" type="text">"]
Чтобы сделать полный плагин jQuery как .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();
Примеры фрагментов:
console.log('$.outerHTML($("#eleID"))'+"\t", $.outerHTML($("#eleID")));
console.log('$("#eleID").outerHTML()'+"\t\t", $("#eleID").outerHTML());
console.log('$("#firstEle, .someElesByClassname, tag").outerHTML()'+"\t", $("#firstEle, .someElesByClassname, tag").outerHTML());
var checkThisOut = $("div").outerHTML();
console.log('var checkThisOut = $("div").outerHTML();'+"\t\t", checkThisOut);
$.each(checkThisOut, function(i, str){ $("div").eq(i).text("My outerHTML Was: " + str); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://rawgit.com/JDMcKinstry/ce699e82c7e07d02bae82e642fb4275f/raw/deabd0663adf0d12f389ddc03786468af4033ad2/jQuery.outerHTML.js"></script>
<div id="eleID">This will</div>
<div id="firstEle">be Replaced</div>
<div class="someElesByClassname">At RunTime</div>
<h3><tag>Open Console to see results</tag></h3>
Вы также можете просто сделать это таким образом
document.getElementById(id).outerHTML
где id - это идентификатор элемента, который вы ищете
Я использовал решение Джессики (которое было отредактировано Джошем), чтобы получить 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();
Надеюсь, кто-то найдет это полезным!
// no cloning necessary
var x = $('#xxx').wrapAll('<div></div>').parent().html();
alert(x);
Скрипка здесь: http://jsfiddle.net/ezmilhouse/Mv76a/
Если сценарий добавляет новую строку динамически, вы можете использовать это:
var row = $(".myRow").last().clone();
$(".myRow").last().after(row);
.myrow
это имя класса <tr>
, Он создает копию последней строки и вставляет ее как новую последнюю строку. Это также работает в IE7, в то время как [0].outerHTML
метод не позволяет назначений в ie7
Это довольно просто с ванильным JavaScript...
document.querySelector('#selector')
Я использовал решение Volomike, обновленное Джессикой. Просто добавили проверку, чтобы увидеть, существует ли элемент, и сделали его пустым, если его нет.
jQuery.fn.outerHTML = function() {
return $(this).length > 0 ? $(this).clone().wrap('<div />').parent().html() : '';
};
Конечно, используйте это как:
$('table#buttons').outerHTML();
node.cloneNode() вряд ли выглядит как хак. Вы можете клонировать узел и добавить его к любому желаемому родительскому элементу, а также манипулировать им, манипулируя отдельными свойствами, вместо того, чтобы, например, запускать на нем регулярные выражения или добавлять его в DOM, а затем манипулировать им после слов.
Тем не менее, вы также можете перебирать атрибуты элемента, чтобы создать его представление в виде строки HTML. Кажется вероятным, что именно так будет реализована любая функция externalHTML, если бы jQuery ее добавил.
Вы можете найти хороший вариант.outerHTML() здесь https://github.com/darlesson/jquery-outerhtml.
В отличие от.html(), который возвращает только HTML-содержимое элемента, эта версия.outerHTML() возвращает выбранный элемент и его HTML-содержимое или заменяет его как метод.replaceWith(), но с той разницей, которая позволяет заменяющему HTML наследоваться цепочка
Примеры также можно увидеть в URL выше.
Обратите внимание, что решение Джоша работает только для одного элемента.
Возможно, "внешний" 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);
Изменить: исправлена еще одна проблема с решением Джоша, см. Комментарий выше.
Коротко и сладко.
[].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, '')
Другое подобное решение с добавлением remove()
временного объекта DOM.
Вот очень оптимизированный внешний плагин 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 => Почему ты присоединяешься ко всем outerHTML? jquery.html возвращает только HTML-содержимое элемента FIRST.
(Извините, не хватает репутации, чтобы оставлять комментарии)
Я сделал этот простой тест, где 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: 594мс
externalHTML2: 332 мс
и в реальных примерах будет больше циклов и элементов, поэтому идеальная комбинация будет
$.fn.outerHTML = function()
{
$t = $(this);
if( "outerHTML" in $t[0] ) return $t[0].outerHTML;
else return $t.clone().wrap('<p>').parent().html();
}
так что метод клонирования на самом деле быстрее, чем метод wrap/unwrap
(запрос 1.7.2)
Это отлично подходит для изменения элементов в 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();
};
Я натолкнулся на это, когда искал ответ на свою проблему, которая заключалась в том, что я пытался удалить строку таблицы и затем добавить ее обратно внизу таблицы (потому что я динамически создавал строки данных, но хотел показать "Добавить новый" Запись 'типа строки внизу).
У меня была та же проблема, в том, что она возвращала innerHtml, поэтому отсутствовали теги TR, которые содержали идентификатор этой строки и означали, что невозможно повторить процедуру.
Ответ, который я нашел, состоял в том, что jquery remove()
Функция фактически возвращает элемент, который она удаляет, как объект. Итак, удалить и повторно добавить строку было так просто, как это...
var a = $("#trRowToRemove").remove();
$('#tblMyTable').append(a);
Если вы не удаляете объект, но хотите скопировать его в другое место, используйте clone()
функция вместо
Коллекция jQuery содержит список ссылок на html-элементы, выбранные запросом, доступ к каждому из которых можно получить по его индексу в том порядке, в котором он появляется в html-документе. Каждый элемент html по-прежнему имеет свойство externalHTML. Вы можете получить к нему доступ следующим образом:
$('<div>')[0].outerHTML
Таким образом, важно знать индекс элемента, который вы хотите иметь в наборе.
Плагин jQuery в качестве сокращения, чтобы напрямую получить весь элемент HTML:
jQuery.fn.outerHTML = function () {
return jQuery('<div />').append(this.eq(0).clone()).html();
};
И используйте это так: $(".element").outerHTML();
Чистый JavaScript:
var outerHTML = function(node) {
var div = document.createElement("div");
div.appendChild(node.cloneNode(true));
return div.innerHTML;
};
$("#myNode").parent(x).html();
Где "x" - номер узла, начиная с 0 в качестве первого, должен получить нужный вам узел, если вы пытаетесь получить конкретный. Если у вас есть дочерние узлы, вам действительно следует поместить идентификатор на тот, который вы хотите, чтобы просто сосредоточиться на этом. Использование этой методологии, и никакое "х" не сработало для меня.