Advertisement
Help Keep Boards Alive. Support us by going ad free today. See here: https://subscriptions.boards.ie/.
If we do not hit our goal we will be forced to close the site.

Current status: https://keepboardsalive.com/

Annual subs are best for most impact. If you are still undecided on going Ad Free - you can also donate using the Paypal Donate option. All contribution helps. Thank you.
https://www.boards.ie/group/1878-subscribers-forum

Private Group for paid up members of Boards.ie. Join the club.

jQuery match all elements after headings

  • 11-02-2010 03:42PM
    #1
    Registered Users, Registered Users 2 Posts: 872 ✭✭✭


    HI,

    I have a page that consists of 20 H5 titles with some paragraphs or lists underneath each heading.

    I would like to hide all elements under each heading and then add a click event to the heading to toggle the elements below the heading.

    I can get the next element after the heading like:

    $('.wrapper h5').next().attr('style','color:red');

    but how could i grab all elements under each heading when there are more than one ?

    Thanks for any tips.


Comments

  • Subscribers Posts: 9,716 ✭✭✭CuLT


    Easiest way that springs to mind is to just wrap all the content between each header in a div, or some other single entity that encapsulates the data and fire a toggle() on click.
    $("h5.someClass").click(function(){
    $(this).next("div").toggle();
    })
    

    That should do the trick (I think?) with a layout like:
    <h5 class="someClass">My Title</h5>
    <div>
    <p>A paragraph!</p>
    <p>
    Here's a neato list:
    <ul>
    <li>A list item in a paragraph!</li>
    </ul>
    </p>
    </div>
    

    Edit: this assumes that the div has a css styling of display:none on load.


  • Registered Users, Registered Users 2 Posts: 872 ✭✭✭grahamor


    Thanks for the reply,

    Unfortunately, there is no div surrounding the elements under the heading :(

    It's done this way in 25 languages so i'm looking for a way to do it without having to modify every language !!


  • Registered Users, Registered Users 2 Posts: 128 ✭✭johnny_rambo


    If there is only text between the h5 tags, try this....
    $("h5").each(function() {
        var text = this.nextSibling;
        var textWrapper = $("<div style='display:none;'></div>")[0];
        text.parentNode.insertBefore(textWrapper , text);
        textWrapper.appendChild(text);            
    })
    .css("cursor", "pointer")
    .toggle(function() { $(this).next().show(); }, function() { $(this).next().hide();});
    


    If there are other elements (e.g. <ul>, <br /> etc.) between the h5 tags, try this....
    $("h5").each(function() {
        var nextSib = this.nextSibling, allSiblings = "";
        while(nextSib != null && nextSib.tagName != this.tagName) {
            if (nextSib.nodeType == 3) { allSiblings += nextSib.nodeValue; }
            else if (nextSib.nodeType == 1) { allSiblings += "<" + nextSib.tagName + ">" + nextSib.innerHTML + "</" + nextSib.tagName + ">"; }
            if (nextSib.nextSibling != null) {
                nextSib = nextSib.nextSibling;
                this.parentNode.removeChild(nextSib.previousSibling);
            }
            else {
                this.parentNode.removeChild(nextSib);
                break;
            }
        }
        var textWrapper = $("<div style='display:none;'>" + allSiblings + "</div>")[0];
        if (nextSib.nextSibling != null) { this.parentNode.insertBefore(textWrapper , nextSib); }
        else { this.parentNode.appendChild(textWrapper); }
    })
    .css("cursor", "pointer")
    .toggle(function() { $(this).next().show(); }, function() { $(this).next().hide();});
    

    The 2nd method is a bit of a hack :o It'll only catch element and text node types....you'll have to add more code to catch other node types (e.g. Comments). Anyone have a better way of doing this?


  • Subscribers Posts: 9,716 ✭✭✭CuLT


    Jaysus, that is murderous looking alright - points for sheer tenacity though :D

    Didn't realize that being unable to modify the HTML was a pre-requisite - ouch. Good luck grahamor.


  • Registered Users, Registered Users 2 Posts: 128 ✭✭johnny_rambo


    Yep you have to check the node type because you can't call innerHTML on a text node. Murderous is right! :D I'm sure there's a more elegent solution!


  • Advertisement
Advertisement