HTML etiketini değiştirmek için jQuery kullanılsın mı?


130

Mümkün mü?

misal:

$('a.change').click(function(){
//code to change p tag to h5 tag
});


<p>Hello!</p>
<a id="change">change</a>

Bu nedenle, değişiklik çapasını tıklamak, <p>Hello!</p>bölümün (örnek olarak) bir h5 etiketine dönüşmesine neden olmalıdır, böylece <h5>Hello!</h5>tıklamadan sonra sonlanırsınız . P etiketini silebileceğinizi ve onu bir h5 ile değiştirebileceğinizi biliyorum, ancak bir HTML etiketini gerçekten değiştirmek mümkün mü?

Yanıtlar:


211

Bir dom öğesi oluşturulduktan sonra, etiketin değişmez olduğuna inanıyorum. Bunun gibi bir şey yapmanız gerekir:

$(this).replaceWith($('<h5>' + this.innerHTML + '</h5>'));

2
Lütfen aşağıdaki yorumuma bakın ... stil uygulamak için belge yapısını değiştirmek en iyi yaklaşım değildir.
jrista

39
Bu, değiştirdiğiniz öğede olabilecek herhangi bir özelliği bozmaz mı? Silinen stil öznitelikleri, veri öznitelikleri vb. Nedeniyle bazı beklenmedik davranışlara yol açabilir ...
Xavi

5
"<" + el.outerHTML.replace(/(^<\w+|\w+>$)/g, "H5") + ">";Veya takılabilir jQuery işlevi: bağlantı
basil

65

İşte her şeyi, birçok yönden birçok öğe üzerinde yapacak bir uzantı ...

Örnek kullanım:

mevcut sınıfı ve öznitelikleri koruyun:

$('div#change').replaceTag('<span>', true);

veya

Mevcut sınıf ve öznitelikleri atın:

$('div#change').replaceTag('<span class=newclass>', false);

ya da

tüm div'leri aralıklarla değiştirin, sınıfları ve nitelikleri kopyalayın, ekstra sınıf adı ekleyin

$('div').replaceTag($('<span>').addClass('wasDiv'), true);

Eklenti Kaynağı:

$.extend({
    replaceTag: function (currentElem, newTagObj, keepProps) {
        var $currentElem = $(currentElem);
        var i, $newTag = $(newTagObj).clone();
        if (keepProps) {//{{{
            newTag = $newTag[0];
            newTag.className = currentElem.className;
            $.extend(newTag.classList, currentElem.classList);
            $.extend(newTag.attributes, currentElem.attributes);
        }//}}}
        $currentElem.wrapAll($newTag);
        $currentElem.contents().unwrap();
        // return node; (Error spotted by Frank van Luijn)
        return this; // Suggested by ColeLawrence
    }
});

$.fn.extend({
    replaceTag: function (newTagObj, keepProps) {
        // "return" suggested by ColeLawrence
        return this.each(function() {
            jQuery.replaceTag(this, newTagObj, keepProps);
        });
    }
});

2
Evet. Ve kayıt için, bir etiketi değiştirmek isteyebileceğiniz pek çok geçerli neden var. örneğin, hella standart dışı olan bir SPAN içinde DIV etiketleriniz varsa. Pdb yayıncılık için princexml'nin katı standartlarıyla çalışırken bu işlevden çok faydalandım.
Orwellophile

1
Gerçekten güzel görünüyor, ancak ne yazık ki değiştirilen öğenin tüm olaylarını kaybetmesine rağmen. Belki bu da halledilebilir - harika olurdu!
NPC

@NPC büyük şehirde hayat budur. Eğer elemanları değiştirecekseniz, kayıplar olacaktır. Olayları klonlamak için ilgili
jquery'yi

1
@FrankvanLuijn @orwellophile, return node;aslında return this;eklentinin "eski sürümünde" gösterildiği gibi olmalıdır . Bu arada gibi olayları zincirleme için essentiall olan$("tr:first").find("td").clone().replaceTag("li").appendTo("ul#list")
Cole Lawrence

1
Anlamıyorum, neden 2 işleve ihtiyacınız var? İkisine de ihtiyacınız var mı? Üzgünüm, kayboldum
João Pimentel Ferreira

12

