Отримайте зовнішній HTML вибраного елемента


791

Я намагаюся отримати 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 ("externalHTML")
хлопець mograbi

Відповіді:


189

2014 р. Редагувати: Питання та відповідь - від 2010 року. Наразі кращого рішення не було широко. Зараз багато інших відповідей краще: Еріка Ху, або Ре Капча, наприклад.

Здається, цей сайт має рішення для вас: jQuery: externalHTML | Єлотофу

jQuery.fn.outerHTML = function(s) {
    return s
        ? this.before(s).remove()
        : jQuery("<p>").append(this.eq(0).clone()).html();
};

4
Я бачив це, але намагався цього уникнути, тому що, здавалося, хакіт і, як би, мав бути кращий спосіб, але це працює добре. Дякую.
Райан

359
$ ('[selector]') [0] .outerHTML
drogon

25
@drogon: Майте на увазі, що outerHTMLвін підтримується у Firefox лише з 11 версії (березень 2012 року).
Блейз

8
@PavingWays: Захист Firefox: outerHTMLце власний атрибут, винайдений Microsoft, а не стандарт W3C. (Веселий факт: innerHTMLстандартизований лише з HTML5 )
Блайз

3
pure jsel.outerHTML || document.createElement('div').appendChild( el.cloneNode( true ) ).parentNode.innerHTML
раб

674

Я вважаю, що в даний час (5/1/2012) усі основні браузери підтримують зовнішню функціюHTML. Мені здається, цього фрагмента достатньо. Я особисто хотів би запам'ятати це:

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

EDIT : Основна статистика підтримки дляelement.outerHTML


14
@SalmanPK FireFox не підтримував цю власність до 2011-11-11. bugzilla.mozilla.org/show_bug.cgi?id=92264 Є ще багато користувачів, які затрималися на 3.6. Я думаю, що це насправді прекрасний приклад того, чому б хто-небудь вирішив використовувати jQuery над нативними функціоналами.
Люцифер Сем

8
@LuciferSam Firefox 3.6 має ~ 6% світової частки на ринку за даними gs.statcounter.com Однак, фільтруючи результати за останні 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теги, тому що він менше друкує і працює так само.


82
Цікаво, чому команда jQuery не додає метод externalHtml ()?
Донні В.

1
@Derek, це не має значення. Я використовую DIV в якості обгортки для того, щоб щось у нього всередині було.
Воломіке

11
.clone (). wrap ('<p>') .parent (). html (); коротше
Uğur Gümüşhan

1
Так, менше натискань клавіш, і досягається той же ефект.
Воломіке

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 .


4
Дуже акуратний і невеликий код порівняно з іншими відповідями. Питання: Чи мають такі зовнішні обмеження HTMLHT, як зазначено в інших відповідях? Чи працює це у FF <11?
MacroMan

3
Тут добре працює, це може бути найкращим рішенням тут. Що стосується браузерів, це повинно бути настільки ж сумісним, як і зовнішнійHTLM. Метод prop () - це лише отримання зовнішнього властивостіHTML.
Том Том

2
Це рішення краще, проте Jquery 1.6.1 було випущено в 2011 році. Питання (і моя відповідь) - з 2010 року.
Девід В.

1
Для мене "$ ('[selector]') [0] .outerHTML;" не працював ні в якому разі, але "$ ('# item-to be be select'). prop ('externalHTML');" так!
Едуардо Лусіо

2
$ ('# item-to be be select'). attr ('зовнішнійHTML'); // ** Для більш раннього jQuery's
Meetai.com

91

Розширити jQuery:

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

І використовуйте його так: $("#myTableRow").outerHTML();


8
Невелика проблема з цим рішенням: вам потрібно клонувати () перед тим, як обгортати (), інакше ви залишите зайве обгортання <div> в документі.
mindplay.dk

1
Дякую, mindplay.dk - я відредагував код, щоб включити вашу пропозицію. :)
jessica

2
Що з того, щоб це змінити назад: return $('<div>').append(this.clone()).html();це лише трохи більше точності.
Джастін Варкентін

2
Спершу слід перевірити наявність зовнішніх HTMLML і просто використовувати це для браузерів, які його підтримують
James Westgate

Це чудово для таких людей, як я, які люблять будувати HTML у відповідях AJAX за допомогою об’єктів jQuery та функцій .appendTo () та .append (). .outerHTML не працює в тих випадках, коли я бачив тестування. Хтось ще може захотіти це перевірити більше, але я не маю часу.
Шон Кендл

43

Я згоден з Арпаном (13 грудня 10.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;
    }
};

2
Це прекрасно працювало для мене. Через помилку з clone()і textarea'я, мені було потрібно неклонне рішення, і це було плямою на.
Шпігфорд

5
+1 для використання нативного, outerHTMLколи це можливо, оскільки він підтримується Chrome на додаток до Internet Explorer.
Енді Е

9
if (! ('externalHTML' в $ t [0])) попередження ('God dammit, оновіть ваш браузер');
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 () / unrap () буде кращим або гіршим, ніж clone ()?
IMSoP

1
IMSoP: Зазвичай завершення / розгортання буде швидше, оскільки клон повинен копіювати всі дочірні елементи та атрибути елемента. wrap () створює лише один елемент, а unrap () знищує його, всі інші елементи просто переміщуються, що більшість часу є досить швидкою операцією.
Енді Е

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

