Kyle Underhill
Kyle Underhill

Reputation: 109

Append on resize and load with multiple instances

I want to append .item from .left to .right on page load and resize when $(window).width() < 479. The problem is that with multiple instances, the resize function re-iterates to append .item several times.

How do I change the code so that it only executes once per .item?

codepen.io/moofawsaw/pen/PoNVejV

function moveDiv() {
  if ($(window).width() < 479) {
    $('.item').appendTo('.right');
  } else {
    $('.item').appendTo('.left');
  }
}
moveDiv();
$(window).resize(moveDiv);
body {
  display: flex;
}

.post {
  display: flex
}

.item {
  height: 100px;
  width: 100px;
  border: 2px solid;
}

.right,
.left {
  min-width: 100px;
  height: 200px;
}

.right {
  background: silver;
}

.left {
  background: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="post">
  <div class="right">
    <div class="item"></div>
  </div>
  <div class="left"></div>
</div>
<div class="post">
  <div class="right">
    <div class="item"></div>
  </div>
  <div class="left"></div>
</div>

Upvotes: 2

Views: 117

Answers (1)

Vasiliy Artamonov
Vasiliy Artamonov

Reputation: 1057

If I would answer the given question, here it is.

The main problem in the given code was that $('.item') selects all existing .items and clones them as much as there are .right or .left items on the page. It would work perfectly if you had only one of those .right or .left containers.

So to solve this one we won't select all .items at once and instead we would process each .item separately using convenient jQuery function .each()

function moveDiv() {
  if ($(window).width() < 479) {
    moveItemInPostTo('.right');
  } else {
    moveItemInPostTo('.left');
  }
}

function moveItemInPostTo(selector) {
  // Instead of working with all .item elements at once,
  // iterate over each one separately
  $('.item').each(function(i, el) {
    // Get parent container, in which we can find
    // both .left and .right elements
    var $post = $(el.closest('.post'));
    // Move the .item to one of them
    $(el).appendTo($post.find(selector));
  })
}

moveDiv();
$(window).resize(moveDiv);
body {
  display: flex;
}

.post {
  display: flex
}

.item {
  height: 100px;
  width: 100px;
  border: 2px solid;
}

.right,
.left {
  min-width: 100px;
  height: 200px;
}

.right {
  background: silver;
}

.left {
  background: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="post">
  <div class="right">
    <div class="item"></div>
  </div>
  <div class="left"></div>
</div>
<div class="post">
  <div class="right">
    <div class="item"></div>
  </div>
  <div class="left"></div>
</div>

Though this code works well, I would really recommend you solve this one in a non-javascript way (probably, just CSS). And if it still should be done using javascript - at least don't use jQuery. It is not really optimized in terms of how much it is pressuring the internet traffic (almost 90KB), and every thing you do with jQuery you can achieve using plain Javascript. Although, gotta admit, it's good for starters.

I answered your question, but if you would provide more details on what are your trying to achieve, I probably could give you another good answer.

Upvotes: 1

Related Questions