jQuery/JavaScript替换标签类型

21

有没有一种简单的方法来遍历所有 td 标签并将它们更改为 th?(等等)。

我的当前方法是将其包装在 th 中,然后删除 td,但这样我会失去其他属性等。


您想要保留当前在<td>上的属性吗? - Nick Craver
是的,我想要保留它们的所有内容。 - Matrym
1
这个操作不能在服务器上完成吗?在客户端中,至少不能轻松地处理所有可能的情况,因为一旦将元素的标签类型添加到DOM中,它就是不可变的。 - Nick Craver
你可能需要考虑使用另一种默认的DOM结构来实现你想要达到的效果。你的操作是可以完成的,但正如Nick所说,这并不是一项简单的任务,特别是如果你的td标签数量可能是可变的。 - ground5hark
7个回答

25

jQuery.replaceTagName

这是一个jQuery插件,用于替换DOM元素的标签名称。

源代码

(function($) {
    $.fn.replaceTagName = function(replaceWith) {
        var tags = [],
            i    = this.length;
        while (i--) {
            var newElement = document.createElement(replaceWith),
                thisi      = this[i],
                thisia     = thisi.attributes;
            for (var a = thisia.length - 1; a >= 0; a--) {
                var attrib = thisia[a];
                newElement.setAttribute(attrib.name, attrib.value);
            };
            newElement.innerHTML = thisi.innerHTML;
            $(thisi).after(newElement).remove();
            tags[i] = newElement;
        }
        return $(tags);
    };
})(window.jQuery);

压缩源代码

(function(e){e.fn.replaceTagName=function(t){var n=[],r=this.length;while(r--){var i=document.createElement(t),s=this[r],o=s.attributes;for(var u=o.length-1;u>=0;u--){var a=o[u];i.setAttribute(a.name,a.value)}i.innerHTML=s.innerHTML;e(s).after(i).remove();n[r]=i}return e(n)}})(window.jQuery);

使用方法

在引入jQuery之后,将上述压缩源代码包含在您的javascript中。

然后,您可以像这样使用插件:

$('div').replaceTagName('span'); // replace all divs with spans

或者在您的情况下,这样做:
$('td').replaceTagName('th');

jQuery选择器的工作方式符合预期

$('.replace_us').replaceTagName('span'); // replace all elements with "replace_us" class with spans
$('#replace_me').replaceTagName('div'); // replace the element with the id "replace_me"

更多资源

带有Qunit测试的jsFiddle


16

完全未经测试,但是让我们试一下:

$("td").each(function(index) {
  var thisTD = this;
  var newElement = $("<th></th>");
  $.each(this.attributes, function(index) {
    $(newElement).attr(thisTD.attributes[index].name, thisTD.attributes[index].value);
  });
  $(this).after(newElement).remove();
});
我一直在仔细研究它,但我想不出为什么它不能工作!
1)遍历每个td元素
2)创建一个新的th元素
3)针对这些td中的每一个,循环遍历其属性
4)将该属性和值添加到新的th元素中
5)一旦所有属性就位,将该元素添加到DOM中,在td右侧,并移除td。 编辑:运行良好:http://jsbin.com/uqofu3/edit

3
非常好用!如果你想要复制元素的内部HTML,可以在最后一行之前添加 $(newElement).html($(this).html());。 - idFlood

5
$("td").each(function() {
  var tmp = $('<div/>').append($(this).clone(true)).html().replace(/td/i,'th');
  $(this).after(tmp).remove();
});

或者纯DOM
function replaceElm(oldTagName, newTagName, targetElm) {
  var target = targetElm || window.document;
  var allFound = target.getElementsByTagName(oldTagName);
  for (var i=0; i<allFound.length; i++) {
    var tmp = document.createElement(newTagName);
    for (var k=0; k<allFound[i].attributes.length; k++) {
      var name = allFound[i].attributes[k].name;
      var val = allFound[i].attributes[k].value;
      tmp.setAttribute(name,val);
    }
    tmp.innerHTML = allFound[i].innerHTML;
    allFound[i].parentNode.insertBefore(tmp, allFound[i]);
    allFound[i].parentNode.removeChild(allFound[i]);
  }
}

replaceElm('td','th',document.getElementsByTagName('table')[0]);

DOM总是更快的:http://jsperf.com/replace-tag-names


在您的jQuery解决方案中,正则表达式将应用于整个HTML内容,这可能会产生意外结果。 - Philippe Rathé

3
这可能有效,但我还没有进行全面测试:
var tds = document.getElementsByTagName("td");
while(tds[0]){
    var t = document.createElement("th");
    var a = tds[0].attributes;
    for(var i=0;i<a.length;i++) t.setAttribute(a[i].nodeName,a[i].nodeValue);
    t.innerHTML = tds[0].innerHTML;
    tds[0].parentNode.insertBefore(t,tds[0]);
    tds[0].parentNode.removeChild(tds[0]);
}

希望这些内容能在某种程度上对您有所帮助。


0

这比@GlenCrawford的答案更加简洁,而且还会复制替换元素的子元素。

$('td').each(function(){
    var newElem = $('<th></th>', {html: $(this).html()});
    $.each(this.attributes, function() {
        newElem.attr(this.name, this.value);
    });
    $(this).replaceWith(newElem);
});

在问题已经被提出并被接受4年之后,发表另一个答案是没有用的。 - Wouter J
虽然这段源代码可能提供了一个答案,但是简要的解释会对当前和未来的读者有所裨益。 - Thom
添加了一些解释。 - jstice4all

0
稍微补充一下@GlenCrawford的答案,以保留带有行内文本的行:
newElement.text($(value).text());

现在一起来:

$("td").each(function(index) {
  var thisTD = this;
  var newElement = $("<th></th>");
  newElement.text($(value).text());
  $.each(this.attributes, function(index) {
    $(newElement).attr(thisTD.attributes[index].name, thisTD.attributes[index].value);
  });
  $(this).after(newElement).remove();
});

0

这个问题有点久了,但仍然可以提供帮助:唯一一个真正按预期工作的jQuery插件是(你不能在另一个对象中重用返回的对象,例如添加属性):

jQuery.fn.extend({
    replaceTagName: function(replaceWith) {
        var tags=[];
        this.each(function(i,oldTag) {
            var $oldTag=$(oldTag);
            var $newTag=$($("<div />").append($oldTag.clone(true)).html().replace(new RegExp("^<"+$oldTag.prop("tagName"),"i"),"<"+replaceWith));
            $oldTag.after($newTag).remove();
            tags.push($newTag.get(0));
        });

        return $(tags);
    }
});

除了基本的$("td").replaceTagName("th");之外,您还可以像$("td").replaceTagName("th").attr("title","test");这样链接调用。
缩小版本:
jQuery.fn.extend({replaceTagName:function(a){var b=[];this.each(function(d,c){var e=$(c);var f=$($("<div />").append(e.clone(true)).html().replace(new RegExp("^<"+e.prop("tagName"),"i"),"<"+a));e.after(f).remove();b.push(f.get(0))});return $(b)}});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接