The Web Design Group

... Making the Web accessible to all.

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
> Classic Div Toggle, ...with a twist I can't seem to figure out...
Duchess
post Jan 6 2010, 04:26 PM
Post #1





Group: Members
Posts: 5
Joined: 6-January 10
Member No.: 10,781



I have the following:

CODE
function showdiv(name,focus){
var obj = (document.getElementById)? document.getElementById(name) : eval("document.all[name]");
    if (obj.style.display=="none"){
        obj.style.display="";
    }else{
        obj.style.display="none";
    }
}

<div align="left"><a onClick="showdiv('div1');" style="cursor: pointer;">DIV 1</a></div>
<div id="div1" style="display: none;">DIV CONTENT</div>

<div align="left"><a onClick="showdiv('div2');" style="cursor: pointer;">DIV 2</a></div>
<div id="div2" style="display: none;">DIV CONTENT</div>


This is the classic JavaScript solution to toggling a div, and it handles multiple divs. It works fine.

What I'm trying to do is advance it a level by making it so only one div shows at a time. In otherwords, I click the link, it shows the div. I click it again, it goes away. This works. I click that link again, it shows the div again. I click the other link now, the first div goes away and the second div shows up instead. So on and so forth.

I tried doing this:

CODE
function showdiv(name1,name2,focus){
var obj1 = (document.getElementById)? document.getElementById(name1) : eval("document.all[name1]");
var obj2 = (document.getElementById)? document.getElementById(name2) : eval("document.all[name2]");
    if (obj2.style.display==""){
        obj2.style.display="none";
    }
    if (obj.style.display=="none"){
        obj.style.display="";
    }else{
        obj.style.display="none";
    }
}

<div align="left"><a onClick="showdiv('div1,div2');" style="cursor: pointer;">DIV 1</a></div>
<div id="div1" style="display: none;">DIV CONTENT</div>

<div align="left"><a onClick="showdiv('div2,div1');" style="cursor: pointer;">DIV 2</a></div>
<div id="div2" style="display: none;">DIV CONTENT</div>


Is this just too simple to be true?
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Jan 7 2010, 08:22 AM
Post #2


.
********

Group: WDG Moderators
Posts: 9,630
Joined: 10-August 06
Member No.: 7



QUOTE(Duchess @ Jan 6 2010, 10:26 PM) *

CODE
function showdiv(name,focus)


The "focus" argument doesn't seem to be used for anything.

QUOTE
CODE
var obj = (document.getElementById)? document.getElementById(name) : eval("document.all[name]");

That looks terribly ancient, I recall document.all was necessary for IE4. Today "all" browsers support document.getElementById.

QUOTE

What I'm trying to do is advance it a level by making it so only one div shows at a time. In otherwords, I click the link, it shows the div. I click it again, it goes away. This works. I click that link again, it shows the div again. I click the other link now, the first div goes away and the second div shows up instead. So on and so forth.

I rewrote both the script and the HTML. ninja.gif This way it's meant to work with any number of DIVs. Haven't tested it much, though. I don't use link elements for the labels, since such links tend to annoy users without javascript, instead I create BUTTON elements (with javascript) so that users can open the DIVs with their keyboard too (not just the mouse). If you don't like the look of buttons you might change their appearance with CSS. The script must appear after the DIVs.


CODE
<div class="toggle">DIV 1
    <div>DIV CONTENT 1</div>
</div>

<div class="toggle">DIV 2
    <div>DIV CONTENT 2</div>
</div>

<script type="text/javascript">
function toggle(parent)
{
    for(var i=0; i<div.length; i++)
    {
        if(div[i].className=='toggle')
        {
            // make toggle button:
            if(div[i].firstChild.nodeName!='BUTTON')
            {
                var button=document.createElement('button');
                button.setAttribute('type', 'button');
                button.appendChild(div[i].firstChild);
                div[i].insertBefore(button, div[i].firstChild);
            }

            var child=div[i].getElementsByTagName('div')[0];
            
            // mark the parent of an opened DIV:
            div[i].state='';
            if(child.style.display=='block')
            {
                div[i].state='open';
            }
            
            child.style.display='none';
            
            div[i].onclick=function()
            {
                toggle(this);
            }
        }
    }
    
    if(parent)
    {
        var child=parent.getElementsByTagName('div')[0];
        if(child.style.display=='none' && parent.state!='open')
        {
            child.style.display='block';
        }
        else
        {
            child.style.display='none';
        }
    }
}
var div=document.getElementsByTagName('div');
toggle();
</script>
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Duchess
post Jan 7 2010, 09:57 AM
Post #3





