jQuery每个都与replaceWith问题相结合

时间:2017-03-28 09:24:11

标签: javascript jquery dom each replacewith

我试图用一个类循环遍历每个元素,然后用div包装它,然后继续下一个。

目前使用此...

$('.img-editable').each(function(i) {
    if ($(this).prop("tagName") == "IMG") {
        $(this).replaceWith('<span class="img-edit-container">'+this.outerHTML+'<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
    } else {
        $(this).replaceWith('<span class="img-edit-container bg-img-edit-container">'+this.outerHTML+'<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
    }
});

它适用于简单的情况。但挑战是当存在像这样的嵌套元素时......

    <div class="img-editable>
        <div id="something else">
            <div class="img-editable"></div>
        </div>
    </div>

然后它崩溃了,内部元素没有被正确包裹。

我认为each()函数循环最外层元素,当它与第一个元素匹配时,它会执行replaceWith()然后继续。但是当循环到达下一个(内部)时,对匹配的第二个内部元素的引用不再存在(根据浏览器)。

我也试过了......

var setupImgWrapper = function(elem) {
    if (elem.prop("tagName") == "IMG") {
        elem.replaceWith('<span class="img-edit-container">'+this.outerHTML+'<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
        elem.children('.img-edtiable').each(function(i) {
            setupImgWrapper($(this));
        });
    } else {
        elem.replaceWith('<span class="img-edit-container bg-img-edit-container">'+this.outerHTML+'<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
        elem.children('.img-edtiable').each(function(i) {
            setupImgWrapper($(this));
        });
    }
}

$('.img-editable').each(function(i) {
    setupImgWrapper($(this));
});

这完全失败了。

我很想知道如何克服这个问题?有没有办法在replaceWith()执行后维护DOM引用,还是可以更新它?

TL; DR 在选定元素的循环中执行replaceWith后,后代元素引用似乎中断,并且这些元素未成功更新。

谢谢!

以下接受的解决方案

$('.img-editable').each(function(i) {
    if ($(this).prop("tagName") == "IMG") {
        $(this).wrap('<span class="img-edit-container"></span>');
        $(this).after('<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>');
    } else {
        $(this).wrap('<span class="img-edit-container bg-img-edit-container"></span>');
        $(this).after('<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>');
    }
});

2 个答案:

答案 0 :(得分:1)

jQuery提供了一种.wrap()方法,可以完全满足您的需求。

这是一个演示

$('body > div').each(function() {
  $(this).wrap('<div class="wrapper" />');
});
.wrapper {
  border: 1px solid tomato;
  margin-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>Normal Element</div>

<div>
  <span>Simple inline element</span>
</div>

<div>
  <div>
    <h1>More Stuff</h1>
  </div>
</div>

如果.img-editable > ... > .img-editable破坏了您的代码,您应该选择更适合您需求的更好的选择器。我可以帮助你,只需对这个答案发表评论,我们就会想出办法。 :)

答案 1 :(得分:1)

尝试wrapall api和each

$( ".img-editable" ).wrapAll( "<span class='img-edit-container'/>");

$(".img-edit-container .img-editable").each( function(){
  if ( $( this ).prop("tagName") == "IMG" )
  {
    $(this).parent().append ( '<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
  }
  else
  {
    $(this).parent().append ( '<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
  }
});

甚至更简单

$( ".img-editable" ).wrapAll( "<span class='img-edit-container'/>");

$(".img-edit-container").append( '<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );

$(".img-edit-container img.img-editable").siblings( "button" ).toggleClass( "btn-sm" ).toggleClass( "bg-img-edit" );