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

717

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

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

  • 87
    Возмутительно, что у jQuery нет средств для подобных вещей. Мне это тоже нужно.
  • 9
    Я отправил запрос на добавление функции со ссылкой на эту ветку, и первоначальный ответ был положительным. bugs.jquery.com/ticket/8142
Показать ещё 8 комментариев
Теги:

29 ответов

189
Лучший ответ

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

У этого сайта есть решение для вас: jQuery: outerHTML | Yelotofu

jQuery.fn.outerHTML = function(s) {
    return s
        ? this.before(s).remove()
        : jQuery("<p>").append(this.eq(0).clone()).html();
};
  • 4
    Я видел это, но пытался избежать этого, потому что это казалось хакерским и, как будто должен был быть лучший способ, но он работает хорошо. Благодарю.
  • 354
    $ ( '[Селектор]') [0] .outerHTML
Показать ещё 10 комментариев
608

Я считаю, что в настоящее время (1/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 года. Учитывая эти данные, я поддерживаю свое решение для более простого кода по сравнению с обратной совместимостью.
Показать ещё 14 комментариев
324

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

$('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, потому что он меньше печатает и работает одинаково.

  • 5
    +1 за точное объяснение, что вы делаете и как это работает!
  • 1
    Я собираюсь вспомнить эту схему.
Показать ещё 12 комментариев
141

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

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

И для установки:

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

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

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

  • 4
    Очень аккуратный и маленький код по сравнению с другими ответами. Q: Имеет ли это те же ограничения externalHTML, как отмечено в других ответах? Это работает в FF <11?
  • 2
    Работает хорошо, это может быть просто лучшим решением здесь. Что касается браузеров, то они должны быть такими же совместимыми, как и externalHTLM. Метод prop () в основном просто получает свойство externalHTML.
Показать ещё 4 комментария
89

Расширить jQuery:

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

И используйте его следующим образом: $("#myTableRow").outerHTML();

  • 4
    Спасибо за преобразование моего предложения в расширение. Смешно, что JQ не имеет этого встроенного уже ..
  • 8
    Небольшая проблема с этим решением: вам нужно clone () перед wrap (), в противном случае вы оставляете лишний перенос <div> в документе.
Показать ещё 7 комментариев
44

Я согласен с Арпаном (Dec 13 '10 5:59).

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

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

$.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;
    }
};
  • 2
    Это отлично сработало для меня. Из-за ошибки в clone() и textarea мне потребовалось решение, не относящееся к клону, и это было точно.
  • 5
    +1 за использование нативного outerHTML где это возможно, поскольку он поддерживается Chrome в дополнение к Internet Explorer.
Показать ещё 2 комментария
18

Чтобы быть по-настоящему 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().

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

Вы также можете использовать 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">'
9

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

update Новая версия имеет лучший контроль, а также более удобный сервис 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);

Это позволит вам не только получить outerHTML одного элемента, но даже получить массив сразу нескольких элементов сразу! и может использоваться в обоих стандартных стилях 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>
8

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

document.getElementById(id).outerHTML

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

  • 0
    работал отлично для меня, именно то, что мне было нужно. Спасибо
  • 1
    Это не работает на FireFox
Показать ещё 2 комментария
6

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

Следующий код дает вам outerHTML оставляя дерево 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" ). externalHTML();

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

  • 1
    Просто используйте .clone, как подсказывает @mindplay в своем комментарии - это проще
5
// no cloning necessary    
var x = $('#xxx').wrapAll('<div></div>').parent().html(); 
alert(x);

Скрипт здесь: http://jsfiddle.net/ezmilhouse/Mv76a/

3

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

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

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

2

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

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

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

$('table#buttons').outerHTML();
2

Я сделал этот простой тест с outerHTML, являющимся решением tokimon (без клона), а внешнийHTML2 - решением jessica (clone)

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");

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

outerHTML: 81ms
externalHTML2: 439ms

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

получаем

outerHTML: 594ms
externalHTML2: 332ms

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

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

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

2

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

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

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

2

Аналогичное решение с добавлением remove() временного объекта DOM.

2

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

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

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

(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);

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

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

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

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

1

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

[].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, '')
1

Вот очень оптимизированный плагин outerHTML для 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 не нужен getter И сеттер: jQuery уже дает нам "replaceWith"...

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

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

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();
};
0

Все, кто ищет простое решение.

просто используйте внешний JavaScript-атрибут JavaScript

$('#elementSelector').get(0).outerHTML

0

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

document.querySelector('#selector')
0

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

-1

Я наткнулся на это, ища ответ на мою проблему, которая заключалась в том, что я пытался удалить строку таблицы, а затем добавить ее обратно в нижней части таблицы (поскольку я динамически создавал строки данных, но хотел показать Строка типа "Добавить новую запись" внизу).

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

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

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

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

-3

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

var myself = $('#div').children().parent();
-4
$("#myNode").parent(x).html(); 

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

  • 0
    Люди голосуют за это, хотите оставить комментарий? У меня есть код идти до РОДИТЕЛЯ, а затем получить HTML-содержимое, а не просто делать .html() для данного элемента. Это работает, и я хотел бы объяснить, почему это не так.
-13
$("#myTable").parent().html();

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

Это то, что тебе нужно?

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню