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 5 of 5
  1. #1
    New Coder
    Join Date
    Jun 2004
    Location
    Chicago
    Posts
    22
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Question Advanced JS question - object scope problem

    I'm working on a web application, and they have requested a dynamic help system. They want 'tool
    tip' type help. I have taken the code from Nicer titles at
    (http://neo.dzygn.com/archive/2003/12/nicer-titles) as a basis for what I am doing. That code is
    great but I need to drop more data into the 'tool tip' than what a title attribute would allow -
    essentially a paragraph of text.

    I've set this up as an object. The problem I am having is that it seems some variables appear to
    be out of scope, and I'm not sure where I am making my mistake.

    Quick rundown on the code:

    Set up the class:

    function DynamicHelp(nDelay, sContainerID, sClassName)
    {
    var oTimer;
    var isActive = false;
    var nDelay;
    var sNameSpaceURI = "http://www.w3.org/1999/xhtml";

    if(!nDelay || nDelay <= 0){ nDelay = false;}
    if(!sContainerID){ sContainerID = "helpdiv";}
    if(!sClassName){ sClassName = "helpbox";}

    // write help div to page
    var oContainer = document.getElementById(sContainerID);
    if(!oContainer)
    {
    oContainer = document.createElementNS ? document.createElementNS(sNameSpaceURI, "div") :
    document.createElement("div");
    oContainer.setAttribute("id", sContainerID);
    oContainer.className = sClassName;
    oContainer.style.display = "none";
    document.getElementsByTagName("body").item(0).appendChild(oContainer);
    }

    //=====================================================================
    // Method addElements (Public)
    //=====================================================================
    this.addElements = function addElements()
    {
    // find all elements that have a span attached
    var spanArray = document.getElementsByTagName("span");
    for(var i=0;i<spanArray.length;i++)
    {
    // but grab only the 'help' spans
    if(spanArray[i].className == "help")
    {
    // attach events
    addEvent(spanArray[i], 'mouseover', show);
    addEvent(spanArray[i], 'mouseout', hide);
    addEvent(spanArray[i], 'focus', show);
    addEvent(spanArray[i], 'blur', hide);
    }
    }
    }
    }

    The addElements() method is where I grab every span that has a class of 'help' and add the events.
    Up to this point, everything is working fine. Those methods are called on mouseover etc:

    function addEvent(obj, evType, fn){
    if(obj.addEventListener){
    obj.addEventListener(evType, fn, false);
    return true;
    } else if (obj.attachEvent){
    var r = obj.attachEvent('on'+evType, fn);
    return r;
    } else {
    return false;
    }
    }

    function show(){
    if(nDelay){
    oTimer = setTimeout(function(){oContainer.style.display = "block";}, nDelay);
    } else {
    oContainer.style.display = "block";
    }
    }

    function hide(){
    oContainer.style.display = "none";
    clearTimeout(oTimer);
    }

    My error is showing up in the show() method. the vars nDelay and oContainer seem to be out of
    scope :

    "Error: oContainer is not defined" - of course it is defined in the class, but this method is not
    seeing that. Below is how I am writing it out to the page:

    DynamicHelp.autoCreation = function()
    {
    if(!document.getElementsByTagName){ return; } //not supported
    DynamicHelp.autoCreated = new Object();
    DynamicHelp.autoCreated.help = new DynamicHelp(600);
    DynamicHelp.autoCreated.help.addElements();
    }

    addEvent(window, "load", DynamicHelp.autoCreation);


    You can see the complete page (all code inline) at:

    http://www.pixelmech.com/rev/help2.html

    TIA

    Tom
    http://www.pixelmech.com/

    Get your FREE mini-mac! Totally legit - same people who do free iPods:
    http://www.FreeMiniMacs.com/?r=15890422

  • #2
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    timeouts are in the scope of the window, not your object. You need to create a variable that's private to the method, and that will be global within (and unique to) the scope of that method, so then you can reference that from inside the timeout.

    It actually sound more complicated than it is:
    Code:
    var thisContainer = oContainer;
    oTimer = setTimeout(function(){thisContainer.style.display = "block";}, nDelay);
    Which is the same trick as going "var self = this" before an expando handler, so that you have a reference to the calling object from inside it.

    btw - your "nDelay" variable is confusing - is it a number or a boolean? It seems to be used as both at different times.
    Last edited by brothercake; 04-18-2005 at 07:14 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

  • #3
    New Coder
    Join Date
    Jun 2004
    Location
    Chicago
    Posts
    22
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks BC - I should have put my show/hide methods inside the class. I've done that and now it works well. The nDelay is a number, although it checks for it as a boolean to see if it has been set, I see where you say that is confusing. I should probably do:

    if(nDelay > 0){
    oTimer = setTimeout(function(){oContainer.style.display = "block";}, nDelay);
    }
    else {
    oContainer.style.display = "block";
    }

    And set it to 0 if it is not passed as an argument when constructed. Would that make more sense? Most of this code is nicked from niceTitles and I've only changed what I needed for it to work.
    http://www.pixelmech.com/

    Get your FREE mini-mac! Totally legit - same people who do free iPods:
    http://www.FreeMiniMacs.com/?r=15890422

  • #4
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Keeping it as a number would be the thing to do - if you're comparing it as a boolean when the value might be zero, you're relying on automatic datatype conversion, and that's not a good thing to do, espcially if you're using the letter-prefix convention to indicate datatype.
    "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
    New Coder
    Join Date
    Jun 2004
    Location
    Chicago
    Posts
    22
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Yep, switched it and it works just fine. Thanks!
    http://www.pixelmech.com/

    Get your FREE mini-mac! Totally legit - same people who do free iPods:
    http://www.FreeMiniMacs.com/?r=15890422


  •  

    Posting Permissions

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