Find next element with a given class, regardless o

2019-05-31 02:58发布

I'm having a really hard time trying to figure out something which I believe should be relatively simple.

I need to get the next occurrence of a class (div.content), which could appear anwhere in the DOM

Below is some simplified markup which represents what I have:

<div class="container">
  <div class="content">
    Example content #1    <a href="#" class="next">Next</a>
  </div>

  <div class="content">
    Example content #2    <a href="#" class="next">Next</a>
  </div>
</div>

<div class="container">
  <div class="content">
    Example content #1    <a href="#" class="next">Next</a>
  </div>

  <div class="content">
    Example content #2    <a href="#" class="next">Next</a>
  </div>
</div>

Showing the next content div within a given container works fine, the problem comes when I try to get from the last content div in a container to the first content div in the next container.

A couple of important points:-

  • By default, only the first content div is visible, the rest are hidden, though I need a solution that would work if for instance the second content div in the fourth container is visible.

  • Only one content div will ever be visible.

The only solution I've managed to come up with so far seems extremely cumbersome, although it does work.

$('.next').click(function() {
    $theContent = $(this).parent('.content');
    $theContent.hide();

    if ($theContent.next('.content').length) {
        $theContent.next('.content').show();
    } else if ($theContent.parent('.container').next('.container')
        .children('.content').length
    ) {
        $theContent.parent('.container').next('.container')
            .children('.content:first').show();
    } else {
        // reached the end or something went wrong
    }
});

The major downside to this is that it relies on having the above DOM structure, I'd convinced myself that a method would exist for selecting the next element with a given class, regardless of where it appeared in the DOM.

Ideally I'd like a solution which doesn't rely on any given DOM structure, if that's not possible, any alternative solutions would be helpful!

Here's a fiddle with the above example

Sorry for the long-winded question!

4条回答
等我变得足够好
2楼-- · 2019-05-31 03:20

how about this:

if ($theContent.next('.content').length) {
   $theContent.next('.content').show();
} else if ($theContent.parent('.container').next('.container').children('.content').length) {
   $theContent.parent('.container').next('.container').children('.content:first').show();
} else {
   $('.content:first').show();
   //alert('Reached the end or something went wrong!');
}

JSFIDDLE

查看更多
可以哭但决不认输i
3楼-- · 2019-05-31 03:28

It turns out that this is indeed a very simple task. By passing a selector to jQuery's index() method, you're able to get the index of the current element, relative to its collection:

var idx = $theContent.index('div.content') + 1;

Then the content div can be targeted directly:

$('div.content').eq(idx).show();
查看更多
姐就是有狂的资本
4楼-- · 2019-05-31 03:28
jQuery(function() {
    var i = 1;
    jQuery('.content').each(function() {
        jQuery(this).addClass('content-' + i);
        i++;

        jQuery(this).find('a.next').bind('click', function() {
            toggleContentDivs(jQuery(this).parent());
        }); 
    });
});

function toggleContentDivs(oContentDiv)
{
    var nextVisible   = false,
        setVisibility = false;

    jQuery('.content').each(function() {
        if (oContentDiv.attr('class') == jQuery(this).attr('class')) {
            nextVisible = true;
            jQuery(this).hide();
        } else if (nextVisible == true) {
            jQuery(this).show();
            nextVisible   = false;
            setVisibility = true;
        } else {
            jQuery(this).hide();
        }
    });
    // it must have been the last .content element
    if (setVisibility == false) { 
        jQuery('.content:first').show();
    }
}

Only DOM dependency with the existing code, is a.next must be an immediate child of .content.

Working jsFiddle example here

查看更多
相关推荐>>
5楼-- · 2019-05-31 03:37

Turns out a simpler (less verbose) way to write it is exactly how you had it minus the function arguments:

$theContent.parent().next().length

EDIT 2:

I tried all of my solutions extensively but they were flawed. In short I think you pretty have the simplest way of doing it. Unless maybe a jQuery expert could chime in on this and show us a better way.

Here's my last proposal:

$('.next').click(function() {
    $theContent = $(this).parent('.content');
    $theContent.hide(10, function() {
        if (!$theContent.next('.content').length) {
            $theContent.parent('.container').next()
                .find('.content:first').show();
        } else {
            $theContent.next('.content').show();
        }
    });
});

The ideal solution would be to use closest(), but the problem is that it's not behaving the way I expected because of their separation by containers. In jQuery's example they use an unordered list. Well yeah, this is much easier because you can distinguish between node types (e.g. li vs ul) and simply do .next('li'). Here you are using all divs. And for some reason .closest('.content') doesn't work once the end of the first container is reached!

查看更多
登录 后发表回答