Group: Members
Posts: 5
Joined: 6-January 10
Member No.: 10,781



First, thank you very much for your reply and help. smile.gif

QUOTE(Christian J @ Jan 7 2010, 08:22 AM) *

QUOTE(Duchess @ Jan 6 2010, 10:26 PM) *

CODE
function showdiv(name,focus)


The "focus" argument doesn't seem to be used for anything.

QUOTE
CODE
var obj = (document.getElementById)? document.getElementById(name) : eval("document.all[name]");

That looks terribly ancient, I recall document.all was necessary for IE4. Today "all" browsers support document.getElementById.


Could be. I had gotten this off another tutorial about two years ago for a different site I was working on. I figured, since it worked, why reinvent the wheel? The tutorial might have been rather old. The 'focus' argument was in that.

QUOTE(Christian J @ Jan 7 2010, 08:22 AM) *

CODE
<div class="toggle">DIV 1
    <div>DIV CONTENT 1</div>
</div>

<div class="toggle">DIV 2
    <div>DIV CONTENT 2</div>
</div>



I'm curious here about the nested divs. Do I really need the double tags here? Seems rather redundant to someone still learning.

This post has been edited by Duchess: Jan 7 2010, 09:57 AM
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Jan 7 2010, 11:37 AM
Post #4


.
********

Group: WDG Moderators
Posts: 9,630
Joined: 10-August 06
Member No.: 7



QUOTE(Duchess @ Jan 7 2010, 03:57 PM) *

I'm curious here about the nested divs. Do I really need the double tags here? Seems rather redundant to someone still learning.

I guess there are several ways to do it, but you'll at least need one element for the content you want to show/hide, and another for the clickable "label". You don't have to use DIV elements for this, many other elements might do as well (a definition list, perhaps?). Also you don't have to nest them, e.g. you could use a clickable heading followed by a text paragraph that's shown/hidden. Of course any such changes to the HTML require rewriting of the script as well.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Duchess
post Jan 7 2010, 03:27 PM
Post #5





Group: Members
Posts: 5
Joined: 6-January 10
Member No.: 10,781



Okay. I can understand that.

QUOTE(Christian J @ Jan 7 2010, 08:22 AM) *

If you don't like the look of buttons you might change their appearance with CSS.


This is apparently the fun part. The buttons clash horribly with the template and the links looked much better. So, now that we've made them into buttons, how do I change them back to looking like links? So far, Google's turned up results for actual 'input' buttons for forms or how to make text links look like buttons, unless I'm searching badly. I tried a few and ended up with some odd results.

This post has been edited by Duchess: Jan 7 2010, 03:28 PM
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Jan 7 2010, 05:56 PM
Post #6


.
********

Group: WDG Moderators
Posts: 9,630
Joined: 10-August 06
Member No.: 7



QUOTE(Duchess @ Jan 7 2010, 09:27 PM) *

now that we've made them into buttons, how do I change them back to looking like links?

Like this?

CODE
button {
border: 0;
text-decoration: underline;
color: #00f;
background: #fff;
cursor: pointer;
}


Or you could simply remove the part of the script that creates the buttons, since it's clicking the parent DIV (and its content) that actually makes things happen. I'd rather keep the BUTTON elements though, since that enables keyboard navigation.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Duchess
post Jan 8 2010, 09:08 AM
Post #7





Group: Members
Posts: 5
Joined: 6-January 10
Member No.: 10,781



QUOTE(Christian J @ Jan 7 2010, 05:56 PM) *
Or you could simply remove the part of the script that creates the buttons, since it's clicking the parent DIV (and its content) that actually makes things happen. I'd rather keep the BUTTON elements though, since that enables keyboard navigation.


I'm doing this for someone else's site. What they want goes. ^^;

Thanks again, though!
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Jan 8 2010, 09:47 AM
Post #8


.
********

Group: WDG Moderators
Posts: 9,630
Joined: 10-August 06
Member No.: 7



You're welcome! smile.gif

Here's an idea that adds links instead of buttons. Use it instead of the button section in the script above.

CODE
// make toggle link
if(div[i].firstChild.nodeName!='A')
{
    var a=document.createElement('a');
    a.setAttribute('href', '#show_or_hide_contents');
    a.appendChild(div[i].firstChild);
    div[i].insertBefore(a, div[i].firstChild);
}


