SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 27
  1. #1
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    My toggle script doesn't work the first time

    Hey guys,

    I've been making this site...
    I have a comment form on each page which is hidden by the css (display:none).
    I use this script :
    Code:
    function ads(div) 
    {
    obj=document.getElementById(div);
    obj.style.display=(obj.style.display=="none")? "block" : "none";  
    }
    to toggle it. (It's not an ad of course - it's called 'ads' because I use the same script on a different page to toggle an ad box (which is also not really an ad box - it's just a demo)).

    The first time you click the box to show the form (the box is at the bottom of the page), nothing happens. After that, everything is great. I feel stupid because I've actually had this same problem before and I fixed it, but I don't remember how I did it.

    Anyone know what's going on here?

    Thanks in advance.

  2. #2
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would imagine that the first time you call your function, obj.style.display is empty, so it becomes "none", the second time "block".

    Try it backwards, ie:
    obj.style.display=(obj.style.display=="block")? "none" : "block";

  3. #3
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That would make sense if it were true. The display style is set in the css as I said - display:none. I even tried it the other way, like this :
    Code:
    function ads(div) 
    {
    obj=document.getElementById(div);
    obj.style.display=!(obj.style.display=="block")? "block" : "none";  
    }
    so that if the style weren't "block" it would become "block". I figure if it thinks the style is empty then it's fair to say that display does not equal "block" and so it should appear on click, but it doesn't. Have a look at this page . This uses the same script in the top-right corner and it works fine.

    My purple-faced brothers and I are confused...

  4. #4
    SitePoint Zealot
    Join Date
    Dec 2004
    Location
    Finland
    Posts
    103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    IIRC element.style returns only inlined properties. Use this instead:
    Code:
    obj.style.display=(obj.style.display!="block")? "block" : "none";
    That way empty string/'undefined' forces "block" too.


    Edit: Rereading your previous message, you already tried that - it should work. If you use IE for testing be sure to exit your page and empty your cache between tests. Simple reload doesn't necessarily refresh linked javascript.

  5. #5
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sounds good, but... I'm afraid it didn't work.

    You know, the thing that really confuses me is that it works fine in that other place I pointed out.

    OK, though - now I'm REALLY confused. I replaced the toggle script with this script which I was sure would work :
    Code:
    function show(div) 
    {
    document.getElementById(div).style.display="block";
    }
    but it did nothing.

    The only difference I can see between this case and the other one (mentioned above) is that the html for this is echoed by php. I'd be very surprised if that was the problem, but is that possible?

  6. #6
    SitePoint Zealot
    Join Date
    Dec 2004
    Location
    Finland
    Posts
    103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It really seems like cache problem, with Opera both your second solution and my solution works if I refresh the cached copy.

  7. #7
    SitePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I believe if you play a bit with this, all will be revealed:

    Code:
       <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
        <html>
        <head>
        <title>Untitled</title>
        <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
        <script type="text/javascript">
        function getStyle(targ){
          if(targ.currentStyle){  //code for IE
        	alert(targ.currentStyle.display);
          }else{  //code for W3C-spec-compatible
        	var targ_sty=document.defaultView.getComputedStyle(targ,'');
        	alert(targ_sty.getPropertyValue('display'));
          }
        }
        </script>
        </head>
        <body>
        <div 
          onclick="alert(this.style.display);" 
          style="height:100px;width:300px;background:#ded;">
        </div>
        
        <div 
          onclick="alert(this.style.display);" 
          style="display:block;height:100px;width:300px;background:#dde;">
        </div>
        
        <div onclick="getStyle(this);" 
          style="height:100px;width:300px;background:#ded;">
        </div>
        
        </body>
        </html>
    In light of this, you might wish to try this, in place of your original:
    obj.style.display=(obj.style.display=="none"||obj.style.display=="")? "block" : "none";

    Though, obviously, that's a bit of a hack (a potentially simpler and more efficient hack, but a hack nevertheless).
    Last edited by JVLB; Jan 5, 2005 at 10:09.

  8. #8
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    jorigami,
    I'm afraid I have to disagree - it can't be a cache problem. I emptied my caches in both Firefox and IE and tried again, but the same thing was happening in both. Then I found another strange thing - with the solution that I was sure would work, IE said there was an error when I clicked the button.

    JVLB,
    Thanks for your input, but I'm afraid it's a little too cryptic for me. I could kind of see what was going on, but - maybe I'm a bit slow - I couldn't see what my solution is. I think, in theory, jorigami's solution should work because, as I said, if the style is not set, it should be set as "block" by the onclick event.
    Do you think you could just tell me what my solution is (if you know)? I'd appreciate that.
    Edit:

    We seem to have cross-posted. I'll try that (your edit) out now. (Though I wonder why you call it a hack?)

    Thanks again.

  9. #9
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK. I did that. No joy I'm afraid.

  10. #10
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, put on your logic boots ("Boots?", you ask, "Not a thinking cap?" Thinking caps are a bit passe, you see, and when I start lecturing on logic, it's probably a good time to have your boots on, so 'logic boots' it is.) and off we go.

    As the first and second divs demonstrate, jorigami is correct, the style.display property only holds either inline style rules or script-set style rules.

    The last div demonstrates, through calling the function getStyle(), the two techniques by which you can read the style currently applied to an element, regardless of whether the rules come from an internal style sheet, an external style sheet, an inline style, or a script-spawned attribute.

    Note that I added a potential kludge-solution to my previous post. I haven't tried it, but you might.

  11. #11
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey guys,
    I'm really sorry, but I've been an idiot.
    Yesterday, I screwed up my js file and had to redo it. I made a different file and uploaded that. Tonight I've been making changes to the old file.
    I've just done this :
    Code:
    obj.style.display=!(obj.style.display=="block")? "block" : "none";
    and it works fine.
    Really sorry to have wasted your time.


    ...

    (Sorry again)

  12. #12
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You might find this syntax a hair more efficient, since it only has to make a logic determination once:
    Code:
     obj.style.display=obj.style.display!="block" ? "block" : "none";

  13. #13
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very logical

    Thanks for your help.

  14. #14
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Bear in mind, that approach is still a bit of a hack because we're not basing execution on the actual currently applied style, but I doubt it should be considered a significant issue.

    The only likely case where it could become an issue is: If you changed the display value in your stylesheet to block, the script would be broken in a similar, though opposite, fashion to what inspired your original post.

  15. #15
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Even though you kind of explained there, I still don't see why you call this code a hack. Why does it need to be based on the current style? If I want it to be "block", does it really matter what the current style is? The point is that it will become "block" with this code. To me, it seems a pretty clean and efficient way of doing it. (Bear in mind that I'm really no expert in javascript so I don't know what is considered a hack and what isn't or the reasons for it).

  16. #16
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's a hack because it can easily be broken if just minor modifications are made to the page's CSS. Robust code allows for such possibilities and eliminates the potential need for a script rewrite each time the page gets modified. The hack is a one-time solution that will only work if nothing about the page changes and it is not portable to another situation.

    Using the hack, if the element were modified to already have display:block set by a style sheet or it is the default for the element, the script would appear not to work the first time. In other words, it would require a rewrite back to code like you first posted. If we used the actual applied style to make the determination, what the style was or where it came from wouldn't matter, the script would work reliably, regardless.

  17. #17
    SitePoint Zealot
    Join Date
    Dec 2004
    Location
    Finland
    Posts
    103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One way to work around that is to use classes instead of style properties. If JavaScript switches between two (or more) classes everything can be changed from CSS. See this page for example. It uses multiple classes for body tag so it's more complicated than what you need, but it should give you the idea. Body tag has classes defined, so there is no problem with initial empty style.className, and that also gives it know default style.

  18. #18
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This demonstrates a generic function for switching display between none and block. Whatever element's id is passed to it will be processed and whatever display status it has initially, it will be toggled between none and block.

    Code:
     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
     <html>
     <head>
     <title>Untitled</title>
     <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
     <style type="text/css">
     #divOne{display:none;height:300px;width:400px;background:#dde;}
     </style>
     <script type="text/javascript">
     function setDispBlkNon(targId){
       var targ=document.getElementById(targId);
       var targ_var="";
       var targ_sty="";
       if(targ.currentStyle){  //code for IE
     	targ_var=targ.currentStyle.display;
       }else{  //code for W3C-spec-compatible
     	targ_sty=document.defaultView.getComputedStyle(targ,"");
     	targ_var=targ_sty.getPropertyValue("display");
       }
       targ_var!="block" ? targ.style.display="block" : targ.style.display="none";
     }
     
     </script>
     </head>
     <body>
     <button onclick="setDispBlkNon('divOne');">see / no-see</button>
     <div id="divOne">
     </div>
     </body>
     </html>

  19. #19
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    jorigami,
    Yes, I was actually doing that before - with the class names - but I felt it was more efficient to not have to add the class names to the html, so I changed it to this script which changes the display value directly.

    JVLB,
    I see. Very interesting - and useful too. I like the script I use because it's so short, but I see how this is more efficient in terms of working every time.

    Now I have a small dilemma. See, I've been putting together that site that I've had the problem with recently and it's just things like this - little useful things for web design. Do I stick with what I have now, which is (I can understand your explanation) a hack - nice and short, but a hack, as you said - or do I ask you if you mind me taking this code and putting it up? I guess, if that's OK with you, it would be good to give you credit for this. If this is actually common practice and not really written by you (I have no idea - as I said, I'm no expert), then let me know.

    I loook forward to hearing what you think.

  20. #20
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're more than welcome to put the code up. I wrote it from scratch, but there is nothing special about it so don't feel any need to attribute it.

    As long as the hack does the job you want and you are comfortable with its limitations, I wouldn't worry about using it.

  21. #21
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK. Thanks a lot.
    I think I will use your code though because as I said before, I was using the same code for two different things and then I had to re-write it for this thing so I have two different functions on my sheet now. Best to have the one, eh?

  22. #22
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just a tip: Usually, the advantages of shared code are best exploited using an external .js file. Load once, use often.

  23. #23
    Winemaster bronze trophy BonRouge's Avatar
    Join Date
    Oct 2004
    Location
    Sendai, Japan
    Posts
    2,417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Erm... yeah - that's what I do. Check the site and you'll see.

  24. #24
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's an even more generic function that will toggle any style attribute on the element on which it's called:

    Code:
        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
        <html>
        <head>
        <title>Untitled</title>
        <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
        <style type="text/css">
        #divOne{display:block;height:300px;width:400px;background:#dde;}
        </style>
        <script type="text/javascript">
        function styTog(targ_id,sty_attr,set_val){	// parameter variables are: id of target element;  
          var targ=document.getElementById(targ_id);  // style attribute to toggle; 2nd state attribute value
          var targ_var="";
          var targ_sty="";
          if(targ.currentStyle){  //code for IE
        	targ_var=targ.currentStyle[sty_attr];
          }else{  //code for W3C-spec-compatible
        	targ_sty=document.defaultView.getComputedStyle(targ,"");
        	targ_var=targ_sty.getPropertyValue(sty_attr);
          }
          targ_var!=set_val ? targ.style[sty_attr]=set_val : targ.style[sty_attr]="";
        }
        </script>
        </head>
        <body>
        <button onclick="styTog('divOne','display','none');">see / no-see</button>
        <div id="divOne">
        </div>
        </body>
        </html>
    Note that the two different "standards" use different names for many attributes, like the JavaScript "backgroundColor" used by IE, versus the CSS "background-color" used in the W3C syntax to describe the same thing. This limits the portability of this simple approach. Also, the use of an attribute value of "" to trigger reversion to the initial setting is a browser convention, not a standard, and appears to be subject to some interpretation.
    Last edited by JVLB; Jan 6, 2005 at 22:05.

  25. #25
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, I was bothered by only providing a partial solution, so here's a more complete generic CSS attribute toggle script. I've tested it on IE, Moz, and O. It works with every attribute I've tried. The rgb bit for Moz is a bit of a hack, but a necessary hack, I fear.

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
     <html>
     <head>
     <title>Style Toggling Script 1/7/05</title>
     <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
     <style type="text/css">
     #divOne{display:block;height:300px;width:400px;background:#ddddee;}
     #divTwo{height:100px;width:100%;text-align:center;padding-top:2em;}
     #divThree{height:100px;width:300px;background:#ccaaaa;margin:auto;}
     </style>
     <script type="text/javascript">
     function styTog(targ_id,sty_attrJ,sty_attrC,set_val){  
       var targ=document.getElementById(targ_id);
       var targ_stat="";
       var targ_sty="";
       if(targ.currentStyle){  //code for IE
     	targ_stat=targ.currentStyle[sty_attrJ];
       }else{  //code for W3C-spec-compatible
     	targ_sty=document.defaultView.getComputedStyle(targ,"");
     	targ_stat=targ_sty.getPropertyValue(sty_attrC);
     	if(targ_stat.indexOf("rgb")!=-1){ // code to accommodate Mozilla's rgb color model
     	  var sv_arr=[set_val.slice(1,3), set_val.slice(3,5), set_val.slice(5)];
     	  for(var i=0;i<3;i++){
     		sv_arr[i]=parseInt(sv_arr[i],16);
     	  }
     	  set_val="rgb("+sv_arr[0]+", "+sv_arr[1]+", "+sv_arr[2]+")";
     	}
       }
       targ_stat!=set_val ? targ.style[sty_attrJ]=set_val : targ.style[sty_attrJ]="";
     }
     </script>
     </head>
     <body>
     <!--  the four parameters being passed to the styTog() function are: the target element's id,
     	  the JavaScript attribute name, the CSS attribute name, and the toggle value for the second state 
     	  (note that the toggle value for a color must be in six-digit hex notation) -->
     <button onclick="styTog('divOne','visibility','visibility','hidden');">block see / no-see</button>
     <button onclick="styTog('span1Div2','display','display','none');">inline see / no-see</button>
     <button onclick="styTog('divThree','marginTop','margin-top','40px');">vertical shift</button>
     <button onclick="styTog('divThree','backgroundColor','background-color','#00bbee');">color shift</button>
     <div id="divOne">
       <div id="divTwo">
     	Text, with a<span id="span1Div2">n inline span, as the</span> target.
       </div>
       <div id="divThree">
       </div>
     </div>
     </body>
     </html>
    Last edited by JVLB; Jan 7, 2005 at 23:53.


Bookmarks

Posting Permissions

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