...

View Full Version : setTimeout and objects again :(



david_currey
06-02-2004, 02:47 AM
hi,

I am pretty sure i got this code from here, most probably from liorean, but i can't find the thread. Anyway, the code is great and does exactly what I want, but blow chunks in safari.....

function C(){
this.a=function(i){
var me=this;
alert(i)
//confirm([i,me.a]) && setTimeout (function(){me.a(i+1)},1000);
setTimeout (function(){me.a(i+1)},1000);
};
}

var t=new C;
t.a(0);

I have a constructor ( like C here) that I create multiple instances of (like t here)
So what I need is a way to call my anim function over and over when they are new instances of my constructor ( i hope that is right terminology ).

does anyone else really hate safari of is it just me :)

cheers,

dave

david_currey
06-02-2004, 06:33 AM
A better (but simplified) example of what i am up to:

the code below works for me in gecko but I need somthing like this that works in safari ( i am assuming it works in explorer )

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>obj_sto</title>
<style type="text/css">
div
{
position: relative;
width:440px;
height: 48px;
border: 1px solid red;
white-space: nowrap;
}

</style>
<script type="text/javascript">
// object constructor
function dcTweenObject(readid,elmid,prop,start,end,duration) {
// define object's properties
this.elm=document.getElementById(elmid)
this.property=prop
this.startpropval=start;
this.endpropval=end;
this.duration=duration;
this.timeout=100;
this.frames=duration/this.timeout;
this.easing=(this.endpropval-this.startpropval)/this.frames;
// define object's methods
this.a=this.a=function(i){
var me=this;
me.num=i;
var d=i*this.easing;
this.elm.style[this.property]=d+'px'
if(me.num>this.frames) return;
this.timer=setTimeout(function(){me.a(me.num+1)},this.timeout);
}
}
window.onload=function() {
t0=new dcTweenObject('r0','adiv0','left' , 0 , 100 , 500 );
}
</script>
</head>
<body>
<div onmouseover="t0.a(0);" id="adiv0">
run t0.a(0)
</div>
</body>
</html>

Garadon
06-02-2004, 07:31 AM
setTimeout(function(){me.a(me.num+1)},this.timeout); <-- that as far as I understand would send the function a.

setTimeout(me+".a("+(me.num+1)+");",this.timeout); <-- this is how I write it usualy works.

david_currey
06-02-2004, 12:52 PM
Garadon, I tried what you suggested, and it makes sense and should work ( sending a string to setTimeout ) but no, in this case it does not .......

If I understand what I have read about my difficulties, it is that all the variables dont exist anymore at the time the setTimeout is run, but I thought I had that covered by the function being 'inside' the constructor.

I am thinking that the thread I started should have been " I want to make a tweening function available to instances of objects - how do I make the looping and iteration parts?"

thanks though,

dave

MikeFoster
06-02-2004, 03:25 PM
function C(limit)
{
var me = this;

this.a = function(i)
{
window.status = i;
setTimeout( function(){if (i < limit) me.a(i + 1);}, 1000 );
}
}

var t = new C(10);
t.a(0);

david_currey
06-02-2004, 05:15 PM
I think I have worked out somthing else to do with my nightmare:

Mike's code above at first did not work - but then I tried it in the "latest" safari (the one that only runs on os X 10.3) and it did work. For compatabilities sake I still run the old version (os X 10.2).

So my question is :

a) How can I set a delay between my animation's frames in older safari browsers?

b) Should I just ditch the constructor instance stuff and use a "regular" function?

c) Why do I have to spend so much time on somthing simple , just because Apple want to sell mp3s(or aacs or whatevers)?

uggh!

d) Should I just give up?

thanks though, I like the conditional in the setTimeout :)