you may also want add a "return false" in the onclick to cancel the link's HREF:

CODE
div[i].onclick=function()
{
    toggle(this);
    return false;
}


By using "return false" like this you may even leave the HREF blank:

CODE
a.setAttribute('href', '');
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Duchess
post Jan 8 2010, 12:42 PM
Post #9





Group: Members
Posts: 5
Joined: 6-January 10
Member No.: 10,781



QUOTE(Christian J @ Jan 8 2010, 09:47 AM) *
Here's an idea that adds links instead of buttons. Use it instead of the button section in the script above.

CODE
// make toggle link
if(div[i].firstChild.nodeName!='A')
{
    var a=document.createElement('a');
    a.setAttribute('href', '#show_or_hide_contents');
    a.appendChild(div[i].firstChild);
    div[i].insertBefore(a, div[i].firstChild);
}


you may also want add a "return false" in the onclick to cancel the link's HREF:

CODE
div[i].onclick=function()
{
    toggle(this);
    return false;
}


By using "return false" like this you may even leave the HREF blank:

CODE
a.setAttribute('href', '');


Ooo... that looks fun. smile.gif I'll give it a go.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
kit
post Jun 16 2011, 03:03 AM
Post #10





Group: Members
Posts: 2
Joined: 16-June 11
Member No.: 14,773



This works beautifully. Thank you!
Is there a way to show the contents of div 1 from the start, before any of the buttons or links are clicked?
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
kit
post Jun 16 2011, 08:30 AM
Post #11





Group: Members
Posts: 2
Joined: 16-June 11
Member No.: 14,773



I entered the first div without the toggle class above the rest so it appears at the start. Thank you again.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Jun 17 2011, 08:56 AM
Post #12


.
********

Group: WDG Moderators
Posts: 9,630
Joined: 10-August 06
Member No.: 7



QUOTE(kit @ Jun 16 2011, 03:30 PM) *

I entered the first div without the toggle class above the rest so it appears at the start. Thank you again.

Of course then it will not disappear even when the other DIVs are shown.

Here's yet another quick version (might be buggy):

CODE
<div class="toggle initially_open">DIV 1
    <div>DIV CONTENT 1</div>
</div>

<div class="toggle">DIV 2
    <div>DIV CONTENT 2</div>
</div>

<div class="toggle">DIV 3
    <div>DIV CONTENT 3</div>
</div>

<script type="text/javascript">
var mechanism='link'; // choose between 'link' or 'button'


function toggle(parent)
{
    for(var i=0; i<div.length; i++)
    {
        if(div[i].className.indexOf('toggle')!=-1)
        {
            // initialize menu
            if(!parent)
            {
                // build toggle mechanism (button or link)
                if(mechanism=='button')
                {
                    var button=document.createElement('button');
                    button.setAttribute('type', 'button');
                    button.appendChild(div[i].firstChild);
                    div[i].insertBefore(button, div[i].firstChild);
                }
                else if(mechanism=='link')
                {
                    var button=document.createElement('a');
                    button.setAttribute('href', '#show_or_hide_contents');
                    button.appendChild(div[i].firstChild);
                    div[i].insertBefore(button, div[i].firstChild);
                }

                // hide items onload, unless except those
                // flagged with the class "initially_open"
                if(div[i].className.indexOf('initially_open')==-1)
                {
                    div[i].getElementsByTagName('div')[0].style.display='none';
                }

                // detect clicks
                button.onclick=function()
                {
                    toggle(this.parentNode);
                    return false;
                }
            }

            // hide all items except the one clicked
            else if(parent)
            {
                div[i].getElementsByTagName('div')[0].style.display='none';
            }
        }
    }

    // react to clicks
    if(parent)
    {
        var child=parent.getElementsByTagName('div')[0];
        if(child.style.display=='none')
        {
            child.style.display='block';
        }
        else
        {
            child.style.display='none';
        }
    }
}
var div=document.getElementsByTagName('div');
toggle();
</script>

User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Jan 21 2013, 08:10 PM
Post #13


.
********

Group: WDG Moderators
Posts: 9,630
Joined: 10-August 06
Member No.: 7



Post moved here: http://forums.htmlhelp.com/index.php?s=&am...ost&p=72701
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post

Reply to this topicStart new topic
2 User(s) are reading this topic (2 Guests and 0 Anonymous Users)
0 Members:

 



- Lo-Fi Version Time is now: 29th March 2024 - 04:00 AM