Получить внешний 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

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

$('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)

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

Это отлично подходит для изменения элементов в 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 в качестве первого, должен получить нужный вам узел, если вы пытаетесь получить конкретный. Если у вас есть дочерние узлы, вам действительно следует поместить идентификатор на тот, который вы хотите, чтобы просто сосредоточиться на этом. Использование этой методологии, и никакое "х" не сработало для меня.

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

var myself = $('#div').children().parent();
Другие вопросы по тегам