如果元素包含在另一个元素中,如何移动元素

时间:2015-02-22 18:53:00

标签: jquery

我有以下模型(这里是一个jsbin:http://jsbin.com/vadutezaci/1/edit?html,css,output):

<div class='jt-header'>a header 1</div>
<div class='jt-detail'>a detail 1
  <div class='jt-item-price'>12.34</div>
</div>
<div class='jt-header'>another header 2<div class='jt-item-price'>34.45</div></div>
<div class='jt-detail'>another detail 2
</div>

基本上,如果jt-item-price在jt-detail中,我想附加到前面的jt-header;这是上面的第一个对联。如果它已经在jt-header内,请保持原样(第二个对联),以便上述内容成为:

<div class='jt-header'>a header  <div class='jt-item-price'>12.34</div>
</div>
<div class='jt-detail'>a detail
</div>
<div class='jt-header'>another header<div class='jt-item-price'>34.45</div></div>
<div class='jt-detail'>another detail
</div>

我该怎么做?我会认为detach()。appendTo()但我如何检测到jt-item-price在一个细节内?我如何将它告诉前面的jt-header(可能有介入的非jt-header元素) ?

THX

编辑#1

一个更现实的例子似乎打破了使用next():

<div class='jt-row'>
<div class='jt-header'>a header 1</div>
</div>
<div class='jt-row'>
<div class='jt-detail'>a detail 1
  <div class='jt-item-price'>12.34</div>
</div>
</div>
<div class='jt-row'>

<div class='jt-header'>another header 2<div class='jt-item-price'>34.45</div></div>
</div>
<div class='jt-row'>
<div class='jt-detail'>another detail 2
</div>
</div>

9 个答案:

答案 0 :(得分:5)

Jquery append()接受一个函数,你可以使用以下逻辑:

$('.jt-header').append(function(){
    return $(this).next('.jt-detail').children('.jt-item-price');
});

-jsFiddle-

答案 1 :(得分:2)

考虑到你的编辑#1,你应该可以通过组合.closest()/ .prev()/ .find()

来实现。

喜欢这个

$(function(){
    $('#move').on('click',function(){
        $('.jt-detail .jt-item-price').each(function(){
            $this = $(this);
            $this.appendTo($this.closest('.jt-row').prev().find('.jt-header'));
        }); 
    });
});

Check the fiddle here

条件是保持当前html结构与你的jt-row:)

答案 2 :(得分:2)

实际上相当简单,只需要正确遍历DOM树

根据您的示例,这是逐步细分:

  • 使用class="jt-item-price"
  • 的FOR EACH 元素
  • IF 父类等于jt-detail
  • 然后将元素附加到jt-header
  • 中的前一个jt-row元素
  • ELSE 移至下一个jt-item-price元素&amp;重复

代码如下所示:

$('.jt-item-price').each(function(){
  if($(this).parent().hasClass('jt-detail')){
    var $headerCheck = $(this).parents('.jt-row');
    var loopCheck = false;

    while(!loopCheck){
      $headerCheck = $headerCheck.prev();
      if($headerCheck.find('.jt-header').length > 0){
        loopCheck = true;
      }
    }

    $(this).appendTo($headerCheck);
  }
})

~Live CodePen~

答案 3 :(得分:1)

您只需使用jQuery.parent()jQuery.prev()方法进行元素定位。

在你的情况下这很简单,因为你的类已经被定义了,所以在这种情况下,下面的代码可以解决这个问题:

jQuery(document).ready(function(){
  // Button required for testing purposes only
  jQuery('.moveIt').on('click', movePrice);
  // If script should run automatically
  // move everything out of this function
  function movePrice() {
    // For maintaining purposes
    var _price = 'jt-item-price';
    var _from = 'jt-detail';
    var _to = 'jt-header';
    // Vudu stuff
    jQuery('div.'+_price).each(function(){
        // Get elements
        var _this = jQuery(this);
        var _parent = _this.parent();
        var _parentClass = _parent.attr('class');
        // If parent matches the wrapper we want
        // to take the element out of
        if( _parentClass == _from ) {
            // Get its parent previous element
            var _finalWrapper = _this.parent().prev();
            // If previous element class matches our
            // destination's class
            if( _finalWrapper.attr('class') == _to ) {
                // Put price there
                jQuery(_finalWrapper).append( _this );
            }
         }
     });
   }
});

/**
 * Answer to: http://stackoverflow.com/questions/28661854/how-to-move-an-element-into-if-it-is-contained-in-another-element
 */
