xtopolis Posted August 25, 2009 Share Posted August 25, 2009 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 ## } Quote Link to comment https://forums.phpfreaks.com/topic/171860-out-of-scope-improperly-referenced/ Share on other sites More sharing options...
KevinM1 Posted August 26, 2009 Share Posted August 26, 2009 Can you show your event handler code? Quote Link to comment https://forums.phpfreaks.com/topic/171860-out-of-scope-improperly-referenced/#findComment-906336 Share on other sites More sharing options...
xtopolis Posted August 26, 2009 Author Share Posted August 26, 2009 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 ------------------------------------------------ Quote Link to comment https://forums.phpfreaks.com/topic/171860-out-of-scope-improperly-referenced/#findComment-906355 Share on other sites More sharing options...
KevinM1 Posted August 26, 2009 Share Posted August 26, 2009 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); Quote Link to comment https://forums.phpfreaks.com/topic/171860-out-of-scope-improperly-referenced/#findComment-906634 Share on other sites More sharing options...
xtopolis Posted August 26, 2009 Author Share Posted August 26, 2009 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. Quote Link to comment https://forums.phpfreaks.com/topic/171860-out-of-scope-improperly-referenced/#findComment-906864 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.