Використання jQuery для заміни одного тегу іншим


101

Мета:

Використовуючи jQuery, я намагаюся замінити всі виникнення:

<code> ... </code>

з:

<pre> ... </pre>

Моє рішення:

Я дійшов до наступного,

$('code').replaceWith( "<pre>" + $('code').html() + "</pre>" );

Проблема з моїм рішенням:

але проблема полягає в тому, що він замінює все між (другим, третім, четвертим тощо) тегами "коду" вмістом між першими тегами "коду".

напр

<code> A </code>
<code> B </code>
<code> C </code>

стає

<pre> A </pre>
<pre> A </pre>
<pre> A </pre>

Я думаю, що мені потрібно використовувати "це" та якусь функцію, але я боюся, що я все ще навчаюся і не дуже розумію, як скласти рішення разом.


Виправлено розгортання рішення jon - перевірити його;)
Jens Roland

Відповіді:


157

Ви можете передати функцію .replaceWith [docs] :

$('code').replaceWith(function(){
    return $("<pre />", {html: $(this).html()});
});

Всередині функції thisвідноситься до codeелемента, що обробляється в даний час .

DEMO

Оновлення: Немає великої різниці в продуктивності , але якщо codeелементи мають інші діти HTML, додавання дітей замість їх серіалізації вважається правильнішим:

$('code').replaceWith(function(){
    return $("<pre />").append($(this).contents());
});

1
Це, здається, є найелегантнішим рішенням, тому я визнаю, що не розумію, що відбувається всередині функції substituWith. хотілося б почути більше. тобто як призначається теги відкриття та закриття? чи досягає простір у <pre />?
Джон

2
@jon: Це коротка рука для створення нових елементів. Більше інформації можна знайти тут: api.jquery.com/jQuery/#jQuery2 . jQuery петляє над усіма елементами і виконує функцію для кожного з них (те саме, що .eachробиться).
Фелікс Клінг

@jon: Але перевірити рішення Йенса ще раз, він його виправив.
Фелікс Клінг

1
+1 за приємний трюк - це може бути використано набагато більше, ніж просто проста заміна тегів на теги.
Єнс Роланд

@FelixKling Чи не буде це перезаписано атрибути кодових тегів?
tewathia

80

Це набагато приємніше:

$('code').contents().unwrap().wrap('<pre/>');

Хоча, безумовно , рішення Фелікса Клинга приблизно вдвічі швидше :


4
працював як шарм, на мій погляд, це здається найефективнішим рішенням. :)
jon

ага. так, хлопці, ви мали рацію. це не працювало і для мене. спасибі за те, що це зробив!
Джон

1
FWIW, $('code').children()поверне порожній об’єкт jQuery для прикладу вище, оскільки в codeелементів немає дочірніх елементів вузлів. Хоча це працює, якщо є дочірні елементи.
Фелікс Клінг

1
Виправлено - вірно, коли вміст складається з одного текстового вузла, children()працювати не буде. Використання contents()натомість працює ідеально. jsfiddle.net/7Yne9
Йенс Роланд

1
Ось версія jsperf, яка не порушує сторінку: jsperf.com/substituting-one-tag-for-another-with-jquery/2, і ви бачите, що різниця швидкостей вже не така величезна. Ваше рішення відбувається повільніше, оскільки ви виконуєте дві маніпуляції з DOM на один елемент: unwrapвидаляє батьківський додаток і додає дітей до дерева, wrapзнову від'єднує їх та додає нового батьківського.
Фелікс Клінг

26

Це правильно, що ви завжди будете отримувати codeвміст першого , тому що$('code').html() ви завжди будете посилатися на перший елемент, де б ви його не використовували.

Натомість ви можете використовувати .eachітерацію над усіма елементами та змінювати кожен окремо:

