IE events expire (typeof = unknown) after callStack finishes. (featuring: setTimeout scoping)

Discussion in 'Javascript' started by phocis@gmail.com, Feb 20, 2007.

  1. Guest

    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').innerHTML = '';"/>
    <div id="result"></div>
    </body>
    </html>
    , Feb 20, 2007
    #1
    1. Advertising

  2. Guest

    On Feb 20, 9:06 pm, "David Golightly" <> wrote:
    > On Feb 20, 12:45 pm, 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').innerHTML = '';"/>
    > > <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_40http://javascript.crockford.com/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.
    , Feb 21, 2007
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Morten Simonsen

    Retrieve callstack from a Thread

    Morten Simonsen, Sep 17, 2003, in forum: Java
    Replies:
    1
    Views:
    314
    Robert Olofsson
    Sep 17, 2003
  2. Jacob

    Callstack question

    Jacob, Sep 22, 2003, in forum: Java
    Replies:
    0
    Views:
    344
    Jacob
    Sep 22, 2003
  3. Stefan Behnel
    Replies:
    0
    Views:
    399
    Stefan Behnel
    Oct 17, 2005
  4. Jeff
    Replies:
    0
    Views:
    288
  5. Tongass Park Neighborhood Association, Juneau Alas

    Cookies expire immediately, not when set to expire

    Tongass Park Neighborhood Association, Juneau Alas, Oct 1, 2009, in forum: ASP General
    Replies:
    2
    Views:
    1,195
    SQLDude
    Nov 24, 2009
Loading...

Share This Page