-1

I have a script that on is supposed to read all sibling HTML elements with the class .rect when one of them is clicked, and put them into an array using Array.from($(this).siblings())... and then do something with that array.

The problem is, the array length is 3 instead of 4, causing everything to be off by one, and I can't figure out why.

In the code below, when one of the colored divs is clicked, the collection of divs is supposed to be replaced with only the one that was clicked. Instead it is replaced with its next sibling. In the event that the last one (yellow) is clicked, nothing happens - presumably because the last index is missing from the array.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
.rect {width:24px; height:12px; border-radius:12px; border:4px solid rgba(0,0,0,0.25); margin-bottom:12px}
.red {background-color:#c21}
.green {background-color:#1c3}
.blue {background-color:#28f}
.yellow {background-color:#ed1}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
</head>
<body>
<div id="target">
 <div class="rect red"></div>
 <div class="rect green"></div>
 <div class="rect blue"></div>
 <div class="rect yellow"></div>
</div>
<script>
$(".rect").click( function() {
 var sort = Array.from( $(this).siblings() );
 var current_index = $(this).index();
 document.getElementById("target").innerHTML = sort[current_index].outerHTML;
});
</script>
</body>
</html>

What would cause this?

Edit: I'm guessing the downvote is because some people think it is obvious that the term "siblings" would not include one's self - as in: "I have three siblings". But the term can also be used like: "We are all siblings" or "I am one of four siblings". And when I searched "javascript does siblings include self" no obvious answers surfaced. Today I learned.

Mentalist
  • 1,530
  • 1
  • 18
  • 32
  • $(this).siblings() returns the three siblings elements not including the element clicked, this is why you get an array of 3 elements – David Oct 30 '19 at 09:08
  • The behaviour you are getting is expected because when one elem with class .rect as clicked it has three other siblings hence you are getting the. Siblings will not obviously include the target element also. – Abhishek Bag Oct 30 '19 at 09:10
  • @David I was wondering about that actually, and searched to find if there was an alternative command that would get *all* the siblings, including the clicked one. I couldn't find any relevant results. Do you know if there is such a command? – Mentalist Oct 30 '19 at 09:12
  • @David User *shrys* just commented that `$(this).parent().children()` would essentially do that. So I guess that answers the question I just asked you (unless you know of an even more elegant way). – Mentalist Oct 30 '19 at 09:19

1 Answers1

1

Use $(".rect") or $(this).parent().children() instead, as .sibilings() would not have the current element, you also wouldn't be needing Array.from:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <style>
    .rect {width:24px; height:12px; border-radius:12px; border:4px solid rgba(0,0,0,0.25); margin-bottom:12px}
    .red {background-color:#c21}
    .green {background-color:#1c3}
    .blue {background-color:#28f}
    .yellow {background-color:#ed1}
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
</head>

<body>
  <div id="target">
    <div class="rect red"></div>
    <div class="rect green"></div>
    <div class="rect blue"></div>
    <div class="rect yellow"></div>
  </div>
  <script>
    $(".rect").click(function() {
      var sort = $(this).parent().children(); //$(".rect");
      var current_index = $(this).index();
      document.getElementById("target").innerHTML = sort[current_index].outerHTML;
    });
  </script>
</body>

</html>
shrys
  • 5,860
  • 2
  • 21
  • 36
  • Thank you! One thing I'm not clear on: If `$(this)` is not used, what prevents all elements with the `.rect` class from being read into the array in duplicate? – Mentalist Oct 30 '19 at 09:14
  • 1
    in that case you're better off using `$(this).parent().children()` instead as it would get only those children elements where the event is fired – shrys Oct 30 '19 at 09:16