Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Javascript (http://www.velocityreviews.com/forums/f68-javascript.html)
-   -   IE events expire (typeof = unknown) after callStack finishes. (featuring: setTimeout scoping) (http://www.velocityreviews.com/forums/t929851-ie-events-expire-typeof-unknown-after-callstack-finishes-featuring-settimeout-scoping.html)

phocis@gmail.com 02-20-2007 08:45 PM

IE events expire (typeof = unknown) after callStack finishes. (featuring: setTimeout scoping)
 
I wrote a pair of functions to enable scoped or referenced setTimeout
calls. I did this because I have an object factory that creates
multiple objects and those objects need to delay a few calls on
themselves at a certain point in time.

This code works fine for normal objects. However, my issue occurs if
at any point, an event object is passed across in IE.

It seems, that events methods and variables in IE are PRIVATE (!)
after the initial callstack has been finished.

The following is the code required to view this bug(?) in IE, and
success in FF.

<html>
<head>
<script>
/*****************************************
Here is the code for the delaying:
******************************************/
// Global variables.
var delayObjects = {}; // Hold the object references.
var delayObjectsIndex = 0; // Keep track of the index.

function delayObjectMethodCall(obj,exp,ms){
delayObjectsIndex++;
delayObjects[delayObjectsIndex] = obj; // This assigns
by reference.

// This is the eval that is to be run.
expNew = '\
if(delayObjects['+delayObjectsIndex+']){\
with(delayObjects['+delayObjectsIndex+']){\
'+exp+';\
}\
delayObjects['+delayObjectsIndex+'] =
undefined}\
';
document.getElementById('result').innerHTML = 'Delay
was called: (event.keyCode = '+obj.event.keyCode+')<br/
>'+document.getElementById('result').innerHTML;

setTimeout(expNew, ms);
return delayObjectsIndex;
}
function delayObjectMethodCallCancel(id){
if(typeof id != 'undefined' && delayObjects[id]){
clearTimeout(id);
delayObjects[id] = undefined;
return true;
}
}


/*********************************************
* Onload

********************************************/
window.onload = function(){
document.getElementById('test').onkeydown=function (e){
if(!e){e=window.event;}
document.getElementById('result').innerHTML =
'Event was fired: (event.keyCode = '+e.keyCode+')<br/
>'+document.getElementById('result').innerHTML;

document.getElementById('result').innerHTML =
'Before Delay: Input Value: '+this.value + '<br/
>'+document.getElementById('result').innerHTML;

// This is the call
delayObjectMethodCall(
// Object To pass
{input:this,event:e,other:'staticObject'},
// String to eval
"\

document.getElementById('result').innerHTML = 'START OF DELAY
PAYLOAD<br/>'+document.getElementById('result').innerHTML;\

document.getElementById('result').innerHTML = 'After Delay: Input
Value: '+input.value + '<br/
>'+document.getElementById('result').innerHTML;\


document.getElementById('result').innerHTML = 'After Delay: Other
Value: '+other + '<br/>'+document.getElementById('result').innerHTML;\
try{\

document.getElementById('result').innerHTML = 'Event keyCode:
'+event.keyCode + '<br/>'+document.getElementById('result').innerHTML;
\
}catch(e){\

document.getElementById('result').innerHTML = '<span style=\"color:red
\">Error:</span> '+e.message + '<br/
>'+document.getElementById('result').innerHTML;\


document.getElementById('result').innerHTML = '<span style=\"color:red
\">Error:</span> typeof event: '+typeof event+'<br/
>'+document.getElementById('result').innerHTML;\


document.getElementById('result').innerHTML = '<span style=\"color:red
\">Error:</span> typeof event.keyCode: '+typeof event.keyCode+'<br/
>'+document.getElementById('result').innerHTML;\

}\

document.getElementById('result').innerHTML = 'END OF DELAY PAYLOAD<br/
><br/>'+document.getElementById('result').innerHTML;\

",
100
);
return true;
}
}
</script>
</head>
<body>
<input id="test" type="text" value="change this somehow"/>
<input type="button" value="clear"
onclick="document.getElementById('result').innerHT ML = '';"/>
<div id="result"></div>
</body>
</html>


phocis@gmail.com 02-21-2007 10:28 PM

Re: IE events expire (typeof = unknown) after callStack finishes. (featuring: setTimeout scoping)
 
On Feb 20, 9:06 pm, "David Golightly" <davig...@gmail.com> wrote:
> On Feb 20, 12:45 pm, pho...@gmail.com wrote:
>
>
>
> > I wrote a pair of functions to enable scoped or referenced setTimeout
> > calls. I did this because I have an object factory that creates
> > multiple objects and those objects need to delay a few calls on
> > themselves at a certain point in time.

>
> > This code works fine for normal objects. However, my issue occurs if
> > at any point, an event object is passed across inIE.

>
> > It seems, thateventsmethods and variables inIEare PRIVATE (!)
> > after the initial callstack has been finished.

>
> > The following is the code required to view this bug(?) inIE, and
> > success in FF.

>
> > <html>
> > <head>
> > <script>
> > /*****************************************
> > Here is the code for the delaying:
> > ******************************************/
> > // Global variables.
> > var delayObjects = {}; // Hold the object references.
> > var delayObjectsIndex = 0; // Keep track of the index.

>
> > function delayObjectMethodCall(obj,exp,ms){
> > delayObjectsIndex++;
> > delayObjects[delayObjectsIndex] = obj; // This assigns
> > by reference.

>
> > // This is the eval that is to be run.
> > expNew = '\
> > if(delayObjects['+delayObjectsIndex+']){\
> > with(delayObjects['+delayObjectsIndex+']){\
> > '+exp+';\
> > }\
> > delayObjects['+delayObjectsIndex+'] =
> > undefined}\
> > ';
> > document.getElementById('result').innerHTML = 'Delay
> > was called: (event.keyCode = '+obj.event.keyCode+')<br/>'+document.getElementById('result').innerHTML;

>
> > setTimeout(expNew, ms);
> > return delayObjectsIndex;
> > }
> > function delayObjectMethodCallCancel(id){
> > if(typeof id != 'undefined' && delayObjects[id]){
> > clearTimeout(id);
> > delayObjects[id] = undefined;
> > return true;
> > }
> > }

>
> > /*********************************************
> > * Onload

>
> > ********************************************/
> > window.onload = function(){
> > document.getElementById('test').onkeydown=function (e){
> > if(!e){e=window.event;}
> > document.getElementById('result').innerHTML =
> > 'Event was fired: (event.keyCode = '+e.keyCode+')<br/>'+document.getElementById('result').innerHTML;

>
> > document.getElementById('result').innerHTML =
> > 'Before Delay: Input Value: '+this.value + '<br/>'+document.getElementById('result').innerHTML;

>
> > // This is the call
> > delayObjectMethodCall(
> > // Object To pass
> > {input:this,event:e,other:'staticObject'},
> > // String to eval
> > "\

>
> > document.getElementById('result').innerHTML = 'START OF DELAY
> > PAYLOAD<br/>'+document.getElementById('result').innerHTML;\

>
> > document.getElementById('result').innerHTML = 'After Delay: Input
> > Value: '+input.value + '<br/

>
> > >'+document.getElementById('result').innerHTML;\

>
> > document.getElementById('result').innerHTML = 'After Delay: Other
> > Value: '+other + '<br/>'+document.getElementById('result').innerHTML;\
> > try{\

>
> > document.getElementById('result').innerHTML = 'Event keyCode:
> > '+event.keyCode + '<br/>'+document.getElementById('result').innerHTML;
> > \
> > }catch(e){\

>
> > document.getElementById('result').innerHTML = '<span style=\"color:red
> > \">Error:</span> '+e.message + '<br/

>
> > >'+document.getElementById('result').innerHTML;\

>
> > document.getElementById('result').innerHTML = '<span style=\"color:red
> > \">Error:</span> typeof event: '+typeof event+'<br/

>
> > >'+document.getElementById('result').innerHTML;\

>
> > document.getElementById('result').innerHTML = '<span style=\"color:red
> > \">Error:</span> typeof event.keyCode: '+typeof event.keyCode+'<br/>'+document.getElementById('result').innerHTML;\

>
> > }\

>
> > document.getElementById('result').innerHTML = 'END OF DELAY PAYLOAD<br/><br/>'+document.getElementById('result').innerHTML;\

>
> > ",
> > 100
> > );
> > return true;
> > }
> > }
> > </script>
> > </head>
> > <body>
> > <input id="test" type="text" value="change this somehow"/>
> > <input type="button" value="clear"
> > onclick="document.getElementById('result').innerHT ML = '';"/>
> > <div id="result"></div>
> > </body>
> > </html>

>
> When you look at your code and you see a lot of repetition, even
> visually, that's a clue that you should re-examine your style (Don't
> Repeat Yourself - Especially When Asking Other People To Look At Your
> Code).
>
> 1. Try to come up with a way to do this without using "eval". (Hint:
> take a look at function closures.) See:http://jibbering.com/faq/#FAQ4_40htt.../code.html(end).
> 2. Since the main element you're working with is 'result', why not
> just assign it to a variable and avoid the repeated
> "document.getElementById" for readability. Ditto with the ubiquitous
> multi-line strings (which will go away after you take care of #1).
>
> As for your "event" object problem, the "event" object's properties
> are not "private", a concept which does not exist in JavaScript, at
> least not in any way analogous to C++ or Java. The problem here, as
> your example demonstrates, is as follows: after the called event
> handler exits and its scope chain is broken down, the window.event
> object is cleared for the next event and any references to it are no
> longer valid. You should instead pass in any specific values (such as
> keyCode) to your literal, as these will be preserved across the
> boundary.
>
> -David


In response to your first point:
Closures will not work for what I'm trying to accomplish. The only way
to process a delayed execution is with either eval or setTimeout. I
cannot imagine that there is any other obvious way to do it. And what
I was trying to share was that it is possible to pass object
references with it using my two functions.

In response to your second point:
All of the repetition is for the display of the testing logic.
Granted, I guess it's still bad to have, but I wanted things to be as
straight forward as possible. As that was my first post to a
newsgroup, I was unaware that my message would be formatted to a set
column size. I apologize for the resulting obfuscation.





All times are GMT. The time now is 07:56 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57