jqueryを使用して要素タイプを変更する方法


回答:


137

jQueryでこれを行う方法の1つを次に示します。

var attrs = { };

$.each($("b")[0].attributes, function(idx, attr) {
    attrs[attr.nodeName] = attr.nodeValue;
});


$("b").replaceWith(function () {
    return $("<h1 />", attrs).append($(this).contents());
});

例: http : //jsfiddle.net/yapHk/

アップデート、ここにプラグインがあります:

(function($) {
    $.fn.changeElementType = function(newType) {
        var attrs = {};

        $.each(this[0].attributes, function(idx, attr) {
            attrs[attr.nodeName] = attr.nodeValue;
        });

        this.replaceWith(function() {
            return $("<" + newType + "/>", attrs).append($(this).contents());
        });
    };
})(jQuery);

例: http : //jsfiddle.net/mmNNJ/


2
@FelixKling:ありがとう、childrenうまくいきませんcontentsでした。
Andrew Whitaker

1
@Andrew Whitaker WOW !!! あなたは上手い!したがって、私がb.classまたはb.xyzxterms(xyzxtermsはクラスの名前)を使用していることを確認するために
bammab

5
@AndrewWhitaker:私が間違っていない場合は、プラグインで、最初に一致した要素の属性がすべての一致する要素に適用されます。それは必ずしも私たちが望むものではありません。また、セット内に一致する要素がない場合もエラーが発生します。これは、一致した要素ごとに独自の属性を保持し、空のセットでエラーをトリガーしないプラグインの変更バージョンです。gist.github.com
Etienne