Щоб зробити FULL плагін 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);

Це дозволить вам не тільки отримати зовнішній HTMLML одного елемента, але навіть отримати повернення масиву відразу декількох елементів! і може використовуватися в обох стандартних стилях 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();

Приклади фрагментів:


9

ви також можете зробити це таким чином

document.getElementById(id).outerHTML

де id - ідентифікатор елемента, який ви шукаєте


4
$("#" + id).attr("id")неймовірно зайвий. Якщо у вас вже є ідентифікатор у змінній, чому ви використовуєте селектор jquery, щоб витягнути елемент із дому, а потім запитати його атрибут ID?
Сем Дуфель

7

Я використовував рішення Джессіки (яке відредагував Джош), щоб отримати зовнішній HTML для роботи над Firefox. Однак проблема полягає в тому, що мій код порушився, оскільки її рішення загорнуло елемент у DIV. Додавання ще одного рядка коду вирішило цю проблему.

Наступний код дає вам зовнішнійHTML, залишаючи дерево 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, пропонує у своєму коментарі - простіше
Ярин


4

Якщо сценарій динамічно додає новий рядок, ви можете використовувати це:

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

.myrow- це ім'я класу <tr>. Він робить копію останнього рядка і вставляє його як новий останній рядок. Це також працює в IE7 , тоді як [0].outerHTMLметод не дозволяє призначити в ie7


3

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

Це означає , що ви також можете повторити атрибути елемента для побудови HTML-рядкового подання цього елемента. Мабуть, саме таким чином буде реалізована будь-яка зовнішня HTML-функція, якщо jQuery додати її.


3

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

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

Звичайно, використовуйте його так:

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


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

Редагувати: виправлена ​​ще одна проблема з рішенням Джоша, див. Коментар вище.


1
Більшість методів "getter" jQuery повертають дані лише для першого елемента, тому було б більше сенсу відповідати цій поведінці.
Енді Е

Я думаю, я чітко заявив, чому це працює так? Це створило б некрасивий / складний код, коли у вас є список елементів - якщо з якоїсь причини ви хочете розмітку лише для першого елемента, просто використовуйте: спочатку у своєму селекторі.
mindplay.dk

Звичайно, так само, як ви могли просто використовувати карту з рішенням усіх інших, щоб отримати HTML з декількох елементів. Все, що я говорив, - це більш послідовне узгодження поведінки стандартних методів jQuery.
Енді Е


2

Я зробив цей простий тест, коли зовнішнійHTML був розчином токімона (без клону), а зовнішнійHTML2 був розчином Джессіки (клон)

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
outerHTML2: 439ms

але якщо ми використовуємо рішення tokimon без нативної функції зовнішньогоHTML (яка зараз підтримується, мабуть, майже в кожному браузері)

ми отримуємо

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

тому метод клонування насправді швидший, ніж метод wrap / unrap
(jquery 1.7.2)


2

Ось дуже оптимізований зовнішній плагін HTML для jquery: ( http://jsperf.com/outerhtml-vs-jquery-clone-hack/5 => два інші фрагменти швидкого коду не сумісні з деякими браузерами, такими як 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 вже дає нам «замінуВ».

@mindplay => Чому ви приєднуєтесь до всіх зовнішніхHTML? jquery.html повертає лише вміст HTML елемента ПЕРШИЙ.

(Вибачте, у мене недостатньо репутації для написання коментарів)


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, '')

2

Це дуже просто з ванільним JavaScript ...

document.querySelector('#selector')

1

Це відмінно підходить для зміни елементів дому, але НЕ працює, тобто при передачі рядка 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

Я зіткнувся з цим під час пошуку відповіді на мою проблему, яка полягала в тому, що я намагався видалити рядок таблиці, а потім додав її внизу таблиці (тому що я динамічно створював рядки даних, але хотів показати "Додати нове" Запис "введіть рядок внизу).

У мене була така ж проблема, що він повертав InternalHtml, тому не було тегів 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();


-2
$("#myNode").parent(x).html(); 

Де 'x' - номер вузла, починаючи з 0 як перший, повинен отримати потрібний потрібний вузол, якщо ви намагаєтесь отримати конкретний. Якщо у вас є дочірні вузли, вам слід дійсно вводити ідентифікатор на той, який ви хочете, хоча на цьому нулі просто нульовий. Використовуючи цю методологію, і жоден "х" не працював мені добре.


1
Люди, які голосують за це, хочуть залишити коментар? У мене з кодом перейдіть до БАСЬКОГО, а потім дістаньте HTML вмісту - не просто виконайте .html()вказаний елемент. ЦЕ ПРАЦЮЄ, і я хотів би пояснити, чому це не так.
vapcguy


-12
$("#myTable").parent().html();

Можливо, я не правильно розумію ваше запитання, але це отримає html-адресу батьківського елемента вибраного елемента.

Це те, що ти шукаєш?


25
Вочевидь ні, тому що якщо у цього батька є інші діти, він також отримає цей html.
Девід В.

1
...що він сказав. Я шукаю сам елемент, а не його та всіх інших його батьків. Як це отримало два голоси ???
Райан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.