I've been looking all over and can't e up with a solution. The following code works perfectly in IE9, Chrome, FF, and Safari. However, when you hit "Start" in IE7 or IE8 you get the following error:
SCRIPT5007: Unable to get the value of property 'newQuestion': object is null or undefined
The code at issue is here:
//This is used to reduce some code size and not type document.getElementById(a) each time
function DOMelem(a) {
return document.getElementById(a);
}
//This is used to round numbers
function roundTo(a,b) {
a=a*Math.pow(10,b);
a=Math.round(a);
a=a/Math.pow(10,b);
return a;
}
//The quiz object
function sQuiz(a,c,init) {
//This part is used to get the variable used by the user
this.getName=function() {
for(var v in window) {
if(window[v] instanceof sQuiz) {
this.varName=v;
}
}
},
//This will create the first page of the quiz
this.createQuiz=function() {
this.getName();
DOMelem(a).innerHTML="<h1>"+init.intro.qTitle+"</h1>";
DOMelem(a).innerHTML+="<h2>"+init.intro.qAuthor+"</h2>";
DOMelem(a).innerHTML+="<h3>"+init.intro.qComments+"</h3><br /><br />";
DOMelem(a).innerHTML+="<input type='button' value='Start' onClick='"+this.varName+".newQuestion(0)'>";
},
//This one will create a random id for the quiz and create a bar for it
this.createBar=function() {
id="12391023103091"+Math.round(Math.random()*12391023103091);
id=id.substr(id.length-14,14);
this.randBarId=id;
DOMelem(c).innerHTML="<div class='progress_full' id='pro_"+id+"'><div class='progress_bar' style='width:0%;' id='bar_"+id+"'></div></div>";
},
//In this section we check to see if there's a bar, if we must show the results or just show the interface.
this.newQuestion=function(index) {
//Create the bar if it does not exist
if(!DOMelem("pro_"+this.randBarId)||!DOMelem("bar_"+this.randBarId)) {
eval(this.varName+".createBar()");
}
//Show the results page
if(index>=init.questions.length) {
eval(this.varName+".showResults()");
}
//Show the question interface
else {
DOMelem(a).innerHTML="<h1>"+init.questions[index].question+"</h1>";
for (var i=0;i<init.questions[index].answers.length;i++) {
DOMelem(a).innerHTML+="<input type='button' name='"+index+"_"+i+"' value='"+init.questions[index].answers[i]+"' onClick='"+this.varName+".checkAnswer("+index+","+i+")'>";
}
DOMelem(a).innerHTML+="<input type='submit' id='btn_"+this.randBarId+"' value='Next Question' onClick='"+this.varName+".changeQuestion("+index+")' disabled>";
DOMelem("bar_"+this.randBarId).style.width=(((index+1)/init.questions.length)*100)+"%";
}
},
//This is used when the user clicks to change the question
this.changeQuestion=function(index) {
return this.newQuestion(index+1);
},
//This part handles when the user clicks on an answer, color it, un-disable the button and record the guess
this.checkAnswer=function(index,i) {
init.questions[index].guessed=i;
var inputs=document.getElementById(a).getElementsByTagName("input");
for(var j=0;j<inputs.length;j++) {
document.getElementById(a).getElementsByTagName("input")[j].className="";
if(inputs[i].name==index+"_"+i) {
document.getElementById(a).getElementsByTagName("input")[i].className="selected";
}
}
DOMelem("btn_"+this.randBarId).disabled=false;
},
//This one here shows the result of the quiz.
this.showResults=function() {
DOMelem(a).innerHTML="<h1>Results of "+init.intro.qTitle+"</h1>";
var count=0;
for(var i=0;i<init.questions.length;i++) {
if(init.questions[i].guessed==(init.questions[i].correctAnswer-1)) {
count++;
DOMelem(a).innerHTML+="<div id='answer' class='correct'>√ Question "+(i+1)+"</div>";
}
else {
DOMelem(a).innerHTML+="<div id='answer' class='wrong'>× Question "+(i+1)+"</div>";
}
}
var result=roundTo((count/init.questions.length)*100,2);
DOMelem(a).innerHTML+="<h3 style='clear:both'><br />"+result+"% correct answers.</h3>";
var tweet=init.tweetText.replace(/--score--/gi,result+"%");
tweet=tweet.replace(/ /gi,'+');
tweet="="+tweet;
DOMelem(a).innerHTML+="<a href='"+tweet+"'>Tweet it</a>";
}
}
You can view a demo here.
I really think I've read about every related question, but still can't e up with a solution. Please let me know if any additional information would be helpful.
UPDATE:
To clarify, I am testing in IE9 with patibility mode turned on. If anyone actually has IE7 or IE8 installed, I would live to know your results. Anyway, the code seems to execute up until here:
//This will create the first page of the quiz
this.createQuiz=function() {
this.getName();
DOMelem(a).innerHTML="<h1>"+init.intro.qTitle+"</h1>";
DOMelem(a).innerHTML+="<h2>"+init.intro.qAuthor+"</h2>";
DOMelem(a).innerHTML+="<h3>"+init.intro.qComments+"</h3><br /><br />";
DOMelem(a).innerHTML+="<input type='button' value='Start' onClick='"+this.varName+".newQuestion(0)'>";
},
Once the start button is clicked, I get an error because this.varName
returns as undefined
.
I've been looking all over and can't e up with a solution. The following code works perfectly in IE9, Chrome, FF, and Safari. However, when you hit "Start" in IE7 or IE8 you get the following error:
SCRIPT5007: Unable to get the value of property 'newQuestion': object is null or undefined
The code at issue is here:
//This is used to reduce some code size and not type document.getElementById(a) each time
function DOMelem(a) {
return document.getElementById(a);
}
//This is used to round numbers
function roundTo(a,b) {
a=a*Math.pow(10,b);
a=Math.round(a);
a=a/Math.pow(10,b);
return a;
}
//The quiz object
function sQuiz(a,c,init) {
//This part is used to get the variable used by the user
this.getName=function() {
for(var v in window) {
if(window[v] instanceof sQuiz) {
this.varName=v;
}
}
},
//This will create the first page of the quiz
this.createQuiz=function() {
this.getName();
DOMelem(a).innerHTML="<h1>"+init.intro.qTitle+"</h1>";
DOMelem(a).innerHTML+="<h2>"+init.intro.qAuthor+"</h2>";
DOMelem(a).innerHTML+="<h3>"+init.intro.qComments+"</h3><br /><br />";
DOMelem(a).innerHTML+="<input type='button' value='Start' onClick='"+this.varName+".newQuestion(0)'>";
},
//This one will create a random id for the quiz and create a bar for it
this.createBar=function() {
id="12391023103091"+Math.round(Math.random()*12391023103091);
id=id.substr(id.length-14,14);
this.randBarId=id;
DOMelem(c).innerHTML="<div class='progress_full' id='pro_"+id+"'><div class='progress_bar' style='width:0%;' id='bar_"+id+"'></div></div>";
},
//In this section we check to see if there's a bar, if we must show the results or just show the interface.
this.newQuestion=function(index) {
//Create the bar if it does not exist
if(!DOMelem("pro_"+this.randBarId)||!DOMelem("bar_"+this.randBarId)) {
eval(this.varName+".createBar()");
}
//Show the results page
if(index>=init.questions.length) {
eval(this.varName+".showResults()");
}
//Show the question interface
else {
DOMelem(a).innerHTML="<h1>"+init.questions[index].question+"</h1>";
for (var i=0;i<init.questions[index].answers.length;i++) {
DOMelem(a).innerHTML+="<input type='button' name='"+index+"_"+i+"' value='"+init.questions[index].answers[i]+"' onClick='"+this.varName+".checkAnswer("+index+","+i+")'>";
}
DOMelem(a).innerHTML+="<input type='submit' id='btn_"+this.randBarId+"' value='Next Question' onClick='"+this.varName+".changeQuestion("+index+")' disabled>";
DOMelem("bar_"+this.randBarId).style.width=(((index+1)/init.questions.length)*100)+"%";
}
},
//This is used when the user clicks to change the question
this.changeQuestion=function(index) {
return this.newQuestion(index+1);
},
//This part handles when the user clicks on an answer, color it, un-disable the button and record the guess
this.checkAnswer=function(index,i) {
init.questions[index].guessed=i;
var inputs=document.getElementById(a).getElementsByTagName("input");
for(var j=0;j<inputs.length;j++) {
document.getElementById(a).getElementsByTagName("input")[j].className="";
if(inputs[i].name==index+"_"+i) {
document.getElementById(a).getElementsByTagName("input")[i].className="selected";
}
}
DOMelem("btn_"+this.randBarId).disabled=false;
},
//This one here shows the result of the quiz.
this.showResults=function() {
DOMelem(a).innerHTML="<h1>Results of "+init.intro.qTitle+"</h1>";
var count=0;
for(var i=0;i<init.questions.length;i++) {
if(init.questions[i].guessed==(init.questions[i].correctAnswer-1)) {
count++;
DOMelem(a).innerHTML+="<div id='answer' class='correct'>√ Question "+(i+1)+"</div>";
}
else {
DOMelem(a).innerHTML+="<div id='answer' class='wrong'>× Question "+(i+1)+"</div>";
}
}
var result=roundTo((count/init.questions.length)*100,2);
DOMelem(a).innerHTML+="<h3 style='clear:both'><br />"+result+"% correct answers.</h3>";
var tweet=init.tweetText.replace(/--score--/gi,result+"%");
tweet=tweet.replace(/ /gi,'+');
tweet="https://www.twitter./share?text="+tweet;
DOMelem(a).innerHTML+="<a href='"+tweet+"'>Tweet it</a>";
}
}
You can view a demo here.
I really think I've read about every related question, but still can't e up with a solution. Please let me know if any additional information would be helpful.
UPDATE:
To clarify, I am testing in IE9 with patibility mode turned on. If anyone actually has IE7 or IE8 installed, I would live to know your results. Anyway, the code seems to execute up until here:
//This will create the first page of the quiz
this.createQuiz=function() {
this.getName();
DOMelem(a).innerHTML="<h1>"+init.intro.qTitle+"</h1>";
DOMelem(a).innerHTML+="<h2>"+init.intro.qAuthor+"</h2>";
DOMelem(a).innerHTML+="<h3>"+init.intro.qComments+"</h3><br /><br />";
DOMelem(a).innerHTML+="<input type='button' value='Start' onClick='"+this.varName+".newQuestion(0)'>";
},
Once the start button is clicked, I get an error because this.varName
returns as undefined
.
- Can you reduce this to the minimum possible that still shows the error? – RobG Commented Jan 17, 2012 at 5:28
- Using IE 9 in patability mode is related to page layout and formatting, I don't think it makes any change to the script engine. Can you post a working snippet that shows the error? – RobG Commented Jan 17, 2012 at 22:47
- @RobG Did you try ktbaker./quiz ? – ARP Commented Jan 21, 2012 at 2:46
- Yes, the page doesn't work at all in IE8. – RobG Commented Jan 23, 2012 at 0:09
2 Answers
Reset to default 2In your code:
> //The quiz object
Is really a function object, not a plain object. And do you expect to call it as a constructor? I can't get to the demo.
Likely this:
> this.getName=function() {
> for(var v in window) {
> if(window[v] instanceof sQuiz) {
> this.varName=v;
> }
> }
> },
is treated as a syntax error because it is terminated with a ma instead of a semi–colon. No, it's not.
Edit
Your problem is here:
for(var v in window) {
if(window[v] instanceof sQuiz) {
this.varName=v;
}
}
Global variables are not enumerable in IE 8 (and probably earlier), so you never find the instance(s) of sQuiz you are looking for and this.varName remains undefined (actually, the object will not have a varName property at all, unless you add it some other way elsewhere).
You need to use some other method of referencing the instance(s)— perhaps using the module pattern and keeping a reference in a closure, or an array of references to each instance.
I'm not 100% sure, but I get a JavaScript error when I load the page in IE. This line:-
if(window[v] instanceof sQuiz)
is failing - you should check window[v] for null first before instanceof