библиотека jQuery: как изменить имя тега?
библиотека jQuery: как изменить имя тега?
например:
<tr>
</tr>
мне нужно
<div>
</div>
Да, я могу
- создать элемент DOM
- копировать содержимое tr в div
- удалить tr из dom
но могу ли я сделать это напрямую?
PS:
$(tr).get(0).tagName = "div";
результаты
DOMException
.
16 ответов
вы можете заменить любую разметку HTML с помощью jQuery .replaceWith()
метод.
пример:http://jsfiddle.net/JHmaV/
Ref.: .replaceWith
Если вы хотите сохранить существующую разметку, вы можете использовать такой код:
$('#target').replaceWith('<newTag>' + $('target').html() +'</newTag>')
нет, это невозможно в соответствии со спецификацией W3C: "tagName типа DOMString, только для чтения"
где метод DOM renameNode ()?
сегодня (2014) ни один браузер не понимает новый метод renameNode DOM3 (см. также консорциума W3C) проверьте, работает ли ваш Боузер:http://jsfiddle.net/k2jSm/1/
Итак, решение DOM уродливо, и я не понимаю почему (??) jQuery не реализовал обходной путь?
чистый алгоритм DOM
-
createElement(new_name)
- скопировать все содержимое новый элемент;
- заменить старое на новое на
replaceChild()
- это что-то вроде этого,
function rename_element(node,name) {
var renamed = document.createElement(name);
foreach (node.attributes as a) {
renamed.setAttribute(a.nodeName, a.nodeValue);
}
while (node.firstChild) {
renamed.appendChild(node.firstChild);
}
return node.parentNode.replaceChild(renamed, node);
}
... ждите обзора и jsfiddle ...
алгоритм jQuery
алгоритм @ilpoldo является хорошей отправной точкой,
$from.replaceWith($('<'+newname+'/>').html($from.html()));
как прокомментировали другие, ему нужна копия атрибута ... ждать родовой ...
характерные для class
, сохранение атрибута см. http://jsfiddle.net/cDgpS/
вышеуказанные решения уничтожают существующий элемент и воссоздают его с нуля, уничтожая любые привязки событий для детей в процессе.
короткий ответ: (теряет атрибуты)
$("p").wrapInner("<div/>").children(0).unwrap();
более длинный ответ: (атрибуты копий)
$("p").each(function (o, elt) {
var newElt = $("<div class='p'/>");
Array.prototype.slice.call(elt.attributes).forEach(function(a) {
newElt.attr(a.name, a.value);
});
$(elt).wrapInner(newElt).children(0).unwrap();
});
возиться с вложенными привязками
было бы здорово скопировать любые привязки из одновременно, но получение текущего привязки у меня не получилось.
для сохранения внутреннего содержимого тега можно использовать аксессоры .html()
в сочетании с .replaceWith()
раздвоенный пример:http://jsfiddle.net/WVb2Q/1/
вы могли бы пойти немного basic. Работать на меня.
var oNode = document.getElementsByTagName('tr')[0];
var inHTML = oNode.innerHTML;
oNode.innerHTML = '';
var outHTML = oNode.outerHTML;
outHTML = outHTML.replace(/tr/g, 'div');
oNode.outerHTML = outHTML;
oNode.innerHTML = inHTML;
для замены внутреннего содержимого несколько теги, каждый со своим оригинальным контентом, вы должны использовать .replaceWith()
и .html()
иначе:
JS, чтобы изменить имя тега
/**
* This function replaces the DOM elements's tag name with you desire
* Example:
* replaceElem('header','ram');
* replaceElem('div.header-one','ram');
*/
function replaceElem(targetId, replaceWith){
$(targetId).each(function(){
var attributes = concatHashToString(this.attributes);
var replacingStartTag = '<' + replaceWith + attributes +'>';
var replacingEndTag = '</' + replaceWith + '>';
$(this).replaceWith(replacingStartTag + $(this).html() + replacingEndTag);
});
}
replaceElem('div','span');
/**
* This function concats the attributes of old elements
*/
function concatHashToString(hash){
var emptyStr = '';
$.each(hash, function(index){
emptyStr += ' ' + hash[index].name + '="' + hash[index].value + '"';
});
return emptyStr;
}
связанная скрипка находится в этом ссылке
просто изменение значений свойств не сделает этого (как говорили другие, некоторые HTMLElement
свойства доступны только для чтения; также некоторые содержат прототипный контекст для более примитивных элементов). Самое близкое, что вы можете получить, чтобы имитировать API DOM, - это имитировать также процесс прототипного наследования в JavaScript.
"настройка" на прототипе объекта через __proto__
обычно хмурится. Кроме того, вы можете подумать, почему вам нужно дублировать весь элемент DOM в первом место. Но вот:
// Define this at whatever scope you'll need to access it
// Most of these kinds of constructors are attached to the `window` object
window.HTMLBookElement = function() {
function HTMLBookElement() {
var book = document.createElement('book');
book.__proto__ = document.createElement('audio');
return book;
}
return new HTMLBookElement();
}
// Test your new element in a console (I'm assuming you have Chrome)
var harryPotter = new HTMLBookElement();
// You should have access to your new `HTMLBookElement` API as well as that
// of its prototype chain; since I prototyped `HTMLAudioElement`, you have
// some default properties like `volume` and `preload`:
console.log(harryPotter); // should log "<book></book>"
console.log(harryPotter.volume); // should log "1"
console.log(harryPotter.preload); // should log "auto"
все элементы DOM работают таким образом. Например:
<div></div>
произведен HTMLDivElement
,
который простирается HTMLElement
,
что, в свою очередь, расширяет Element
,
что, в свою очередь, расширяет Object
.
С replaceWith()
не работал для меня на элементной основе (возможно, потому, что я использовал его внутри map()
), Я сделал это, создав новый элемент и скопировав атрибуты по мере необходимости.
$items = $('select option').map(function(){
var
$source = $(this),
$copy = $('<li></li>'),
title = $source.text().replace( /this/, 'that' );
$copy
.data( 'additional_info' , $source.val() )
.text(title);
return $copy;
});
$('ul').append($items);
возьмите его за слово
принятые на вопрос "как изменить имя тега?"Я бы предложил такое решение:
Если это имеет смысл или нет, это должно решаться в каждом конкретном случае.
мой пример будет "переименовывать" все A-теги с гиперссылками для SMS с тегами span. Сохранение всех атрибутов и содержимого:
$('a[href^="sms:"]').each(function(){
var $t=$(this);
var $new=$($t.wrap('<div>')
.parent()
.html()
.replace(/^\s*<\s*a/g,'<span')
.replace(/a\s*>\s*$/g,'span>')
).attr('href', null);
$t.unwrap().replaceWith($new);
});
поскольку нет никакого смысла иметь тег span с атрибутом href, я удаляю это тоже. Это пуленепробиваемое и совместимые со всеми браузерами, которые поддерживаются jquery. Есть и другие способы, которыми люди пытаются скопировать все атрибуты в новый элемент, но они не совместимы со всеми браузерами.
хотя я думаю, что это довольно дорого, чтобы сделать это таким образом.
плагин Jquery, чтобы сделать" tagName " редактируемым:
(function($){
var $newTag = null;
$.fn.tagName = function(newTag){
this.each(function(i, el){
var $el = $(el);
$newTag = $("<" + newTag + ">");
// attributes
$.each(el.attributes, function(i, attribute){
$newTag.attr(attribute.nodeName, attribute.nodeValue);
});
// content
$newTag.html($el.html());
$el.replaceWith($newTag);
});
return $newTag;
};
})(jQuery);
еще один скрипт для изменения имени узла
function switchElement() {
$element.each(function (index, oldElement) {
let $newElement = $('<' + nodeName + '/>');
_.each($element[0].attributes, function(attribute) {
$newElement.attr(attribute.name, attribute.value);
});
$element.wrapInner($newElement).children().first().unwrap();
});
}
http://jsfiddle.net/rc296owo/5/
он скопирует атрибуты и внутренний html в новый элемент, а затем заменит старый.
$(function(){
$('#switch').bind('click', function(){
$('p').each(function(){
$(this).replaceWith($('<div/>').html($(this).html()));
});
});
});
p {
background-color: red;
}
div {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Hello</p>
<p>Hello2</p>
<p>Hello3</p>
<button id="switch">replace</button>
вы можете использовать эту функцию
var renameTag = function renameTag($obj, new_tag) {
var obj = $obj.get(0);
var tag = obj.tagName.toLowerCase();
var tag_start = new RegExp('^<' + tag);
var tag_end = new RegExp('<\/' + tag + '>$');
var new_html = obj.outerHTML.replace(tag_start, "<" + new_tag).replace(tag_end, '</' + new_tag + '>');
$obj.replaceWith(new_html);
};
ES6
const renameTag = function ($obj, new_tag) {
let obj = $obj.get(0);
let tag = obj.tagName.toLowerCase();
let tag_start = new RegExp('^<' + tag);
let tag_end = new RegExp('<\/' + tag + '>$');
let new_html = obj.outerHTML.replace(tag_start, "<" + new_tag).replace(tag_end, '</' + new_tag + '>');
$obj.replaceWith(new_html);
};
пример кода
renameTag($(tr),'div');
вдохновленный ericP ответ, отформатированный и преобразованный в плагин jQuery:
$.fn.replaceWithTag = function(tagName) {
var result = [];
this.each(function() {
var newElem = $('<' + tagName + '>').get(0);
for (var i = 0; i < this.attributes.length; i++) {
newElem.setAttribute(
this.attributes[i].name, this.attributes[i].value
);
}
newElem = $(this).wrapInner(newElem).children(0).unwrap().get(0);
result.push(newElem);
});
return $(result);
};
использование:
$('div').replaceWithTag('span')