Ответ 1
Как только элемент dom создается, я считаю, что тег неизменен. Вам нужно будет сделать что-то вроде этого:
$(this).replaceWith($('<h5>' + this.innerHTML + '</h5>'));
Возможно ли это?
Пример:
$('a.change').click(function(){
//code to change p tag to h5 tag
});
<p>Hello!</p>
<a id="change">change</a>
Таким образом, щелчок аннота изменения должен привести к тому, что раздел <p>Hello!</p>
изменится на (как пример) тег h5, после чего вы получите <h5>Hello!</h5>
после клика. Я понимаю, что вы можете удалить тег p и заменить его на h5, но есть ли вообще что-либо изменить HTML-тег?
Как только элемент dom создается, я считаю, что тег неизменен. Вам нужно будет сделать что-то вроде этого:
$(this).replaceWith($('<h5>' + this.innerHTML + '</h5>'));
Здесь расширение, которое будет делать все это, на столько же элементов, сколько...
Пример использования:
сохранить существующий класс и атрибуты:
$('div#change').replaceTag('<span>', true);
или
Отменить существующий класс и атрибуты:
$('div#change').replaceTag('<span class=newclass>', false);
или даже
заменить все divs на пробелы, классы и атрибуты копирования, добавить дополнительное имя класса
$('div').replaceTag($('<span>').addClass('wasDiv'), true);
Источник плагина:
$.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);
});
}
});
Вместо того, чтобы изменять тип тега, вы должны изменить стиль тега (вернее, тег с определенным идентификатором). Неправильная практика изменения элементов вашего документа для применения стилистических изменений. Попробуйте следующее:
$('a.change').click(function() {
$('p#changed').css("font-weight", "bold");
});
<p id="changed">Hello!</p>
<a id="change">change</a>
Я заметил, что первый ответ был не совсем то, что мне нужно, поэтому я сделал пару модификаций и решил, что отправлю его здесь.
replaceTag(<tagName>)
replaceTag(<tagName>, [withDataAndEvents], [withDataAndEvents])
Аргументы:
- tagName: String
- Имя тега, например. "div", "span" и т.д.
- withDataAndEvents: Boolean
- "Логическое значение, указывающее, следует ли копировать обработчики событий вместе с элементами. В jQuery 1.4 данные элементов также будут скопированы." информация
- deepWithDataAndEvents: Boolean,
- Логическое значение, указывающее, следует ли копировать обработчики событий и данные для всех детей клонированного элемента. По умолчанию его значение соответствует первому аргументу (значение по умолчанию равно false). info
Возвращает:
Недавно созданный элемент jQuery
Хорошо, я знаю, что здесь есть несколько ответов, но я взял на себя это, чтобы написать это снова.
Здесь мы можем заменить тег так же, как мы используем клонирование.
Мы выполняем тот же синтаксис, что и .clone() с withDataAndEvents
и deepWithDataAndEvents
, которые копируют данные и события дочерних узлов, если они используются.
$tableRow.find("td").each(function() {
$(this).clone().replaceTag("li").appendTo("ul#table-row-as-list");
});
$.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);
})
}
})
Обратите внимание, что этот не заменяет выделенный элемент, он возвращает вновь созданный.
Я придумал подход, в котором вы используете строковое представление вашего объекта jQuery и заменяете имя тега, используя регулярные выражения и базовый JavaScript. Вы не потеряете контент и не будете перебирать каждый атрибут/свойство.
/*
* 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);
}
Наконец, вы можете заменить существующий объект / node следующим образом:
var $newElement = replaceTag($rankingSubmit, 'a');
$('#not-an-a-element').replaceWith($newElement);
Это мое решение. Он позволяет переключаться между тегами.
<!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>
Идея состоит в том, чтобы обернуть элемент и развернуть содержимое:
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;
}
Пример использования:
renameElement($('p'),'h5');
Есть ли какая-то конкретная причина, по которой вам нужно изменить тег? Если вы просто хотите сделать текст более крупным, изменение класса CSS p-тегов было бы лучшим способом для этого.
Что-то вроде этого:
$('#change').click(function(){
$('p').addClass('emphasis');
});