Collapsible Panel

Hi all.

I am a newbie to Javascript and I have found this code for collapsible panels which works great, however i would like the panel to begin collapsed rather then expanded when the page is loaded. Can anyone help please? thank you in advance.



<html>
<head>
    <style type="text/css">
    .squarebox {
        width: 100%;
        border: solid 1px #336699;
        text-align: center;
        overflow: hidden; }
    .squareboxgradientcaption {
        color: #ffffff;
        padding: 5px;
        background-image: url(../images/gradient_blue.png);
        background-repeat: repeat-x; }
    .squareboxcontent {
        background-color: #f5f5f5;
        padding: 10px;
        overflow: hidden;
        border-top: solid 1px #336699; }
    </style>
    <script language="javascript" type="text/javascript">
    function togglePannelStatus(content)
    {
        var expand = (content.style.display=="none");
        content.style.display = (expand ? "block" : "none");
        var chevron = content.parentNode
            .firstChild.childNodes[1].childNodes[0];
        chevron.src = chevron.src
            .split(expand ? "expand.gif" : "collapse.gif")
            .join(expand ? "collapse.gif" : "expand.gif");
    }
    </script>
</head>
<body>
<!-- Collapsible panel, with separate CSS and JavaScript -->
<div style="width:170px;">
    <div class="squarebox"><div
     class="squareboxgradientcaption"
     style="height:20px; cursor: pointer;"
     onclick="togglePannelStatus(this.nextSibling)"><div
         style="float: left">Title goes here...</div><div
         style="float: right; vertical-align: middle"><img
         src="../images/collapse.gif" width="13"
         height="14" border="0"
         alt="Show/Hide" title="Show/Hide" /></div>
        </div><div class="squareboxcontent">
            <img width="150" height="100"
             src="../images/sample_photo.jpg"
             alt="This is an image" title="This is an image" /><br />
             Content goes here...
        </div>
    </div>
    <img width="170" height="20" alt="" src="../images/shadow.gif" />
</div>
</body>
</html>


You could add “display: none” to the inline style that you already have there.

That worked, thank you.

However, now on initial load up the panel requires 2 clicks to expand it. once it has been initially expanded one click closes it and opens it. why does it need 2 clicks initially and is there a way to fix it?

thank you again for all your help.

Most likely due to the display:none being in the wrong place.

Try it here:


<div class="squareboxcontent" style="display: none;">

If you let is know where you found that code, we could also put efforts to converting it into more stable and easier to modify code.

Spot on, thank you.

I put the display: none in the css block at the top of the page. Its quite amazing that putting it there causes you to have to click twice but putting it in the main block corrects it. Why does that happen?

I used the tutorial at this website;

http://xtractpro.com/articles/Animated-Collapsible-Panel.aspx

thank you again, its great to know there are people out there with the answers.

Because the element.style object relates to the inline styles. There’s a completely separate and not very cross-compatible way to access the computed styles, and the stylesheets themself. Quite frankly it’s a mess.

We can work around it though by adjusting what the script looks for.

The elements style could be “” or “none” when it’s closed.
It can only be “block” when it’s open, so we can check for that instead, and use ! to invert the result.


var expand = !(content.style.display=="block");

Oh yes, I forgot to add that having it closed by default from the CSS stylesheet guarantees that anyone who is not using JavaScript won’t be able to see it.

For such reasons, it’s often better to use scripting to close such elements instead, which also neatly resolves the trouble with the element.style object.

If you want to go that way just let us know.

so as it is, people not using javascript wont be able to see the expanded content?

I definatly need a solution for that please?

Okay, this requires running some script after the page content is available. It’s not possible to run the script directly from the head, because at that particular time nothing below it exists yet.

It’s possible to use window.onload or other domcontentready events, but this is where we can make good use of the best-practice technique where you put scripts at the bottom of the page. Just before the </body> tag.

First we need scripting to obtain a reference to the element. That can easily be done if there’s a unique identifier, but with a class name things get a bit trickier.

Some web browsers natively support getElementsByClassName while others don’t. One technique is to provide a completely separate getElementsByClassName function, and a simpler technique is to loop through your DIVs looking for one who’s class name matches what we’re after.

I’ll use the simpler technique here since there’s no point in adding three times the scripting code if it’s only going to be used just the once.


var divs = document.getElementsByTagName('div'),
    divsLen = divs.length,
    div,
    i;
for (i = 0; i < divsLen; i += 1) {
    if (divs[i].className === 'squareboxcontent') {
        div = divs[i];
        break;
    }
}
div.style.display = 'none';

Remove that added css style, put in the above script at the end of your body (a script reference to an external script file is preferred, instead of inline scripting), just before the </body> tag, and you’ll be all good to go.

something strange is happening!

I have 3 collapsible panels on the page.

it works perfectly when javascript is turned off, it displays the expanded content. However, when javascript is turned back on it has the first one collapsed but the second and third and expanded?

thank you again for your time

Okay, when dealing with multiple elements things have to be done a little bit differently.

Here’s an update to the script.


var divs = document.getElementsByTagName('div'),
    divsLen = divs.length,
    div,
    i;
for (i = 0; i < divsLen; i += 1) {
    div = divs[i];
    if (div.className === 'squareboxcontent') {
        div.style.display = 'none';
    }
}

wow, your amazing. that worked perfectly. thank you so much.