jquery를 사용하여 요소 유형을 변경하는 방법


답변:


137

다음은 jQuery로 할 수있는 한 가지 방법입니다.

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 2011

1
@Andrew Whitaker 와우 !!! 당신은 훌륭합니다! 따라서 b.class 또는 b.xyzxterms (xyzxterms가 클래스 이름 임)를 사용하는지 확인하기 위해
bammab

5
@AndrewWhitaker : 내가 틀리지 않았다면 플러그인에서 첫 번째 일치 요소의 속성이 일치하는 모든 요소에 적용됩니다. 반드시 우리가 원하는 것은 아닙니다. 또한 세트에 일치하는 요소가 없으면 오류가 발생합니다. 다음은 일치하는 각 요소에 대해 고유 한 속성을 유지하고 빈 세트에서 오류를 트리거하지 않는 수정 된 버전의 플러그인입니다. gist.github.com/2934516
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 2014 년

수정 하면 jquery-plugin-template로 함수를 호출하여 "이상적인 jquery 플러그인" 을 정의 할 수 있습니다.
Peter Krauss 2014 년

결정된. 문제는 첫 번째 아이를 복사 한 후 더 이상 다음 형제가 없어서 while(child = child.nextSibling)실패 했다는 것 입니다. 감사!
Felix Kling 2014 년

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를 전달합니다.)


이것은 가장 좋은 옵션 인 것 같습니다. 내가 이해하지 못하는 유일한 것은 this.each ()에서 attrs에 대한 var 선언을 옮긴 이유입니다. : 그것은 괜찮이 왼쪽 작동 jsfiddle.net/9c0k82sr/1
야곱 C.는 분석 재개 모니카 말한다

나는 jslint 때문에 vars를 그룹화했다 : "(또한 jslint를 통과하도록 코드를 정리했다.)". 그 뒤에있는 아이디어는 코드를 더 빠르게 만드는 것입니다 (각 each루프 내에서 vars를 다시 선언 할 필요가 없음 ).
fiskhandlarn

2

내가 생각할 수있는 유일한 방법은 모든 것을 수동으로 복사하는 것입니다. 예 jsfiddle

HTML

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

Jquery / 자바 스크립트

$(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()메소드 를 추가한다는 아이디어를 좋아합니다 . 하지만 플러그인은 블랙 박스와 같으며 코드에 상관없이 작지만 잘 작동한다면 성능이 필요하고 코드보다 가장 중요합니다.

"Pure 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 Tag, new 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');
슬레이트 자르는 연장

이와 같이 일반 HTML을 바꾸면 객체에 연결된 이벤트 리스너도 손실됩니다.
호세 야 네즈

1

자바 스크립트 솔루션

이전 요소의 속성을 새 요소에 복사

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.