SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    SitePoint Addict
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    377
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    passing values with this keyword using setTimeout

    I need some more advice on using the this keyword and passing it through a setTimeout thing.

    I'm new to this and made up a simple script to make things clear.

    This following script changes style when mousing over a paragraph:
    Code:
    <html>
    <head>
     <script type="text/javascript">
     
       function changeNew(){
         this.style.borderBottom = 'dashed 1px #000000';
       }
     
        function changeOld(){
         this.style.borderBottom = 'solid 3px #0099FF';
       }
    
    
        function doMyFunc(){
        var thePars = document.getElementsByTagName('p');
        
        for (var i=0; i<thePars.length; i++){
        thePars[i].onmouseover = changeNew;
        thePars[i].onmouseout = changeOld;
        
        }
       }
     
    window.onload = doMyFunc;
     
    </script>
    <title>coffee</title>
    </head>
    <body>
     
     <p>test 1 </p>
     <p>test 2 </p>
     <p>test 3 </p>
     <p>test 4 </p>
     
    </body>
    </html>
    I pass the value of the referred paragraph to a new function and it gets loaded in the new function with the "this" keyword.
    Works okay.

    But then I want to use setTimeout to delay the function.
    How can I pass the value of the this keyword through that setTimeout ?

    With this code it doesn't work out:
    Code:
     function firstChange(){
       setTimeout("changeNew",2000);
    }
    
    function secondChange(){
      setTimeout("changeOld()",3000);
    } 
    
    // the doMyFunc events are linked to these functions above right now
    
        function doMyFunc(){
        var thePars = document.getElementsByTagName('p');
        
        for (var i=0; i<thePars.length; i++){
        thePars[i].onmouseover = firstChange;
        thePars[i].onmouseout = secondChange;
        
        }
       }
    Does someone have a good tutorial around this issue?

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,678
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    As the timeout events run in a separate execution context, the this keyword will be set to the window object.

    You can deal with that by passing the this keyword to a function that is called, so that you can then set that as the calling context.

    Something like the following should work.
    Code javascript:
    function firstChange(){
        setTimeout(function (context) {
            return function () {
                changeNew.call(context);
            };
        }(this), 2000);
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    SitePoint Addict
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    377
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok I see.

    And if, for example, you want to let these 2 styles change a few times after each other, for creating a blinking effect. How do you put this in a loop?

    It's not repeating the loop with this one:
    Code javascript:
      function changeStyles(){
     
    var interval = 500;
    for (var t = 0; t<5; t++){
     
        setTimeout(function (context) {
            return function () {
                firstStyle.call(context);
            };
        }(this), interval);
     
        setTimeout(function (context) {
            return function () {
                secondStyle.call(context);
            };
        }(this), interval*2);    
     
      }
    }

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,678
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by bulevardi View Post
    And if, for example, you want to let these 2 styles change a few times after each other, for creating a blinking effect. How do you put this in a loop?
    Yes, that's a common problem that comes about from not quite understanding what's occurring.

    When the timeouts have been set up and the loops are completed, the timeouts run the appropriate functions which use the variables as they are at the time when those functions are run, not when they were set up.

    If you want the variable from the loop to be retained, you will need to pass it to the function as well.

    This means not just passing the this keyword to the function as context, but also passing interval to the function as interval.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  5. #5
    SitePoint Addict
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    377
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, still don't understand what I have to do (as a javascript noob)

    I rewrote it all and have it like this now, but it still doesn't work.
    Do I still have to pass the interval like this aswel?

    Code JavaScript:
     
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
     
    <script type="text/javascript">
    function doEffect(){  
    var obj;  
    var TimerID; 
    var TimerIDTwo;
    var thePars = document.getElementsByTagName('p');
     
        for (var i=0; i<thePars.length; i++){
        thePars[i].onmouseover = doFlip;
        thePars[i].onmouseout = stopFlip;
        }
     
     
     
    function doFlip(){
     obj = this;
      for(var j=0; j<20; j++){
      TimerID = setTimeout(function(){changeStyle(obj)},100);
      TimerIDTwo = setTimeout(function(){changeStyleTwo(obj)},500);
      return true;
      }
    }
     
     
    function stopFlip(){
     obj = this;
     TimerID = setTimeout(function(){changeStyleTwo(obj)},100);
    }
     
    function changeStyle(){
    obj.style.borderBottom = 'solid 3px #0099FF';
    }
     
    function changeStyleTwo(){
    obj.style.borderBottom = 'dashed 2px #669944';
    }
     
    }
     
    window.onload = doEffect;
     
     
    </script>
    <title></title>
    </head>
    <body>
     
     
     <p>test 1 </p>
     <p>test 2 </p>
     <p>test 3 </p>
     <p>test 4 </p>
     
    </body>
    </html>

  6. #6
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,678
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by bulevardi View Post
    Ok, still don't understand what I have to do (as a javascript noob)

    I rewrote it all and have it like this now, but it still doesn't work.
    That's odd, what you posted appears to work for me in Chrome, Firefox and IE.

    What seems to be the problem?
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  7. #7
    SitePoint Addict
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    377
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm on a computer with IE7 only at the moment.
    Can't verify other browsers right now.

    The script only changes the style 1 time instead of 20 times like I hoped with this:
    for(var j=0; j<20; j++){

  8. #8
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,678
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Pardon, I misunderstood that the timeout event wasn't working as expected.

    One possible way to achieve it is to have each timeout function call the other timeout function.
    When the mouseout event occurs you can then clear the timeout event and set the style to finish things off.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  9. #9
    SitePoint Addict
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    377
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Great ! Works out super!
    Thanks for the advice...

    I have it like this right now to make cool buttons:
    Code JavaScript:
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
     
    <script type="text/javascript">
    function doEffect(){  
    var obj;  
    var TimerID; 
    var interval = 100;
    var thePars = document.getElementsByTagName('p');
     
        for (var i=0; i<thePars.length; i++){
        thePars[i].onmouseover = startFlip;
        thePars[i].onmouseout = stopFlip;
        }
     
     
    function startFlip(){
     obj = this;
      TimerID = setTimeout(function(){styleOne(obj);},interval);
    }
     
    function styleOne(){
    obj.style.border = 'solid 3px #0099FF';
    obj.style.width = '100px';
    obj.style.height = '49px';
      TimerID = setTimeout(function(){styleTwo(obj);},interval);
    }
     
    function styleTwo(){
    obj.style.border = 'dashed 2px #669944';
    obj.style.width = '100px';
    obj.style.height = '50px';
      TimerID = setTimeout(function(){styleOne(obj);},interval);
    }
     
     
    function stopFlip(){
    clearTimeout(TimerID);
    obj.style.border = 'dashed 2px #669944';
    obj.style.width = '100px';
    obj.style.height = '50px';
    }
     
     
    }
     
    window.onload = doEffect;
     
     
    </script>
    <title></title>
    <style>
    p { display: inline; width: 100px; height: 50px; border: solid 2px #0099FF; margin: 5px;
    }
    </style>
    </head>
    <body>
     
     
     <p>test 1 </p>
     <p>test 2 </p>
     <p>test 3 </p>
     <p>test 4 </p>
     
     
     
    </body>
    </html>


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
  •