jQuery(document).ready(function(){
    // Testing with no Row wrappers
    jQuery('.unwrap').on('click', function(){
        jQuery('.row > .jt-header').unwrap();
    });
    // Button required for testing purposes only
    jQuery('.moveIt').on('click', movePrice);
    // If script should run automatically
    // move everything out of this function
    function movePrice() {
        // For maintaining purposes
        var _price = 'jt-item-price';
        var _from = 'jt-detail';
        var _to = 'jt-header';
        // Vudu stuff
        jQuery('div.'+_price).each(function(){
            // Get elements
            var _this = jQuery(this);
            var _parent = _this.parent();
            var _parentClass = _parent.attr('class');
            // If parent matches the wrapper we want
            // to take the element out of
            if( _parentClass == _from ) {
                // Get its parent previous element
                var _finalWrapper = _this.parent().prev();
                // If previous element class matches our
                // destination's class
                if( _finalWrapper.attr('class') == _to ) {
                    // Put price there
                    jQuery(_finalWrapper).append( _this );
                }
            }
        });
    }
});
.jt-header {
    clear: both;
    border: 1px solid #f5f5f5;
    padding: 0px .5em;
    margin: .5em;
    background: #f1f1f1;
}
.jt-detail, 
.jt-item-price {
    display: inline-block;
}
.jt-detail { padding: 1em; }
.jt-item-price {
    margin: 1em 0;
    background: #f1f1f1;
    padding: .5em;
    font-weight: bold;
}
.row {
    display: block;
    padding: .5em;
    border: 1px solid #efefef;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
    <div class='jt-header'>Product 1</div>
    <div class='jt-detail'>Product Details
      <div class='jt-item-price'>12.34</div>
    </div>
</div>
<div class="row">
    <div class='jt-header'>Product 2 
        <div class='jt-item-price'>34.45</div>
    </div>
    <div class='jt-detail'>Product Details</div>
</div>
<div class="row">
    <div class='jt-header'>Product 3</div>
    <div class='jt-detail'>Product Details
      <div class='jt-item-price'>20.55</div>
    </div>
</div>
<hr />
<button class="moveIt">Move Prices</button>
<button class="unwrap">Unwrap from Rows</button>

我希望这会有所帮助。

祝你好运, JoséSAYAGO。

jsFiddle Example

答案 4 :(得分:1)

按照您在编辑#1中发布的结构,您迭代所有jt-row,如果其中jt-item-price的父级不是jt-header,则将该元素移至上一行{ {1}}

jt-header

这是一个bin可以玩:)

答案 5 :(得分:1)

这里是小提琴链接:http://jsfiddle.net/fjjeo22h/1/

代码:

$(".jt-detail .jt-item-price").each(function () {
    var price = $(this);
    var prevhead = $(this).parent(".jt-detail").prev(".jt-header");
    if (!prevhead.find('.jt-item-price').length > 0) {
        price.appendTo(prevhead);
    }
});

答案 6 :(得分:1)

尝试

// filter `.jt-item-price` , 
// return elements not already children of `jt-header`
var itemPrice = $(".jt-item-price").not(function (i, el) {
    return $(el).parent().is(".jt-header")
});

// `itemPrice` parent element
var item = itemPrice.parents(".jt-row");

// if `item` contains child element `jt-header` ,
// append `itemPrice` at current `item`
if (item.find(".jt-header").is("*")) {
    item.find(".jt-header").append(itemPrice)
} 
// else filter `.jt-row` by index 1 less than current `item`,
// append `itemPrice` to `.jt-header` at selected `.jt-row`
else {
    item.siblings(".jt-row").eq(item.index(".jt-row") - 1)
    .find(".jt-header").append(itemPrice)
};

// filter `.jt-item-price` , 
// return elements not already children of `jt-header`
var itemPrice = $(".jt-item-price").not(function (i, el) {
    return $(el).parent().is(".jt-header")
});

// `itemPrice` parent element
var item = itemPrice.parents(".jt-row");

// if `item` contains child element `jt-header` ,
// append `itemPrice` at current `item`
if (item.find(".jt-header").is("*")) {
    item.find(".jt-header").append(itemPrice)
} 
// else filter `.jt-row` by index 1 less than current `item`,
// append `itemPrice` to `.jt-header` at selected `.jt-row`
else {
    item.siblings(".jt-row").eq(item.index(".jt-row") - 1)
    .find(".jt-header").append(itemPrice)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div class='jt-row'>
    <div class='jt-header'>a header 1</div>
</div>
<div class='jt-row'>
    <div class='jt-detail'>a detail 1
        <div class='jt-item-price'>12.34</div>
    </div>
</div>
<div class='jt-row'>
    <div class='jt-header'>another header 2
        <div class='jt-item-price'>34.45</div>
    </div>
</div>
<div class='jt-row'>
    <div class='jt-detail'>another detail 2</div>
</div>

答案 7 :(得分:0)

使用此Demo Here

$(function(){
    $('#move').on('click',function(){
        $('.jt-detail .jt-item-price').each(function(){
            $this = $(this);
            $this.appendTo($this.closest('.jt-row').prev().find('.jt-header'));
        }); 
    });

});

答案 8 :(得分:0)

你可以使用nextUntil,它会迭代直到找到元素。有了这个,你可以在标题和细节之间拥有尽可能多的元素(这是我理解的目标吗?)

JSFIDDLE

运行以下代码段。我只是将标题加粗,以便您可以看到它正常工作。

$('.jt-header').each(function () {
    var $this = $(this)
    $this.append(function () {
        var el = $this.next('.jt-detail')
        if (el.length < 1) el = $this.nextUntil('.jt-detail').next('.jt-detail');
        return el.children('.jt-item-price');
    });
});
.jt-header {
    font-weight:bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="jt-header">a header 1</div>
<div class="jt-detail">a detail 1
    <div class="jt-item-price">12.34</div>
</div>
<div class="jt-header">another header 2
    <div class="jt-item-price">34.45</div>
</div>
<div class="jt-detail">another detail 2</div>

<hr />

<div class="jt-header">a header 1</div>
<div class="something-between">La la la I'm in the way :P</div>
<div class="jt-detail">a detail 1
    <div class="jt-item-price">12.34</div>
</div>
<div class="jt-header">another header 2
    <div class="jt-item-price">34.45</div>
</div>
<div class="jt-detail">another detail 2</div>