$('code').each(function() {
    $(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
    // this function is executed for all 'code' elements, and
    // 'this' refers to one element from the set of all 'code'
    // elements each time it is called.
});

12

Спробуйте це:

$('code').each(function(){

    $(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );

});

http://jsfiddle.net/mTGhV/


Ого. ви, хлопці, придумали таке саме рішення протягом 2 секунд один від одного. є невеликі відмінності у форматуванні. Я не впевнений, на який слід звернути увагу - мені дуже не подобається пробіл між функцією та () у відповіді томасу та 2 рядки порожнього простору у відповіді kokos є досить точністю + має бути пробіл між () та {
Майкл Більстра


6

На основі відповіді Фелікса.

$('code').replaceWith(function() {
    var replacement = $('<pre>').html($(this).html());
    for (var i = 0; i < this.attributes.length; i++) {
        replacement.attr(this.attributes[i].name, this.attributes[i].value);
    }
    return replacement;
});

Це відтворить атрибути codeтегів у замінникуpre тегах .

Редагувати: це замінить навіть ті codeтеги, які знаходяться всередині innerHTMLінших codeтегів.

function replace(thisWith, that) {
    $(thisWith).replaceWith(function() {
        var replacement = $('<' + that + '>').html($(this).html());
        for (var i = 0; i < this.attributes.length; i++) {
            replacement.attr(this.attributes[i].name, this.attributes[i].value);
        }
        return replacement;
    });
    if ($(thisWith).length>0) {
        replace(thisWith, that);
    }
}

replace('code','pre');

2
найкраща відповідь поки що. Інші - майже все те саме, що справді дивно, що люди їх висловлюють. Конграц за те, що він єдиний, хто думав про атрибути.
Гільхерм Девід да Коста


2

Якщо ви використовували ванільний JavaScript, ви:

  • Створіть новий елемент
  • Перемістіть діти старого елемента в новий елемент
  • Вставте новий елемент перед старим
  • Видаліть старий елемент

Ось jQuery еквівалент цього процесу:

$("code").each(function () {
    $("<pre></pre>").append(this.childNodes).insertBefore(this);
    $(this).remove();
});

Ось URL-адреса jsperf:
http://jsperf.com/substituting-one-tag-for-another-with-jquery/7

PS: Всі рішення, які використовують .html()або .innerHTMLє руйнівними .



0
$('code').each(function(){
    $(this).replaceWith( "<pre>" + $(this).html()  + "</pre>" );
    });

Найкращий і чистий спосіб.


0

Ви можете використовувати html функцію jQuery. Нижче наведено зразок, який замінює тег коду попереднім тегом, зберігаючи всі атрибути коду.

    $('code').each(function() {
        var temp=$(this).html();
        temp=temp.replace("code","pre");
        $(this).html(temp);
    });

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


0

Зроблено jqueryплагін, зберігаючи також атрибути.

$.fn.renameTag = function(replaceWithTag){
  this.each(function(){
        var outerHtml = this.outerHTML;
        var tagName = $(this).prop("tagName");
        var regexStart = new RegExp("^<"+tagName,"i");
        var regexEnd = new RegExp("</"+tagName+">$","i")
        outerHtml = outerHtml.replace(regexStart,"<"+replaceWithTag)
        outerHtml = outerHtml.replace(regexEnd,"</"+replaceWithTag+">");
        $(this).replaceWith(outerHtml);
    });
    return this;
}

Використання:

$('code').renameTag('pre')

0

Усі наведені тут відповіді припускають (як показує приклад запитання), що в тегу немає атрибутів. Якщо прийнята відповідь ведеться на цьому:

<code class='cls'>A</code>

якщо буде замінено на

<pre>A</pre>

Що робити, якщо ви також хочете зберегти атрибути - що означає заміна тегу ...? Це рішення:

$("code").each( function(){
    var content = $( "<pre>" );

    $.each( this.attributes, function(){ 
         content.attr( this.name, this.value );
    } );

    $( this ).replaceWith( content );
} );

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

це було б зроблено, додавшиcontent.html( this.html )
Патріка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.