Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

jQuery match all elements after headings

Options
  • 11-02-2010 3:42pm
    #1
    Registered Users 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 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 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 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