MikeFoster
06-02-2004, 06:16 PM
Just curious... in this demo (http://cross-browser.com/x/examples/floater.html), does the menu 'slide' vertically in OS X 10.2 ?

david_currey
06-02-2004, 06:26 PM
Just curious... in this demo (http://cross-browser.com/x/examples/floater.html), does the menu 'slide' vertically in OS X 10.2 ?

hi,

yes that works fine [safari on 10.2]

MikeFoster
06-02-2004, 06:32 PM
Thanks! :)

With all the recent interest in 'closures', it would be interesting to know why it didn't work in OSX 10.2. Perhaps the following would help to debug it:


function C(limit)
{
var me = this;
this.name = 'myClosureTest';
this.a = function(i)
{
alert('method a()\n\n' +
'me: ' + me + '\n' +
'me.name: ' + me.name + '\n' +
'limit: ' + limit + '\n' +
'i: ' + i);
}
this.b = function(i)
{
setTimeout( function() {
alert('delayed method b()\n\n' +
'me: ' + me + '\n' +
'me.name: ' + me.name + '\n' +
'limit: ' + limit + '\n' +
'i: ' + i);}, 1000);

}
}

var t = new C(10);
t.a(0);
t.b(1);

david_currey
06-02-2004, 07:20 PM
Thanks! :)

With all the recent interest in 'closures', it would be interesting to know why it didn't work in OSX 10.2. Perhaps the following would help to debug it:



hi, thanks for that code, I bunged it into "that" browser and recieved the alert below:

me: [object Object]
me.name: myClosureTest
limit: 10
i: 0

just the one.....is that what I was supposed to do?

liorean
06-02-2004, 07:23 PM
I believe the problem lies in a deficiency of the Safari JavaScript engine (KJS) to support closures.

MikeFoster
06-02-2004, 07:26 PM
It seems that setTimeout(function(){...}, timeout) did not work. This feature is only supported by later Javascript versions (i'm not sure what version, i'll have to look it up). I wonder what version of js is supported by that browser?

david_currey
06-02-2004, 07:45 PM
And I wonder what on earth I can do to make a website. I really don't care what the code looks like, should I just drop all this contructor, instance, squarebracket stuff and go back to using millions of separate regular functions :(

I can just about argue my way round not supporting extra js in IE5 mac (which doesn't work either) but not safari.

MikeFoster
06-02-2004, 11:28 PM
Oh there will always be incompatibilities between browsers ;)

You're application probably doesn't 'require' using closures. But it sounds like the closure in my test code above did work. If you will, try it again and comment-out this line: t.a(0);

Javascript v1.2 added support for function arguments to setInterval(). What version of Safari do you use on OSX 10.2 ?

david_currey
06-03-2004, 12:20 AM
sorry for my ranting -

the last version of safari that people can use if they don't upgrade the OS to osx10.3 is 1.0.2 (v85.7).

I bet you're right about not needing closures, it is just that this was the first "major" exploration into objects and whatnot and not just writing the mess of functions I usually create ( ie trying to do things properly ), to be honest I have read as much as I could about closures and I just don't get it....all I want to do is write clean,efficient code that will do something over and over again to lots of different things :)

anyway, if I remove the line: t.a(0); how should I call the function?

thanks for the help, it is greatly appreciated,

dave

MikeFoster
06-03-2004, 01:59 AM
I don't know what js version is supported by Safari v1.0.2 - can't find it at developer.apple.com. Anyone?

To run the test, copy the following, save it as a file and load it into the browser. Run the test then copy the results out of the textarea.

Thanks!


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type='text/javascript'>
function myClass(limit)
{
var me = this; // private instance variable
this.name = 'myClosureTest'; // public instance variable
this.a = function(i) // public privileged method
{
var ta = document.getElementById('ta1');
ta.value = 'Method a()\n' +
'me: ' + me + '\n' +
'me.name: ' + me.name + '\n' +
'limit: ' + limit + '\n' +
'i: ' + i;
}
this.b = function(i) // public privileged method
{
setTimeout( function() {
var ta = document.getElementById('ta1');
ta.value += '\n\nDelayed Method b()\n' +
'me: ' + me + '\n' +
'me.name: ' + me.name + '\n' +
'limit: ' + limit + '\n' +
'i: ' + i;}, 1000);
}
}
myClass.prototype.test = function() // public method
{
this.a(1);
this.b(2);
}
var t = new myClass(10);
</script>
</head>
<body>
<h1>Javascript Closure Experiment</h1>
<p><a href='javascript:t.test()'>Run Closure Test</a></p>
<form>
<textarea id='ta1' rows='10' cols='40'>
</textarea>
</form>
</body>
</html>

