Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    New to the CF scene
    Join Date
    Dec 2004
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts

    setTimeout("this.function") passing instance method

    I'm using setTimeout() to animate an image moving across the screen to the edge of the page. When I call setTimeout() and pass it a this.function as the function to execute it won't do it & throws and err saying it's not a function. I've also tried passing a reference to an object and it didn't seem to like that either.

    I've extended the Image class adding several prototype methods and proerties of my own. I wanted to call the Image instance's animateLeft method repeatedly & delayed so that it looks as though the image moves across the screen to the edge.

    the _P functions are used to extend the Image object and they become the instance methods sans '_p' : animateLeft_p() can then be called using "this.animateLeft()"

    Here's the code:
    PHP Code:
        // Params that control the speed images animate left and up
        
    var moveIncr 1;
        var 
    timeInt 10;

         
    //instance method of Image to animate the image to the left edge of screen
         
    function animateLeft_p()
         {
            
    this.lcounter 1;
            
    this.startX this.getLeft();
            
    this.movedSum 0;

            while(
    this.startX this.movedSum 0)
            {
                
    this.movedSum this.movedSum moveIncr;
                
    ///************Below is the problem call *************
                
    setTimeout('this.moveLeft(1)',this.lcounter*timeInt);
                
    this.lcounter =this.lcounter+1;
            }
         }
         function 
    moveLeft_p(pxls)
         {
            
    this.style.left=parseInt(this.style.left) - pxls;
         }
         function 
    getLeft_p()
         {
            return 
    parseInt(this.style.left);
         }

        
    //add the methods & properties to each subsequent image object created
        // so I can call using someImage.animateLeft() for example
         
    Image.prototype.animateLeft animateLeft_p;
         
    Image.prototype.moveLeft    moveLeft_p;
         
    Image.prototype.getLeft     getLeft_p;
         
    Image.prototype.lcounter    1;
         
    Image.prototype.movedSum    0;
         
    Image.prototype.startX      null;

       
    //Now create the image objects
         
    projects = new Image(100,100);
         
    projects.src "http://www.bytality.com/prog_arch/images/projects_100x100.jpg";
    </SCRIPT> 
    Here's the HTML code:
    PHP Code:
    <IMG src="images/blue_logo_100x100.jpg" style="position:absolute;left:100;top:0;" height="100" id="bluelogo" width="100" onclick="this.animateLeft();"
    I had been using public vars to do this, and that worked for a single image, but when I move multiple images at once, they share the control variables and don't move the entire distance correctly.

    Anyone know how I can make the code work using setTimeout() function or another function?

  • #2
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    You'd need to use a global object reference in an anonymous function, because setTimeout is not local.

    As in: setTimeout(function(){//object.method(arg); etc...}, milliseconds);

    Edit: Well, sort of, because local variables can be used, but the function itself is seperate, so "this" is in a different context--I meant.
    Last edited by codegoboom; 12-16-2004 at 07:31 PM.
    *this message will self destruct in n-seconds*

  • #3
    New to the CF scene
    Join Date
    Dec 2004
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Yeah, but when I use a global var and move multiple images, they simultaneously share that global var and they don't move correctly.

    More than one starts modifying the control vars at the same time and the math goes haywire.

    Is there some why I can pass the string name without using a global var?

  • #4
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    The problem is that setTimeout and setInterval are not local methods of your object, they're methods of the window, therefore "this" inside a timer is a reference to window.

    But there is a little trick you can do - create a scope-global reference to "this" inside the constructor, which you'll then be able to refer to from inner functions. This kind of thing:
    Code:
    //some object constructor
    function someObjectConstructor()
    {
    	//create a test variable
    	this.test = 'hello world';
    
    	//create a global [within this scope] reference to this
    	var self = this;
    	
    	//start an anonymous timer 
    	this.timer = window.setInterval(function()
    	{
    		
    		alert(self.test);	//"hello world"
    		alert(self.timer);	//a reference to this timer
    	
    	}, 5000);
    };
    Last edited by brothercake; 12-16-2004 at 08:30 PM.
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  • #5
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Things can be kept seperate when assigned as object properties. Each new call could check for a pre-existing prop, create a new one if not found, or modify the cycle accordingly.

    That was not to discount the above point, btw...
    Last edited by codegoboom; 12-16-2004 at 08:38 PM.
    *this message will self destruct in n-seconds*

  • #6
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by codegoboom
    That was not to discount the above point, btw...
    It doesn't The principle is the same with what I suggested, except you haven't had to pollute the global scope with another variable
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  • #7
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Actually, I had something else in mind when mentioning that, but it was sort of a tangent, I guess, looking back...
    *this message will self destruct in n-seconds*

  • #8
    New to the CF scene
    Join Date
    Dec 2004
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by codegoboom
    Things can be kept seperate when assigned as object properties. Each new call could check for a pre-existing prop, create a new one if not found, or modify the cycle accordingly.

    That was not to discount the above point, btw...
    I tried using an object property, except I still couldn't figure out a way to pass the particular object without storing to a global var for use with setTimeout(). You can't use a this reference at all and any time I use a global, multiple images will be moving at once and they share the global var and it screws everything up!

    How come my prototyped custom object properties aren't seeming to be protected within the Image object? Does that just add a reference to the global function rather than nesting it within the object for var protection, or didn't I do it right?

    Using brothercake's hint, I tried creating an new image_wrapper() object that created an internal image object when the wrapper object was constructed. That way I could add the object.self reference to my custom object rather than extending the standard Image object. My problem there came in using the image_wrapper for calling. I couldn't call Image.moveLeft() from the HTML because the functions are now owned by the image_wrapper object not the image object which meant I couldn't use 'this' in the moveLeft() to move the image. How can I associate the HTML image with my image_wrapper object instead of a standard Image object? If I could do that it may work with some tweaking.... maybe.

    Does that make sense to anyone?

  • #9
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I dunno.
    A prototype for Image is undefined in IE, btw.
    Here's how I might set that type o' thing up...
    Code:
    <body>
    <script type="text/javascript">
    
    var active = [];
    
    function animateLeft(elem, indx)
    {
    	if(typeof active[indx] != "undefined")
    		clearTimeout(active[indx]);
    	var moveIncr = 5;
    	var startX = parseInt(elem.style.left);
    	(function moveLeft()
    	{
    		if((startX -= moveIncr) >= 0)
    		{
    			elem.style.left = startX + "px";
    			active[indx] = setTimeout(moveLeft, 10);
    		}
    		else
    			elem.style.left = "0px";
    	})();
    }
    </script>	
    
    <IMG src="images/blue_logo_100x100.jpg" style="position:absolute;left:100;top:0;" onclick="animateLeft(this, 0);">  
    <IMG src="images/red_logo_100x100.jpg" style="position:absolute;left:100;top:101;" onclick="animateLeft(this, 1);"> 
    <!-- etc. --> 
    </body>
    Last edited by codegoboom; 12-18-2004 at 05:23 PM.
    *this message will self destruct in n-seconds*


  •  

    Posting Permissions

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