Подтвердить что ты не робот

JQuery: как изменить имя тега?

jQuery: как изменить имя тега?

Например:

<tr>
    $1
</tr>

Мне нужно

<div>
    $1
</div>

Да, я могу

  • Создать элемент DOM <div>
  • Скопировать tr-контент в div
  • Удалить tr из dom

Но могу ли я сделать это напрямую?

PS:

    $(tr).get(0).tagName = "div"; 

приводит к DOMException.

4b9b3361

Ответ 1

Вы можете заменить любую HTML-разметку, используя метод jQuery .replaceWith().

пример: http://jsfiddle.net/JHmaV/

Ref.:.replaceWith

Если вы хотите сохранить существующую разметку, вы можете использовать такой код:

$('#target').replaceWith('<newTag>' + $('#target').html() +'</newTag>')

Ответ 3

Где метод DOM renameNode()?

Сегодня (2014) ни один браузер не понимает новый метод DOM3 renameNode (см. также W3C) проверьте, не запускается ли у вас доза:http://jsfiddle.net/k2jSm/1/

Итак, решение DOM безобразно, и я не понимаю, почему (??) jQuery не реализовал обходной путь?

алгоритм чистого DOM

  1. createElement(new_name)
  2. скопировать весь контент в новый элемент;
  3. заменить старое на новое 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/

Смотрите также fooobar.com/questions/111486/...

Ответ 4

Приведенные выше решения стирают существующий элемент и воссоздают его с нуля, уничтожая любые привязки событий к дочерним процессам.

краткий ответ: (теряет атрибуты)

$("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();
});

возиться с вложенными привязками

Было бы неплохо скопировать любые привязки одновременно, но получение текущих привязок мне не помогло.

Ответ 5

Чтобы сохранить внутренний контент тега, вы можете использовать accessor .html() в сочетании с .replaceWith()

forked example: http://jsfiddle.net/WVb2Q/1/

Ответ 6

Вы можете пойти немного базовым. Работает для меня.

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;

Ответ 7

Вдохновленный ответом 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')

Ответ 8

Чтобы заменить внутреннее содержимое нескольких тегов, каждое из которых имеет свой собственный исходный контент, вы должны использовать .replaceWith() и .html() иначе:

http://jsfiddle.net/kcrca/VYxxG/

Ответ 9

JS, чтобы изменить имя тега

/**
 * This function replaces the DOM elements 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;
}

Связанный скрипт находится в этой ссылке

Ответ 10

Простое изменение значений свойств не будет делать это (как говорили другие, некоторые свойства HTMLElement доступны только для чтения, а некоторые содержат прототипный контекст для более примитивных элементов). Самое близкое, что вы можете подражать DOM API, - это подражать процессу прототипного наследования в 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.

Ответ 11

Так как 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);

Ответ 12

Возьмите его под словом

Возник вопрос по слову "как изменить имя тега?" Я бы предложил это решение:
Если это имеет смысл или нет, это необходимо решить в каждом конкретном случае.

Мой пример будет "переименовывать" все 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. Существуют и другие способы, с помощью которых люди пытаются скопировать все атрибуты в новый элемент, но они не совместимы со всеми браузерами.

Хотя я считаю, что это так дорого.

Ответ 13

Плагин 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);

Смотрите: http://jsfiddle.net/03gcnx9v/3/

Ответ 14

Еще один script, чтобы изменить имя node

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 в новый элемент, а затем заменит старый.

Ответ 15

$(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>

Ответ 16

Вы можете использовать эту функцию

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');

Ответ 17

Работает чистый алгоритм DOM

function rename_element(node, name) {
    let renamed = document.createElement(name);

    Array.from(node.attributes).forEach(attr => {
        renamed.setAttribute(attr.name, attr.value);        
    })
    while (node.firstChild) {
        renamed.appendChild(node.firstChild);
    }
    node.parentNode.replaceChild(renamed, node);
    return renamed;
}