liorean
06-03-2004, 02:08 AM
Safari uses KJS, the KDE JavaScript engine created primarily for use in the Konqueror browser. It doesn't use any version of JavaScript as of Netscape's or Mozilla's devising. The Netscape JavaScript versions are versions of the Netscape JavaScript engine, and the only non-Netscapian/Mozillan browser I know of that uses either of them is IceBrowser that uses the Rhino engine (Mozilla's Java based JavaScript 1.5 engine).

david_currey
06-03-2004, 03:37 AM
here is the result from safari on 10.2:


Method a()
me: [object Object]
me.name: myClosureTest
limit: 10
i: 1

liorean
06-03-2004, 04:06 AM
Try the following:
var
a="global",
b=a,
c=b,
fn=(function(b,c){
b="outer";
c=b;
return function(c){
c="inner";
return [a,b,c];
}
})();
alert('Should be [global,outer,inner]:\n'+fn());
If the value happens to instead be global,global,inner you know that the JavaScript engine doesn't properly support closures. If it happens to be global,outer,inner, the JavaScript engine evidently created the closure from the outer function correctly.

david_currey
06-03-2004, 04:31 AM
alert('Should be [global,outer,inner]:\n'+fn());

i get an error saying I am missing a closing bracket - should it go right at the end ?

I think over today we have worked out that safari can't do this, I hate it...

I have to find another way,

david_currey
06-03-2004, 04:36 AM
var
a="global",
b=a,
c=b,
fn=(function(b,c){
b="outer";
c=b;
return function(c){
c="inner";
return [a,b,c];
};
})()
alert('Should be [global,outer,inner]:\n'+fn());

david_currey
06-03-2004, 04:40 AM
if the )() trick i learned from you about executing the function was what you had in mind the unbelievably it works- where that leaves us, I just don't know ...frazzled - long year ....


function bed() {alert('NOW')}

thanks for a very interesting and learnfull day

liorean
06-03-2004, 10:50 AM
Hmm, that works, huh? Then I expect the problem to lie elsewhere. Maybe timeouts don't support callback functions in KJS?

MikeFoster
06-03-2004, 04:56 PM
Those were some good tests. Thanks David, for running those.


Maybe timeouts don't support callback functions in KJS?
Its beginning to look like that's the case. But David did say that it worked in the latest Safari.

liorean, thanks for the version info - I'm not very familiar with that platform.

liorean
06-03-2004, 06:17 PM
Oh, I can confirm that it works in the latest Safari (WebCore 125.7). And evidently my OmniWeb 5 beta 6.1 (WebCore 85.?) does give the global,outer,inner result that I would expect a closure creating JavaScript engine to output. However, running

setTimeout('alert(0)',1000);
setTimeout(function(){
alert(1);
},2000));points towards the earlier KJS versions (OmniWeb) not supporting callback functions as arguments to timeouts, while later KJS versions (Safari 1.2) supports it.

david_currey
06-03-2004, 09:35 PM
Don't get me wrong, I value the learning more than completing my task, but I still would like to find a way of making an constructor function that I can make a bunch of instances of that will let me change properties of html elements over time. (see post#2 in this thread).

So far from what we have discovered, because of safari, I need to make some kind of regularly occurring time delay between function calls that does not involve using setTimeout with a callback function as its argument.

again, thanks for your involvement, this thread has been a great help to me,

cheers,

david

liorean
06-03-2004, 11:26 PM
Well, your problem is that you need a string containing a function call to execute in the global scope. The easiest way of doing this is to use a global array containing function objects, and call an entry in that array from the timeout, using the string.

david_currey
06-03-2004, 11:35 PM
ahh, I see. I will give that route a try. thanks again :)

dave

MikeFoster
06-04-2004, 01:03 AM
The animation function doesn't have to be an object method. Remember that floater menu demo I posted a link to previously? ;)

oops, I made this post without seeing the two previous posts. Good suggestion



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum