www.webdeveloper.com
Results 1 to 9 of 9

Thread: Trouble with my drop down menu

  1. #1
    Join Date
    Jun 2014
    Posts
    21

    Trouble with my drop down menu

    Hey, so I'm creating a drop down menu. It can be toggled on and off with onclick.

    One of the things I'm not certain of is the existence of: getElementsByClassName. I gave my two menu items the class 'project' and wanted to use both of them at the same time.

    JS

    Code:
    function toggleDrop() {
    
       var myProj = document.getElementsByClassName('project');
    
       var displaySetting = myProj.style.display;
       
       if (displaySetting == 'block') { 
          //It's visible - hide it
          myProj.style.display = 'none';
          
    	  }else { 
          // It's hidden - show it
          myProj.style.display = 'block';
         
        }
    }

    HTML

    Code:
    <ul id="projectDrop">	
    	<li>
            <a onclick="toggleDrop()" id="top" href="">Our Projects</a>
            <ul>
                <li class="project"><a href="#">Project 1</a></li>
    
                <li class="project"><a href="#">Project 2</a></li>
            </ul>
     
        </li>
     </ul>

    CSS

    Code:
    #projectDrop{
    	list-style: none; 
    	font-weight: bold; 
    	margin-bottom:10px;
    	width: 500px
    }
    
    #projectDrop li{
    	margin-right:0px;
        position:relative;
    	
    }
    
    #projectDrop a{
    	
    	text-decoration: none;  
    	padding:5px; 
    	margin-top:0px;
    	color:#fff; 
    	transition: background-color 0.5s ease;
    	background-color:#333;
    }
    
    #projectDrop a:hover{
    
    	background-color: #75ACFF;
    
    }
    
    #projectDrop ul{
    	background: #fff; 
        background: rgba(255,255,255,0);
        list-style: none;
        position: absolute;
        display: none; 
    }
    Sorry about the extent of it all but I just can't seem to figure out where the problem is. Thanks if you can help!

  2. #2
    Join Date
    Mar 2009
    Posts
    523
    The main problem is that your variable myProj is not what you think it is.

    Code:
    function toggleDrop() {
    
       var myProj = document.getElementsByClassName('project');
       //myProj is a nodeList, which is similar to an array
    
       var displaySetting = myProj.style.display;
        //myProj doesn't have any 'style', but its individual elements do
       
    //You need a loop to go through the individual elements
    
       if (displaySetting == 'block') { 
          //It's visible - hide it
          myProj.style.display = 'none';
          
    	  }else { 
          // It's hidden - show it
          myProj.style.display = 'block';
         
        }
    }
    As in:

    Code:
    function toggleDrop() {
       var i, len, el;
       var myProj = document.getElementsByClassName('project');
       len = myProj.length;
    
       for(i = 0; i < len; i++){
            el = myProj[i];
           if( el.style.display != 'none){
                el.style.display = 'none';
           }
           else{
              el.style.display = 'block';
          }
    }

  3. #3
    Some advice:

    1) display:none can prevent screen readers from ever letting users at whatever it is you're hiding.

    2) if you only need this section open when focused and don't mind others closing when you open it, you don't need to waste JS on it anymore unless you really need it to 'work' in IE9/earlier -- my solution there is to make the CSS only target modern browsers using a media query.

    3) you might want to learn a bit more about selectors so you aren't wasting markup with "classes for nothing" like on that "project" class.

    So first the markup:
    Code:
    <ul id="projectDrop">	
    	<li id="top">
    		<a href="#top" class="showTarget"></a>
    		<a href="#" class="hideTarget"></a>
    		Our Projects
    		<ul>
    			<li><a href="#">Project 1</a></li>
    			<li><a href="#">Project 2</a></li>
    		</ul>
    	</li>
    </ul>
    Then get a load of this, controlling it from the CSS:

    Code:
    @media (min-width:1px) { /* cute trick to target modern browsers only */
    
    	#projectDrop>li {
    		overflow:hidden; /* will hide aPo child */
    		position:relative; /* to set child aPo relative to this */
    	}
    
    	#projectDrop>li .hideTarget,
    	#projectDrop>li:target .showTarget {
    		display:none;
    	}
    	
    	#projectDrop>li:target .hideTarget, 
    	#projectDrop>li .showTarget {
    		display:inline;
    	}
    
    	#projectDrop>li ul {
    		position:absolute; /* remove from flow */
    	}
    	#projectDrop>li:target ul {
    		position:relative; /* back in flow, will show as content */
    	}
    
    	#projectDrop .hideTarget:before {
    		content: "Hide";
    	}
    	
    	#projectDrop .showTarget:before {
    		content: "Show"
    	}
    
    }
    Legacy browsers (IE 8 and earlier) will have these elements open all the time -- OH WELL. They should be thankful we give them content at this point.

    Even if I was doing it via js, I'd be doing a class swap and the above hide/show technique, instead of playing with style directly. Would give you more control over it and the possibility of CSS3 transitions. If I have time later and remember I'll belt out an example of that approach as well.

  4. #4
    Join Date
    Jun 2014
    Posts
    21
    I'm really struggling to understand this and I don't want to include code I don't understand as I'll never learn.

    Why do I need to determine the length of myProj?
    Is it just for the loop?

    el = myProj[i] - so that's looking for i as it increments up to-- whatever the length is and then assigning the value to el. I don't understand.

    Thanks for the reply though!

  5. #5
    Join Date
    Mar 2009
    Posts
    523
    Why do I need to determine the length of myProj?
    Is it just for the loop?
    Yes.

    And the loop makes sure that it will do the procedure on every element that is of class "project." It doesn't matter how many are in the page (if any). If any are there the references to them will appear in the "myProj" nodelist.

    You can also do the loop as so, omitting the use of the "el" variable, but this is less efficient:

    Code:
    function toggleDrop() {
       var i, len;
       var myProj = document.getElementsByClassName('project');
       len = myProj.length;
    
       for(i = 0; i < len; i++){
           if( myProj[i].style.display != 'none'){
                myProj[i].style.display = 'none';
           }
           else{
              myProj[i].style.display = 'block';
          }
    }
    And if you really want to simplify it further but make it yet more inefficient:

    Code:
    function toggleDrop() {
       var i;
       var myProj = document.getElementsByClassName('project');
    
       for(i = 0; i < myProj.length; i++){
           if( myProj[i].style.display != 'none'){
                myProj[i].style.display = 'none';
           }
           else{
              myProj[i].style.display = 'block';
          }
    }
    --and I just noticed that in my original reply I omitted a single quote mark at the end of the first "none" Sorry about that.

  6. #6
    Quote Originally Posted by PoxMoy View Post
    as I'll never learn.
    *SIGH* you might want to consider doing something other than working on websites then.

  7. #7
    Join Date
    Jun 2014
    Posts
    21
    @deathshadow, what's wrong with wanting to understand something before just copying and pasting it into your project?

  8. #8
    You made it sound like you don't want to understand it. If I misinterpreted your post, my bad... but the "I never will"?

  9. #9
    Join Date
    Oct 2013
    Posts
    609
    Quote Originally Posted by PoxMoy View Post
    I don't want to include code I don't understand as I'll never learn.
    Let me translate:
    Code:
    function PoxMoy() {
    	if (understand_the_posted_code.value == 'no'){
    		alert('I want to learn before deploying');
    	}
    }

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles