gameI created the following "class":
function State(){
this.board = [];
for (i=0; i< 9; i++){
var row = [];
for (j=0; j< 9; j++){
row.push(0);
}
this.board.push(row);
}
}
It has a method called nextEmptyCell:
State.prototype.nextEmptyCell = function(){
...
}
I created an instance of this class and passed it to another function.
game = new State();
function solveSudoku(game){
var next = game.nextEmptyCell();
...
}
On the following line: var next = game.nextEmptyCell(); I receive an error saying:
"Uncaught TypeError: Cannot read property 'nextEmptyCell' of undefined".
I don't understand why 'game' is undefined and how to fix this error.
Link to the full code: jsfiddle.net/py6kv7ps/5
P.S. Is there a better way of using JS as OOP?
Issue comes from solveSudoku(), you are calling it recursively without passing an argument. Thats why you are getting error.
"Uncaught TypeError: Cannot read property 'nextEmptyCell' of
undefined".
function solveSudoku(game) {
if (solveSudoku(ADD game OBJECT HERE)) {
return game;
}
}
You probably meant game.nextEmptyCell(), not state.nextEmptyCell(). There is no variable named state anywhere in the code you posted.
Its because your parameter game shadows the glbal variable game of the same name. The global variable game = new State(); has the correct value. So you can pass it to your method call to use the correct value of game within the method solveSudoku()
function State(){
this.board = [];
for (i=0; i< 9; i++){
var row = [];
for (j=0; j< 9; j++){
row.push(0);
}
this.board.push(row);
}
}
State.prototype.nextEmptyCell = function(){
console.log('egvse gtrs');
document.write('egvse gtrs');
};
var game = new State();
function solveSudoku(game){
var next = game.nextEmptyCell();
}
solveSudoku(game);
Related
I have referenced multiple SO questions but I still could not find a solution. These are the questions I took a look at (main ones):
Pass a JavaScript function as parameter
How to execute a method passed as parameter to function
compute.js:
const mainTable = document.getElementById('nonFixedSample');
function getRows(metricName) {
let row = 0;
let z = document.getElementsByTagName('tr');
for (let i = 0; i < z.length; i++) {
if (mainTable.rows[i].firstChild.textContent === metricName) {
row = i;
return row;
}
}
}
// Here I am trying to pass that function as callback
function stdCellArea(callback) {
rowNumber = callback();
let runs = mainTable.rows[rowNumber].cells.length;
// Other code
}
Now I am calling it, reg_report.php:
<script>
stdCellArea(function() {
getRows('test');
});
</script>
But I get the following error:
Uncaught TypeError: Cannot read property 'cells' of undefined
at stdCellArea (compute.js:17)
at reg_report.php:39
Basically, I need to use return value of getRows() as an argument for stdCellArea(). I know I could simply do this:
let x = getRows('text');
stdCellArea(x);
But I have to call this function over 10 times, so I do not want to create many variables. Who can help?
You need to return the value from your callback: return getRows('test');. Without that, rowNumber becomes undefined as that's what functions without an explicit return, return.
I have always wondered this and every now and again it pops up.
var name = document.title;
var user = document.getElementsByClassName("class-name")[0].children[j].getElementsByTagName("a")[0].innerHTML;
var someArr = [];
for (var j = 0; j < document.getElementsByClassName("class-name")[0].children.length; j++) {
if (user == name) {
someArr.push(user)
};
};
alert(someArr);
Now this is all made up (obviously) but see how the variable "user" is checking for children[j], well if I were to try use this code, it would come up with an error along the lines of "Cannot read property 'getElementsByTagName' of undefined". Now my question is: Is there a way to allow this code to work without giving an error message and not executing. I would use this for clean code in the if loop, like all variables are used for. This wouldn't be the only instance of the "user" variable being used either so it is very useful.
Thanks in advance,
Daniel.
Your j variable will have undefined value if you use it before the for loop.
You could put it inside a function closure, but using variables like this does not make code readable in my opinion. What you can do is create a getUser() function and also cache the array of elements. Something like this:
var name = document.title;
var getUser = function(elem) {
return elem.getElementsByTagName('a')[0].innerHTML;
};
var initialArr = document.getElementsByClassName("class-name")[0].children;
var someArr = [];
for (var j = 0; j < initialArr.length; j++) {
var user = getUser(initialArr[j]);
if (user == name) {
someArr.push(user)
};
};
alert(someArr);
I m trying to make a simple dumb tic-tac-toe game using HTML, CSS and Javascript.
In the below function for the player move the ComputerMove Function cannot be called because of Typeerror in JSON object.
function Mymove(idValue)
{
var flag=0;
var image = document.getElementById(idValue);
if (image.src.match("blank.png")) {
image.src = "X.png";
flag=Check();
if (flag==1)
{
alert("You Won");
reset();
return;
};
ComputerMove();
};
}
function Check(){
for (var i =0 ; i <= 8;i++) {
var image=document.getElementById(winList[i].a);
if (!image.src.match("blank.png")) {
if(image.src==document.getElementById(winList[i].b).src && image.src==document.getElementById(winList[i].c).src)
return 1;
}
}
Here is the JSON object below:-
var winList =[
{a:1,b:2,c:3},
{a:4,b:5,c:6},
{a:7,b:8,c:9},
{a:1,b:4,c:7},
{a:2,b:5,c:8},
{a:3,b:6,c:9},
{a:1,b:5,c:9},
{a:3,b:5,c:7}];
The check function works always, and the console response as
TypeError: winList[i] is undefined
While Debugging I found after this error the ComputerMove() function never gets called.
So please help.
Your winList array has a length of 8, with an index spanning from 0 - 7.
Your loop for (var i =0 ; i <= 8;i++) tries to access the winList[8] (when the i == 8), which is undefined - thus crashing the script when you try to access a of undefined (winList[i].a).
Try changing your loop condition to the following: for (var i = 0 ; i < 8; i++)
I have a function which works just fine the first if I call it just once, but when I call it repeatedly within a for loop, I get the following error:
TypeError: getNamedRange is not a function, it is string.
Doing a search on this error gives me a clue that this is a javascript error, not a Google Apps Script error. I haven't worked much with javascript, but I suspect it may have something to do with how I return the value from the function.
This is the code which calls the function:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var baseSheet = ss.getSheetByName("Base");
var catCol = 9;
var riskAreaColumn = 10;
var numRows = baseSheet.getDataRange().getNumRows();
// I am not using this var, should I be?
var data = baseSheet.getDataRange().getValues();
var cell;
var rangeName;
var range;
var rule;
for(var i=2; i<numRows; i++){
cell = baseSheet.getRange(i, riskAreaColumn);
rangeName = getNamedRange("CategoryRiskRange",baseSheet.getRange(i, catCol).getValue());
range = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(rangeName);
rule = SpreadsheetApp.newDataValidation().requireValueInRange(range).build();
cell.setDataValidation(rule);
}
SpreadsheetApp.flush();
}
This is the function being called:
function getNamedRange(categoryRange, category) {
var categoryList = SpreadsheetApp.getActive().getRangeByName(categoryRange).getValues();
for (var i = 0; i < categoryList.length; i++) {
if (categoryList[i][0] == category) {
getNamedRange = categoryList[i][1];
return getNamedRange;
}
}
}
The first time through the for loop works, the second time gives me the aforementioned error. Thank you for reading this, I hope it's clear.
you are overwriting the function definition here:
getNamedRange = categoryList[i][1];
this will work:
if (categoryList[i][0] == category) {
return categoryList[i][1];
}
Javascript doesn't interpret things until it gets to them, and is very happy to redefine things when you tell it to.
The first time through, it sees
function getNamedRange(categoryRange, category)
and says "oh, a function! Cool!" But in that function, you have the line
getNamedRange = categoryList[i][1];
and it says "Oh, so getNamedRange is something else now. Okay, I'm fine with that."
Rename your variable, and you should be fine.
function createTextFields(obj) {
for (var i = 0; i < obj.length; i++) {
var dataDump = {};
for (var key in obj[i]) {
var textField = Ti.UI.createTextField(pm.combine($$.labelBrown, {
left: 200,
height:35,
value:obj[i][key],
width:550,
keyboardType:Ti.UI.KEYBOARD_NUMBER_PAD,
layout:'horizontal',
backgroundColor:'transparent',
id:i
}));
dataDump[key] = textField.value;
var callback = function (vbKey) {
return function (e) {
dataDump[vbKey] = e.source.value;
};
}(key);
}
globalData.push(dataDump);
}
}
I am using the simlar code for Adding the data and it works fine. I posted the problem yesterday and it got resolved...
Last Object is always getting updated?
Now when i go to edit page, it shows me four text fields or number of text fields added... now when i edit something and click on save... the value get's updated on the fourth or the last TextFields Object...
Don't define functions inside loops. Computationally expensive and leads to problems, like this one. Here's a fix that should solve it:
function createTextFields(obj) {
var callback = function (vbKey, localDump) {
return function (e) {
localDump[vbKey] = e.source.value;
};
}
var i;
var max = obj.length;
for (i = 0; i < max; i++) {
var dataDump = {};
for (var key in obj[i]) {
dataDump[key] = textField.value;
var callBackInstance = function(keyn, dataDump);
}
globalData.push(dataDump);
}
}
JavaScript does not have block level scope, so your variables dataDump and callback, though "declared" inside for-loops actually belong to the function. As in, you're saving a value to dataDump, then you're overwriting it, each time you go through the loop. Which is why finally only the code that operated on the last value remains.
Take a look at What is the scope of variables in JavaScript? too.