Remova uma tag HTML, mas mantenha o innerHtml

148

Eu tenho algum HTML simples que eu preciso remover a formatação simples.

A nice house was found in <b>Toronto</b>.

Preciso remover o negrito, mas deixar a frase intacta.

Como isso é possível no jQuery?

Ian Vink
fonte

Respostas:

301
$('b').contents().unwrap();

Isso seleciona todos os <b>elementos e, em seguida, usa.contents() para direcionar o conteúdo de texto do e <b>, em seguida.unwrap() , para remover seu <b>elemento pai .


Para obter o melhor desempenho, sempre vá nativo:

var b = document.getElementsByTagName('b');

while(b.length) {
    var parent = b[ 0 ].parentNode;
    while( b[ 0 ].firstChild ) {
        parent.insertBefore(  b[ 0 ].firstChild, b[ 0 ] );
    }
     parent.removeChild( b[ 0 ] );
}

Isso será muito mais rápido do que qualquer solução jQuery fornecida aqui.

user113716
fonte
1
Eu estava sentado escrevendo uma resposta quase idêntica a respeito unwrap()e não conseguia me lembrar de como obter a parte do texto, esqueci .contents()- excelente.
Orbling
2
Enquanto isso funciona, também é bastante lento em comparação com .replacewith()a passagem extra do DOM ... se for uma <b>tag apenas com HTML, fica ainda mais rápido.
Nick Craver
Além disso, se você quiser apenas desembrulhar uma tag de extensão ou fonte específica, poderá fazer algo assim: $ (". ClassName font"). Contents (). Desembrulhar ();
9788 Steve Jobs #
se html <div> abc </div> abc break line não for válido? como posso segurá-lo se usar <div> para quebra de linha? @ user113716
Hoa.Tran
1
Obrigado, isso foi muito útil. Eu adicionei parent.normalize()depois parent.removeChild(...para mesclar nós de texto adjacentes. Isso foi útil se você estiver modificando continuamente a página.
Justin Harris
52

Você também pode usar .replaceWith(), assim:

$("b").replaceWith(function() { return $(this).contents(); });

Ou se você sabe que é apenas uma string:

$("b").replaceWith(function() { return this.innerHTML; });

Isso pode fazer uma grande diferença se você estiver desembrulhando muitos elementos, pois qualquer uma das abordagens acima é significativamente mais rápida que o custo .unwrap().

Nick Craver
fonte
Nick, também gosto muito da sua resposta. Eu escolhi o outro porque a quantidade de tags / texto que vou usar no meu aplicativo para iPad (dados locais) é pequena, portanto o desempenho não é muito importante. A resposta de Partick é um pouco mais simples para eu manter. Dividir os cabelos em duas ótimas soluções, mas eu só poderia dar uma.
Ian Vink
1
@ BahaiResearch.com - Se o desempenho não é um problema, então vá absolutamente simples ... Estou fornecendo isso para outras pessoas que o encontrarem mais tarde, que possam estar preocupadas com isso :)
Nick Craver
Eu estava tentando usar esse exemplo com uma caixa de texto, mas estava me matando porque o conteúdo dentro eram tags html que eu queria avaliar e não apenas exibidas como texto. Acabei usando: $ ('textarea'). ReplaceWith (function () {return $ (this) .val ();});
Will Sampson
13

A maneira mais simples de remover elementos html internos e retornar apenas texto seria a função JQuery .text () .

Exemplo:

var text = $('<p>A nice house was found in <b>Toronto</b></p>');

alert( text.html() );
//Outputs A nice house was found in <b>Toronto</b>

alert( text.text() );
////Outputs A nice house was found in Toronto

jsFiddle Demo

WebChemist
fonte
5

Que tal agora?

$("b").insertAdjacentHTML("afterend",$("b").innerHTML);
$("b").parentNode.removeChild($("b"));

A primeira linha copia o conteúdo HTML da bmarca para o local diretamente após a bmarca e, em seguida, a segunda linha remove ob marca do DOM, deixando apenas seu conteúdo copiado.

Normalmente, envolvo isso em uma função para facilitar o uso:

function removeElementTags(element) {
   element.insertAdjacentHTML("afterend",element.innerHTML);
   element.parentNode.removeChild(element);
}

Todo o código é realmente Javascript puro, o único JQuery usado é o de selecionar o elemento a ser segmentado (o b tag no primeiro exemplo). A função é apenas JS: D

Veja também:

Toastrackenigma
fonte
3
// For MSIE:
el.removeNode(false);

// Old js, w/o loops, using DocumentFragment:
function replaceWithContents (el) {
  if (el.parentElement) {
    if (el.childNodes.length) {
      var range = document.createRange();
      range.selectNodeContents(el);
      el.parentNode.replaceChild(range.extractContents(), el);
    } else {
      el.parentNode.removeChild(el);
    }
  }
}

// Modern es:
const replaceWithContents = (el) => {
  el.replaceWith(...el.childNodes);
};

// or just:
el.replaceWith(...el.childNodes);

// Today (2018) destructuring assignment works a little slower
// Modern es, using DocumentFragment.
// It may be faster than using ...rest
const replaceWithContents = (el) => {
  if (el.parentElement) {
    if (el.childNodes.length) {
      const range = document.createRange();
      range.selectNodeContents(el);
      el.replaceWith(range.extractContents());
    } else {
      el.remove();
    }
  }
};
redisko
fonte
1

Outra solução nativa (no café):

el = document.getElementsByTagName 'b'

docFrag = document.createDocumentFragment()
docFrag.appendChild el.firstChild while el.childNodes.length

el.parentNode.replaceChild docFrag, el

Não sei se é mais rápido que a solução do user113716, mas pode ser mais fácil entender para alguns.

GijsjanB
fonte
1

A resposta mais simples é alucinante:

O outerHTML é suportado no Internet Explorer 4!

Aqui está para fazê-lo com javascript, mesmo sem jQuery

function unwrap(selector) {
    var nodelist = document.querySelectorAll(selector);
    Array.prototype.forEach.call(nodelist, function(item,i){
        item.outerHTML = item.innerHTML; // or item.innerText if you want to remove all inner html tags 
    })
}

unwrap('b')

Isso deve funcionar em todos os principais navegadores, incluindo o IE antigo. no navegador recente, podemos até chamar cada um diretamente no nodelist.

function unwrap(selector) {
    document.querySelectorAll('b').forEach( (item,i) => {
        item.outerHTML = item.innerText;
    } )
}
izzulmakin
fonte