StudioTime
StudioTime

Reputation: 24019

Find child of a sibling - jQuery

I have the following html structure:

<div class="clickMe" data-videourl="http://yt.com/123/">click</div>
<div class="somethingElse">blah</div>
<div class="showVideo">
  <iframe class="ytVideo" src=""></iframe>
</div>

What I need to do is take the data-videourl value from .clickMe and add it it .ytVideo

This is what I'm trying but the src is not being set:

$('.clickMe').on("click", function() {
  var videoURL = $(this).data('videourl');
  alert(videoURL); <-- a test, this works fine, the data is there
  $(this).next('.showVideo').find('.ytVideo').attr('src',videoURL);
});

Upvotes: 0

Views: 64

Answers (2)

jfriend00
jfriend00

Reputation: 708036

jQuery's .next() often trips people up. It does not find the next sibling of all the siblings that matches the selector you give it. Instead, it looks ONLY at the next sibling to see if it matches that selector. That, obviously won't do what you need.

A common design pattern for this type of problem is to use .closest() to get a common parent and then use .find() to find the desired child.

<div class="container">
    <div class="clickMe" data-videourl="http://yt.com/123/">click</div>
    <div class="somethingElse">blah</div>
    <div class="showVideo">
       <iframe class="ytVideo" src=""></iframe>
    </div>
</div>

$('.clickMe').on("click", function() {
  var videoURL = $(this).data('videourl');
  $(this).closest(".container").find('.ytVideo').attr('src',videoURL);
});

You can also use .nextAll() to collect all the siblings that follow your element that match a given selector.

$('.clickMe').on("click", function() {
  var videoURL = $(this).data('videourl');
  $(this).nextAll(".showVideo").find('.ytVideo').attr('src',videoURL);
});

The advantage of using a common parent and .closest() is that it is less dependent upon the exact structure of your HTML (and therefore less brittle to change in the HTML). All it requires is that the target object is somewhere within a common parent. That's why the use of .closest() and then .find() on that common parent is such a common design pattern for this type of problem. Intervening divs could be added to faciliate presentation changes and the code would continue to work. That is not necessarily true with .nextAll() as the target div has to stay at exactly the right level, not just in a common branch.

The performance difference between .find() in a branch and .nextAll() at a sibling level is rarely significant for any operation triggered by a user's click so it makes sense to code for robustness.

Upvotes: 1

Krycke
Krycke

Reputation: 3186

Next only return the immidiate sibling (.somethingElse) and that doesn't match the selector.

Change it to nextAll() to select all of them, and then grab the one you want with the selector.

$('.clickMe').on("click", function() {
  var videoURL = $(this).data('videourl');
  alert(videoURL); <-- a test, this works fine, the data is there
  $(this).nextAll('.showVideo').find('.ytVideo').attr('src',videoURL);
});

Here is the documentation: https://api.jquery.com/nextAll

Upvotes: 1

Related Questions