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 ## } 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? 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 ------------------------------------------------ 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); 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. 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
Archived
This topic is now archived and is closed to further replies.