Jump to content

Recommended Posts

I can't figure out why I can't access the object properties in my function addTime().  The object (dayObject) is created with properties: src, name, hoursArr, counter.  (src is the parent element (HTML obj), name (str), hoursArr(array), counter(int).

 

It calls itself with init(), which is a function that is prototyped to the dayObject.  Inside of dayObject->init(), those properties are still visible (alert(this.name))...  When I later called addTime() (which is an onclick event), it no longer sees those properties (they are undefined..)  Anyone know why?

 

[if I had to guess what was wrong, I'd say that in the init() function, the binding of link.onclick = this.addTime doesn't provide a reference to the object itself...  I'm not sure how to provide it though, using this coding style (which I'd like to stick with)]

 

HTML for testing:

<html><head></head><body>
<div id="timezones">
    <div class="Monday" id=div_Monday"></div>
    <div class="Tuesday" id="div_Tuesday"></div>
</div><!-- timezones -->
<script type="text/javascript" src="times.js"></script>
</body></html>

 

relevant Javascript (times.js)

var hours = [ "--",1,2,3,4,5,6,7,8,9,10 ];//available hours
var dayObjTracker = [];


//onload bind to divs
window.onload = function () {
    //get div for each day
    var tz = document.getElementById("timezones");
        var target_divs = tz.getElementsByTagName("div");
    
    //create day object for each day
    for(var i=0;i<target_divs.length;i++)
    {
        dayObjTracker.push( new dayObject(target_divs[i]) );
    }
}//onload ---------------------------------------------------


//dayObject
function dayObject(mainElement) {

    this.src = mainElement;
    this.name = mainElement.className;
    this.hoursArr = hours.slice();
    this.counter = 0;

        this.init();
};//dayObject -----------------------------------------------


//init(): add links to the divs
dayObject.prototype.init = function() {
    //create the link + attributes
    var link = document.createElement("a");
        link.appendChild(document.createTextNode("Add Time"));//link text
        link.setAttribute("href", "#");//null href
        link.onclick = this.addTime;//onclick
    
    //append link to main element
    this.src.appendChild(link);
}//init -----------------------------------------------------


//addTime(): request a new time block
dayObject.prototype.addTime = function() {
    alert(this.counter);  //this comes up as undefined ##
}

Link to comment
https://forums.phpfreaks.com/topic/171860-out-of-scope-improperly-referenced/
Share on other sites

I don't have any event handler code..  What I provided is exactly what I had up to that point.. The rest of the code that is missing would include creating SELECT and OPTION elements, and appending them to the source element..  I didn't include the addTime() code before because it is reliant on having access to the this.hoursArr variable.

 

Perhaps I misunderstand your question?

 

The HTML code is exactly the same.

 

The full javascript is this:

var hours = [ "--",1,2,3,4,5,6,7,8,9,10 ];//available hours
var dayObjTracker = [];


//onload bind to divs
window.onload = function () {
    //get div for each day
    var tz = document.getElementById("timezones");
        var target_divs = tz.getElementsByTagName("div");
    
    //create day object for each day
    for(var i=0;i<target_divs.length;i++)
    {
        dayObjTracker.push( new dayObject(target_divs[i]) );
    }
}//onload ---------------------------------------------------


//dayObject
function dayObject(mainElement) {

    this.src = mainElement;
    this.name = mainElement.className;
    this.hoursArr = hours.slice();
    this.counter = 0;

        this.init();
};//dayObject -----------------------------------------------


//init(): add links to the divs
dayObject.prototype.init = function() {
    //create the link + attributes
    var link = document.createElement("a");
        link.appendChild(document.createTextNode("Add Time"));//link text
        link.setAttribute("href", "#");//null href
        link.onclick = this.addTime;//onclick
    
    //append link to main element
    this.src.appendChild(link);
}//init -----------------------------------------------------


//addTime(): request a new time block
dayObject.prototype.addTime = function() {

    //create paragraph to hold it
    var p = document.createElement("p");
        p.setAttribute("id","timeblock_" + this.counter);
    
    //create "From"
    var fromTxt = document.createElement("span");
        fromTxt.setAttribute("class","fromText");
        fromTxt.appendChild(document.createTextNode("From"));

    //create "until"
    var fromTxt = document.createElement("span");
        fromTxt.setAttribute("class","untilText");
        fromTxt.appendChild(document.createTextNode("until"));

    //#############
    //create select1: name == day_start/end# (Monday_start0...)
        var startName = this.name + "_" + "start" + this.counter;
        var endName = this.name + "_" + "end" + this.counter;

    var select1 = makeSelect(startName, this.hoursArr, endName);
        
        //if its the first one, make it reset all others
        if(this.counter == 0) {
            select1.onchange = function() {
                alert('ready to remove all');
                updateOps(select1, endName);//source Element, destination name
            }
        }else{
            select1.onchange = function() {
                updateOps(select1, endName);
            }
        }//counter == 0?
        
    //create select2
    var select2 = makeSelect(endName, this.hoursArr, "");
    
    
        //put it together
        p.appendChild(fromTxt);
        p.appendChild(select1);
        p.appendChild(untilTxt);
        p.appendChild(select2);
        
        this.src.appendChild(p);

}//addTime --------------------------------------------------
*/

//makeSelect(): create a <select> element
function makeSelect(name, hoursArr, trgt) {

    //create select element
    var select = document.createElement("select");
        select.setAttribute("name", name);
        select.setAttribute("id", name);
        select.setAttribute("trgt",trgt);//trgt is second select in block or null
    
    var opsArr = makeOptions(hoursArr);
        var opsArr_len = opsArr.length;
    
    for(var i=0; i<opsArr_len; i++)
    {
        select.appendChild(opsArr[i]);
    }
    
    return select;//HTML element
}//makeSelect -----------------------------------------------


//makeOptions: create <option> element(s)
function makeOptions(arr) {

    var ops = [];
    var arr_len = arr.length;
    for(var i=0; i<arr_len; i++)
    {
        var o = document.createElement("option");
            o.setAttribute("value", arr[i]);//val
            o.appendChild(document.createTextNode(arr[i]));//innerhtml
        ops.push(o);
    }
    
    return ops;//array
}//makeOptions ----------------------------------------------

//updateOps: change all elements to be higher than previous select
function updateOps(src,dest) {

    var hrs = hours.slice(src.selectedIndex + 1);
    var trgt = document.getElementById(dest);
        while(trgt.hasChildNodes() && (trgt.childNodes.length >= 1)) {
            trgt.removeChild( trgt.firstChild );
        }
    var o = makeOptions(hrs);
        var o_len = o.length;
    for(var i=0;i<o_len;i++)
    {
        trgt.appendChild(o[i]);
    }
}//updateOps ------------------------------------------------

Oh, I see the problem.  Your assumption is correct - the 'this' in addDate is referencing the link, not your custom object.  Why cant you just pass a reference of the object to the function?  Something like:

 

dayObject.prototype.addDate = function(objRef){
   alert(objRef.counter);
}

//in init():

link.onclick = addDate(this);

Thanks, I was able to get it to recognize the object using your suggestion.  It also brought along another issue, see below.

//init();
        ...
        link.onclick = this.addTime(this);//onclick

//addTime();
dayObject.prototype.addTime = function(objRef) {//I had tried this,placing "this" instead of objRef or w.e inside >.> so close..
        alert(objRef.counter);
}

 

 

However, in changing the init() onclick line, it now automatically executes the function on page load.  addTime(this) runs without clicking, etc, and clicking on the link doesn't do anything.  I have had this problem before, but not sure how I fixed it.. any ideas?  I will continue to mess around with it as well.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.