2
これは魅力のように機能します!セレクタが一致する要素を見つけられなかった場合を除いて、this [0]は未定義のアクセス属性ブレークであるため、コンソールにエラーメッセージがスローされます。条件を追加すると修正されます:if(this.length!= 0){...
ciuncan

1
@ciuncan:フィードバックをありがとう!.each以下の答えが示すように、それは本当にブロックに包まれるべきです。
Andrew Whitaker 2013

14

jQueryについては不明です。単純なJavaScriptを使用すると、次のことができます。

var new_element = document.createElement('h1'),
    old_attributes = element.attributes,
    new_attributes = new_element.attributes;

// copy attributes
for(var i = 0, len = old_attributes.length; i < len; i++) {
    new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
}

// copy child nodes
do {
    new_element.appendChild(element.firstChild);
} 
while(element.firstChild);

// replace element
element.parentNode.replaceChild(new_element, element);

デモ

ブラウザー間の互換性についてはわかりません。

バリエーションは次のとおりです。

for(var i = 0, len = old_attributes.length; i < len; i++) {
    new_element.setAttribute(old_attributes[i].name, old_attributes[i].value);
}

詳細については、Node.attributes [MDN]を参照してください。


コードのパフォーマンスは「純粋なjQuery」(例:Andrewのコード)よりも優れていますが、内部タグに少し問題があります。コードreference-exampleを使用してこの例の斜体を参照してください
Peter Krauss

修正すると、「理想的なjqueryプラグイン」を定義して、jquery-plugin-templateで関数を呼び出すことができます。
Peter Krauss

修繕。問題は、最初の子をコピーした後、次の兄弟がないためにwhile(child = child.nextSibling)失敗したことです。ありがとう!
Felix Kling 14年

9

@jakovおよび@Andrew Whitaker

複数の要素を一度に処理できるように、さらに改善を加えました。

$.fn.changeElementType = function(newType) {
    var newElements = [];

    $(this).each(function() {
        var attrs = {};

        $.each(this.attributes, function(idx, attr) {
            attrs[attr.nodeName] = attr.nodeValue;
        });

        var newElement = $("<" + newType + "/>", attrs).append($(this).contents());

        $(this).replaceWith(newElement);

        newElements.push(newElement);
    });

    return $(newElements);
};

3

@Jazzboの回答では、jQueryオブジェクトの配列を含むjQueryオブジェクトが返されましたが、これはチェーン化できませんでした。$ .eachが返すものに似たオブジェクトを返すように変更しました。

    $.fn.changeElementType = function (newType) {
        var newElements,
            attrs,
            newElement;

        this.each(function () {
            attrs = {};

            $.each(this.attributes, function () {
                attrs[this.nodeName] = this.nodeValue;
            });

            newElement = $("<" + newType + "/>", attrs).append($(this).contents());

            $(this).replaceWith(newElement);

            if (!newElements) {
                newElements = newElement;
            } else {
                $.merge(newElements, newElement);
            }
        });

        return $(newElements);
    };

(jslintを渡すようにコードのクリーンアップも行いました。)


これは最も良いオプションのようです。私が得られない唯一のことは、attrのvar宣言をthis.each()から移動した理由です。そのままにしておくと正常に機能します:jsfiddle.net/9c0k82sr/1
Jacob C.が

jslintのために変数をグループ化しました。「(jslintを渡すために、コードのクリーンアップも行いました。)」その背後にある考え方は、コードを高速化することです(各eachループ内で変数を再宣言する必要がないと思います)。
fiskhandlarn 2017年

2

私が考えることができる唯一の方法は、手動ですべてをコピーすることです:例jsfiddle

HTML

<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>

jquery / JavaScript

$(document).ready(function() {
    var me = $("b");
    var newMe = $("<h1>");
    for(var i=0; i<me[0].attributes.length; i++) {
        var myAttr = me[0].attributes[i].nodeName;
        var myAttrVal = me[0].attributes[i].nodeValue;
        newMe.attr(myAttr, myAttrVal);
    }
    newMe.html(me.html());
    me.replaceWith(newMe);
});

2

@Andrew Whitaker:この変更を提案します。

$.fn.changeElementType = function(newType) {
    var attrs = {};

    $.each(this[0].attributes, function(idx, attr) {
        attrs[attr.nodeName] = attr.nodeValue;
    });

    var newelement = $("<" + newType + "/>", attrs).append($(this).contents());
    this.replaceWith(newelement);
    return newelement;
};

その後、次のようなことができます: $('<div>blah</div>').changeElementType('pre').addClass('myclass');


2

@AndrewWhitakerなどのアイデアが好きで、jQueryプラグインを使用して、changeElementType()メソッドを追加しています。しかし、プラグインはブラックボックスのようなものであり、コードが小さくても問題なく機能する場合は問題ありません。したがって、パフォーマンスが必要であり、コードよりも重要です。

「純粋なJavaScript」はjQuery よりもパフォーマンス優れています。@ FelixKlingのコードは@AndrewWhitakerなどのコードよりもパフォーマンスが優れていると思います。


ここでは、jQueryプラグインにカプセル化された「純粋なJavavascript」(および「純粋なDOM」)コードを示します

 (function($) {  // @FelixKling's code
    $.fn.changeElementType = function(newType) {
      for (var k=0;k<this.length; k++) {
       var e = this[k];
       var new_element = document.createElement(newType),
        old_attributes = e.attributes,
        new_attributes = new_element.attributes,
        child = e.firstChild;
       for(var i = 0, len = old_attributes.length; i < len; i++) {
        new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
       }
       do {
        new_element.appendChild(e.firstChild);
       }
       while(e.firstChild);
       e.parentNode.replaceChild(new_element, e);
      }
      return this; // for chain... $(this)?  not working with multiple 
    }
 })(jQuery);

2

ここに私がjqueryのhtmlタグを置き換えるために使用する方法があります:

// Iterate over each element and replace the tag while maintaining attributes
$('b.xyzxterms').each(function() {

  // Create a new element and assign it attributes from the current element
  var NewElement = $("<h1 />");
  $.each(this.attributes, function(i, attrib){
    $(NewElement).attr(attrib.name, attrib.value);
  });

  // Replace the current element with the new one and carry over the contents
  $(this).replaceWith(function () {
    return $(NewElement).append($(this).contents());
  });

});

2

jQuery せずに属性を反復処理:

replaceElem以下の方法は受け入れold Tagnew Tagそしてcontext、正常に交換を実行します。


replaceElem('h2', 'h1', '#test');

function replaceElem(oldElem, newElem, ctx) {
  oldElems = $(oldElem, ctx);
  //
  $.each(oldElems, function(idx, el) {
    var outerHTML, newOuterHTML, regexOpeningTag, regexClosingTag, tagName;
    // create RegExp dynamically for opening and closing tags
    tagName = $(el).get(0).tagName;
    regexOpeningTag = new RegExp('^<' + tagName, 'i'); 
    regexClosingTag = new RegExp(tagName + '>$', 'i');
    // fetch the outer elem with vanilla JS,
    outerHTML = el.outerHTML;
    // start replacing opening tag
    newOuterHTML = outerHTML.replace(regexOpeningTag, '<' + newElem);
    // continue replacing closing tag
    newOuterHTML = newOuterHTML.replace(regexClosingTag, newElem + '>');
    // replace the old elem with the new elem-string
    $(el).replaceWith(newOuterHTML);
  });

}
h1 {
  color: white;
  background-color: blue;
  position: relative;
}

h1:before {
  content: 'this is h1';
  position: absolute;
  top: 0;
  left: 50%;
  font-size: 5px;
  background-color: black;
  color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div id="test">
  <h2>Foo</h2>
  <h2>Bar</h2>
</div>

幸運を...


1
私はあなたの答えが好きです!どうして?他のすべての答えは、アンカーをラベルに変換するような単純なことをしようとすると失敗するからです。とはいえ、回答に対する次の修正/改訂を検討してください:A)。コードはセレクターでは機能しません。B)コードは大文字と小文字を区別しない正規表現を実行する必要があります。そうは言っても、ここに私の提案する修正があります:regexOpeningTag = new RegExp( '^ <' + $(el).get(0).tagName、 'i'); regexClosingTag = new RegExp($(el).get(0).tagName + '> $'、 'i');
zax

このようなプレーンHTMLを置き換えると、オブジェクトに関連付けられているイベントリスナーも失われます。
ホセ・ヤネス

1

JavaScriptソリューション

古い要素の属性を新しい要素にコピーします

const $oldElem = document.querySelector('.old')
const $newElem = document.createElement('div')

Array.from($oldElem.attributes).map(a => {
  $newElem.setAttribute(a.name, a.value)
})

古い要素を新しい要素に置き換えます

$oldElem.parentNode.replaceChild($newElem, $oldElem)

map未使用の新しい配列を作成しforEachます。これはで置き換えることができます。
Orkhan Alikhanov

1

これが私のバージョンです。基本的には@fiskhandlarnのバージョンですが、新しいjQueryオブジェクトを作成する代わりに、古い要素を新しく作成された要素で上書きするだけなので、マージする必要はありません。
デモ:http : //jsfiddle.net/0qa7wL1b/

$.fn.changeElementType = function( newType ){
  var $this = this;

  this.each( function( index ){

    var atts = {};
    $.each( this.attributes, function(){
      atts[ this.name ] = this.value;
    });

    var $old = $(this);
    var $new = $('<'+ newType +'/>', atts ).append( $old.contents() );
    $old.replaceWith( $new );

    $this[ index ] = $new[0];
  });

  return this;
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.