Etiket türünü değiştirmek yerine, etiketin stilini (veya belirli bir kimliğe sahip etiketi) değiştirmelisiniz. Biçimsel değişiklikler uygulamak için belgenizin öğelerini değiştirmek iyi bir uygulama değildir. Bunu dene:

$('a.change').click(function() {
    $('p#changed').css("font-weight", "bold");
});

<p id="changed">Hello!</p>
<a id="change">change</a>

3
Bu durumda bile, belge yapınızı değiştirmemelisiniz. Tıklanan bir düzenlemeye yanıt olarak bir giriş görüntülemeniz gerekiyorsa, girişi yerleştirin ve ekranı yapıştırın: yok veya görünürlük: üzerinde gizli. <h5> öğesini gizleyin ve düğme tıklamasına yanıt olarak <input> değerini gösterin. Belge yapınızı sürekli olarak değiştiriyorsanız ... yolun sonunda bir sürü stil ve düzen sorunu istersiniz.
jrista

1
Kesinlikle. Javascript'iniz gömülü veya bağlantılı, bu nedenle endişeniz güvenlik ise, o zaman güvenlik yaklaşımınız bir şekilde kusurludur. Belgenizin içeriğini kullanıcının rolüne göre oluşturmalısınız ... Roller için içeriği karıştırmak, soruna yaklaşmanın güvenli bir yolu değildir. Birisi sisteminize yönetici olarak giriş yapmışsa, içeriği bir yönetici için oluşturun. Sisteminizde okuyucu olarak oturum açmışlarsa, içeriği bir okuyucu için oluşturun. Bu, erişilmemesi gereken içeriği tamamen ortadan kaldırır. İçerik oluşturulduktan sonra, belgenize stil vermek ve öğeleri göstermek / gizlemek için CSS kullanın.
jrista

2
Size katılıyorum ve önerilerinizi projeye aldım. Yalnızca bir yönetici oturum açtığında oluşturulan yönetici öğelerini göstermek için toggle () kullanacağım. Orijinal soruyla (doğrudan) alakası olmasa da, bu muhtemelen başlangıçta gittiğim yönden daha iyi bir çözüm. Şerefe!
Christopher Cooper

1
Woo! Başka bir kötü güvenlik darbesi daha geldi! Bir galibiyet ve herkes için tur! (bira simgesini buraya ekleyin)
jrista

1
Güvenlik için istemci tarafındaki javascript'e güvenmek aslında hiç güvenlik olmamasından daha KÖTÜDÜR . Neden? Çünkü güvenliğiniz olduğunu sanıyorsunuz ama aslında yok.
BryanH

8

İlk cevabın ihtiyacım olan şey olmadığını fark ettim, bu yüzden birkaç değişiklik yaptım ve buraya geri göndereceğimi düşündüm.

Gelişmiş replaceTag(<tagName>)

replaceTag(<tagName>, [withDataAndEvents], [withDataAndEvents])

Argümanlar:

  • tagName: Dize
    • Etiket adı, örneğin "div", "span" vb.
  • withDataAndEvents: Boole
    • "Olay işleyicilerinin öğelerle birlikte kopyalanması gerekip gerekmediğini belirten bir Boole. JQuery 1.4'ten itibaren öğe verileri de kopyalanacaktır." bilgi
  • deepWithDataAndEvents: Boole ,
    • Klonlanan öğenin tüm alt öğeleri için olay işleyicilerinin ve verilerinin kopyalanması gerekip gerekmediğini belirten bir Boole. Varsayılan olarak değeri, ilk bağımsız değişkenin değeriyle eşleşir (varsayılan olarak yanlıştır). " Bilgi

İadeler:

Yeni oluşturulmuş bir jQuery öğesi

Tamam, şimdi burada birkaç cevap olduğunu biliyorum, ama bunu tekrar yazmayı kendime aldım.

Burada, klonlamayı kullandığımız gibi etiketi değiştirebiliriz. .Clone () ile aynı sözdizimini izliyoruzwithDataAndEvents ve alt düğümlerin verilerini ve eğer kullanılıyorsa olayları deepWithDataAndEventskopyalıyoruz .

Misal:

$tableRow.find("td").each(function() {
  $(this).clone().replaceTag("li").appendTo("ul#table-row-as-list");
});

Kaynak:

$.extend({
    replaceTag: function (element, tagName, withDataAndEvents, deepWithDataAndEvents) {
        var newTag = $("<" + tagName + ">")[0];
        // From [Stackoverflow: Copy all Attributes](http://stackoverflow.com/a/6753486/2096729)
        $.each(element.attributes, function() {
            newTag.setAttribute(this.name, this.value);
        });
        $(element).children().clone(withDataAndEvents, deepWithDataAndEvents).appendTo(newTag);
        return newTag;
    }
})
$.fn.extend({
    replaceTag: function (tagName, withDataAndEvents, deepWithDataAndEvents) {
        // Use map to reconstruct the selector with newly created elements
        return this.map(function() {
            return jQuery.replaceTag(this, tagName, withDataAndEvents, deepWithDataAndEvents);
        })
    }
})

Bunun seçilen öğenin yerine geçmediğini , yeni oluşturulan öğeyi döndürdüğünü unutmayın.


2
Unutmayın .children()herhangi tamamen metin düğümleri içermez. .contents()IIRC'yi denemek isteyebilirsiniz .
Orwellophile

5

Fikir, öğeyi sarmak ve içeriği açmaktır:

function renameElement($element,newElement){

    $element.wrap("<"+newElement+">");
    $newElement = $element.parent();

    //Copying Attributes
    $.each($element.prop('attributes'), function() {
        $newElement.attr(this.name,this.value);
    });

    $element.contents().unwrap();       

    return $newElement;
}

Örnek kullanım:

renameElement($('p'),'h5');

gösteri


0

JQuery nesnenizin bir dize gösterimini kullandığınız ve etiket adını normal ifadeler ve temel JavaScript kullanarak değiştirdiğiniz bir yaklaşım buldum. Herhangi bir içeriği kaybetmeyeceksiniz ve her bir öznitelik / özellik üzerinde döngü yapmanız gerekmeyecek.

/*
 * replaceTag
 * @return {$object} a new object with replaced opening and closing tag
 */
function replaceTag($element, newTagName) {

  // Identify opening and closing tag
  var oldTagName = $element[0].nodeName,
    elementString = $element[0].outerHTML,
    openingRegex = new RegExp("^(<" + oldTagName + " )", "i"),
    openingTag = elementString.match(openingRegex),
    closingRegex = new RegExp("(<\/" + oldTagName + ">)$", "i"),
    closingTag = elementString.match(closingRegex);

  if (openingTag && closingTag && newTagName) {
    // Remove opening tag
    elementString = elementString.slice(openingTag[0].length);
    // Remove closing tag
    elementString = elementString.slice(0, -(closingTag[0].length));
    // Add new tags
    elementString = "<" + newTagName + " " + elementString + "</" + newTagName + ">";
  }

  return $(elementString);
}

Son olarak, mevcut nesneyi / düğümü aşağıdaki gibi değiştirebilirsiniz:

var $newElement = replaceTag($rankingSubmit, 'a');
$('#not-an-a-element').replaceWith($newElement);

0

Bu benim çözümüm. Etiketler arasında geçiş yapılmasına izin verir.

<!DOCTYPE html>
<html>
<head>
	<title></title>

<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script type="text/javascript">

function wrapClass(klass){
	return 'to-' + klass;
}

function replaceTag(fromTag, toTag){
	
	/** Create selector for all elements you want to change.
	  * These should be in form: <fromTag class="to-toTag"></fromTag>
	  */
	var currentSelector = fromTag + '.' + wrapClass(toTag);

	/** Select all elements */
	var $selected = $(currentSelector);

	/** If you found something then do the magic. */
	if($selected.size() > 0){

		/** Replace all selected elements */
		$selected.each(function(){

			/** jQuery current element. */
			var $this = $(this);

			/** Remove class "to-toTag". It is no longer needed. */
			$this.removeClass(wrapClass(toTag));

			/** Create elements that will be places instead of current one. */
			var $newElem = $('<' + toTag + '>');

			/** Copy all attributes from old element to new one. */
			var attributes = $this.prop("attributes");
			$.each(attributes, function(){
				$newElem.attr(this.name, this.value);
			});

			/** Add class "to-fromTag" so you can remember it. */
			$newElem.addClass(wrapClass(fromTag));

			/** Place content of current element to new element. */
			$newElem.html($this.html());

			/** Replace old with new. */
			$this.replaceWith($newElem);
		});

		/** It is possible that current element has desired elements inside.
		  * If so you need to look again for them.
		  */
		replaceTag(fromTag, toTag);
	}
}


</script>

<style type="text/css">
	
	section {
		background-color: yellow;
	}

	div {
		background-color: red;
	}

	.big {
		font-size: 40px;
	}

</style>
</head>
<body>

<button onclick="replaceTag('div', 'section');">Section -> Div</button>
<button onclick="replaceTag('section', 'div');">Div -> Section</button>

<div class="to-section">
	<p>Matrix has you!</p>
	<div class="to-section big">
		<p>Matrix has you inside!</p>
	</div>
</div>

<div class="to-section big">
	<p>Matrix has me too!</p>
</div>

</body>
</html>


0

Bu, jQuery kullanarak DOM'nuzdaki HTML etiketlerini değiştirmenin hızlı yoludur. Bu replaceWith () işlevinin çok kullanışlı olduğunu düşünüyorum.

   var text= $('p').text();
   $('#change').on('click', function() {
     target.replaceWith( "<h5>"+text+"</h5>" );
   });

0

JQuery yardımı ile metoda göre & değer elde etmek için, değerleri aldıktan sonra metodu kullanarak bu şekilde bir data-*öznitelik elde edebilirsiniz . Aşağıdakini değiştirmeden herhangi bir etiket değişimini kolayca yönetmek için bu özellik tekniği (tüm etiket değişimi için ortak kod). Umarım aşağıdaki pasaj size çok yardımcı olur.data-replace="replaceTarget,replaceBy"replaceTargetreplaceBy.split().replaceWith()
data-*

$(document).on('click', '[data-replace]', function(){
  var replaceTarget = $(this).attr('data-replace').split(',')[0];
  var replaceBy = $(this).attr('data-replace').split(',')[1];
  $(replaceTarget).replaceWith($(replaceBy).html($(replaceTarget).html()));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<p id="abc">Hello World #1</p>
<a href="#" data-replace="#abc,<h1/>">P change with H1 tag</a>
<hr>
<h2 id="xyz">Hello World #2</h2>
<a href="#" data-replace="#xyz,<p/>">H1 change with P tag</a>
<hr>
<b id="bold">Hello World #2</b><br>
<a href="#" data-replace="#bold,<i/>">B change with I tag</a>
<hr>
<i id="italic">Hello World #2</i><br>
<a href="#" data-replace="#italic,<b/>">I change with B tag</a>


0

Aşağıdaki işlev hile yapar ve tüm özellikleri saklar. Örneğin bunu şöyle kullanıyorsunuz:changeTag("div", "p")

function changeTag(originTag, destTag) {
  while($(originTag).length) {
    $(originTag).replaceWith (function () {
      var attributes = $(this).prop("attributes");
      var $newEl = $(`<${destTag}>`)
      $.each(attributes, function() {
        $newEl.attr(this.name, this.value);
      });  
      return $newEl.html($(this).html())
    })
  }
}

Çalıştığından emin olmak için aşağıdaki örneği kontrol edin

function changeTag(originTag, destTag) {
  while($(originTag).length) {
    $(originTag).replaceWith (function () {
      var attributes = $(this).prop("attributes");
      var $newEl = $(`<${destTag}>`)
      $.each(attributes, function() {
        $newEl.attr(this.name, this.value);
      });  
      return $newEl.html($(this).html())
    })
  }
}

changeTag("div", "p")

console.log($("body").html())
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="A" style="font-size:1em">
  <div class="B" style="font-size:1.1em">A</div>
</div>
<div class="C" style="font-size:1.2em">
  B
</div>
</body>


-1

Etiketi değiştirmeniz için özel bir neden var mı? Metni büyütmek istiyorsanız, p etiketinin CSS sınıfını değiştirmek bunun için daha iyi bir yol olacaktır.

Bunun gibi bir şey:

$('#change').click(function(){
  $('p').addClass('emphasis');
});

Öğeyi / etiketi değiştirmeyi istememin nedeni, sayfanın başka bir yerinde bir "düzenle" düğmesi tıklandığında bir etiketi (tür ilgisiz olsa da bir <h5>) <input> olarak değiştirmeye çalışmamdır. .
Christopher Cooper
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.