Why does one function works, but the other does not? - javascript

This one works, it shows the table:
When I put .style.display = "tablerow", the function works
var getMain = document.getElementById("main").style.display = "table-row";
var getLocalStorage = localStorage.hasOwnProperty('tableFill');
for (i = 0; i < getLocalStorage.lenght; i++) {
if (getLocalStorage[i]){
getMain;
But when I put it in in the for loop it doesn't work anymore, but I also get no error at all in the console...
var getMain = document.getElementById("main");
var getLocalStorage = localStorage.hasOwnProperty('tableFill');
for (i = 0; i < getLocalStorage.lenght; i++) {
if (getLocalStorage[i]){
getMain.style.display = "table-row";

localStorage.hasOwnProperty('tableFill') returns true or false. Does not have any length so you won't get into the loop.

localStorage.hasOwnProperty('tableFill') returns a boolean to check if the property exists or not. It does not have data to make a loop out of it

Related

JS Class property "is undefined" even tho it appears to be defined

I'm quite new to JS and I'm trying to do a TicTacToe game with a custom size board in an attempt to learn a bit more. I first coded just a 3x3 version and started building up from there.
Right as I got past the point where I have a custom grid size entered right after loading the page and the grid rendering, I started getting the same problem when trying to click any cell to try and play a turn.
"this.game_state[clicked_cell_i] is undefined".
I have tried opening up F12 and checking if the game_state array (which is a 2d array of strings that tracks which cell is played and which isn't) but when I do everything seems normal and the array gets printed out without problem. (picture showcases printing out the game_state array in a 4x4 grid) https://i.stack.imgur.com/gV0pY.png
I would really appreciate it if somebody could explain to me what's happening or even better - help me fix it. Thanks :)
Code: https://jsfiddle.net/z8649pxL
class game {
status_display;
is_game_active;
curr_player;
game_state;
constructor() {
this.status_display = document.querySelector('.status');
this.is_game_active = true;
this.curr_player = "X";
this.game_state = matrix(rows, rows, "");
}
cell_played(clicked_cell, clicked_cell_i, clicked_cell_j){
this.game_state[clicked_cell_i][clicked_cell_j] = this.curr_player;
clicked_cell.innerHTML = this.curr_player;
if(this.curr_player === "X"){
document.getElementById((i*rows)+j).style.backgroundColor = "#ff6600";
} else if(this.curr_player === "O"){
document.getElementById((i*rows)+j).style.backgroundColor = "#33ccff";
}
}
cell_click(clicked_cellEvent){
debugger
const clicked_cell = clicked_cellEvent.target;
let clicked_cell_i = parseInt(clicked_cell.getAttribute('i'));
let clicked_cell_j = parseInt(clicked_cell.getAttribute('j'));
if(this.game_state[clicked_cell_i][clicked_cell_j] !== "" || !this.is_game_active) {
return;
}
this.cell_played(clicked_cell, clicked_cell_i, clicked_cell_j);
this.res_validation();
}
};
let ex_game = new game();
function create_grid() {
document.getElementById('hidestart').style.display = "none";
var Container = document.getElementsByClassName("grid");
Container.innerHTML = '';
rows = prompt("n?");
let i = 0, j = 0;
document.documentElement.style.setProperty("--columns-row", rows);
for (i = 0; i < rows ; i++) {
for(j = 0; j < rows; j++){
var div = document.createElement("div");
div.className = "cell";
div.id = (i*rows)+j;
div.setAttribute("cell-index", (i*rows)+j);
div.setAttribute("i", i);
div.setAttribute("j", j);
let wrapper = document.getElementsByClassName("grid");
wrapper[0].appendChild(div);
}
}
document.querySelectorAll('.cell').forEach(cell => cell.addEventListener('click', (e) => {
ex_game.cell_click(e);
e.stopPropagation();
}));
document.getElementById('hidestart').style.display = "block";
}
function matrix(rows, cols, defaultValue){
var arr = [];
// Creates all lines:
for(var i=0; i < rows; i++){
// Creates an empty line
arr.push([]);
// Adds cols to the empty line:
arr[i].push(new Array(cols));
for(var j=0; j < cols; j++){
// Initializes:
arr[i][j] = defaultValue;
}
}
return arr;
}```
When you call
new game()
the constructor is been called of that class.
And in that constructor you are calling matrix which requires the value of rows.
But initially the class do not have any value.
So the state is not getting initialized at that point of time.
That why when you use the array, it is getting undefined.
So to resolve this issue, you could just try to get the object of class game after getting the rows from user, and pass that rows in the arguments when calling the constructor of the class.
let ex_game = new game(rows);
And then using this argument call the function matrix.
Edit:
I have looked into your code.
The error is in the method called cell_played. you are using i and j which are not known to it. Please replace your code with following line. This would resolve your error.
cell_played(clicked_cell, clicked_cell_i, clicked_cell_j){
this.game_state[clicked_cell_i][clicked_cell_j] = this.curr_player;
clicked_cell.innerHTML = this.curr_player;
if(this.curr_player === "X"){
document.getElementById((clicked_cell_i*rows)+clicked_cell_j).style.backgroundColor = "#ff6600";
} else if(this.curr_player === "O"){
document.getElementById((clicked_cell_i*rows)+clicked_cell_j).style.backgroundColor = "#33ccff";
}
}
And also remove the parameter rows from constructor and just call the constructor after taking the number of rows from user.
let ex_game
function create_grid() {
/* document.getElementById('hidestart').style.display = "none" */
var Container = document.getElementsByClassName("grid");
Container.innerHTML = '';
rows = prompt("n?");
let i = 0, j = 0;
ex_game= new game().........

For loop only running once in openFile function

I'm trying to use a function to read an external file and split segments of it into an array using a for loop. For some reason the for loop only occurs once and I cant figure out why for the life of me.
I've tried commenting out sections of the code to see if anything in particular is causing it but I cant seem to isolate it exactly
function nthIndex(str, pat, n){ //just used to put string of hsl values from txt file into cArray
var L= str.length, i= -1;
while(n-- && i++<L){
i= str.indexOf(pat, i);
if (i < 0) break;
}
return i;
}
function openFile(event){
var input = event.target;
var r = new FileReader();
r.readAsText(input.files[0]);
r.onload = function(){
var text = r.result;
var n = 3;
var index1 = 0;
var index2 = nthIndex(text,",",n)
for(c=0;c<361;c++){ //WHY DOESNT THIS LOOP
var value = text.slice(index1, indexOf(",",index2));
cArray.push(value);
index1 = indexOf(",",index2);
index2 = nthIndex(text,",",n+3);
}
window.alert(cArray[0];
window.alert(cArray[360];)// just to test
draw(cArray)} // this isnt relavent
};
The result should show an alert the first and last element in the cArray array but it doesnt show at all. What could be the issue?

Strange behaviour in the if statement

I have a piece of code that is meant to hide table elements depending on given array. I am running loops to compare innerText of one of the cells and the given array.
However, my if statement is statement is acting weird, once i set the operator to === the operation is successful and table rows that match the array are hidden. But i need my if to hide the elements that are not a part of the array, so naturally I set my operator to !== but once i do it it just executes anyway and of course hides all of the elements in the table.
Any idea why this is happening here is the code:
var td1 = document.querySelectorAll("#course");
var rowss = document.querySelectorAll("#rows");
var courseNames1 = [td1.innerText];
var diff = _.difference(soretedArray, courseNames1)
console.log(diff);
for (var i = 0; i < rowss.length; i++) {
for (var j = 0; j < diff.length; j++) {
if (td1[i].innerText === diff[j]) { // if i set the logic operator to !== it hides all of the elements rather the ones that don't match
console.log(rowss[i]);
rowss[i].style.display = "none";
break;
}
}
}
I added the code as I have understood your request: You want the negation of "contains" to hide the element. This is as complete as possible based on the information you gave.
var soretedArray = [];//initialized elsewhere
var td1 = document.querySelectorAll("#course");
var rowss = document.querySelectorAll("#rows");
function tdContains(td) {
for(var j= 0 ; j< soretedArray.length; j++){
if(td.innerText === soretedArray[j]){
return true;
}
}
return false;
}
for(var i = 0 ; i < rowss.length; i++){
if(!tdContains(td1[i])) {
console.log(rowss[i]);
rowss[i].style.display= "none";
}
}

undefined parameter in js

I am receiving a type error stating that the array testA[i] is undefined whenever I add an input into the html page. I have the array set and i'm trying to add the value of currency to the array using the push method to add to the second part of the array i.e([0][currency])
function Test() {
var testA = [];
for (i = 0; i < 4; i++) {
this.currency = prompt("Please enter a 3-letter currency abbreviation", "");
testA[i].push(currency);
}
}
var index = new Test();
any help as to why the array is undefined would be appreciated.
Note: I have now tried both testA.push(currency) and testA[i] = this.currency, and I still get the same error as before.
Note: the final version should have it loop through 4 different questions asked and each time adding these into an array. At the end of the loop a new variant of the array should be made and the new set of data entered will be added to it. something like
for(i = 0; i < 4; i++) {
testA[i] = i;
for(j = 0; j < 4; j++) {
this.currency = prompt("Please enter a 3-letter currency abbreviation", "");
testA[i][j] = this.currency;
}
}
but at this point in time I'm just trying to get it to work.
You don't use the push method on a index. You use it on the array itself.
Replace this
testA[i].push(currency);
With this
testA.push(currency);
You need to perform push operation on the array directly.
testA.push(currency);
By executing testA[index] you will receive hold value. In JS it will always return undefined, if index is greater than array length.
Because your array is empty as the beginning, you are always receiving undefined.
You are mixing up two different implementation.
Either you use direct assignation.
var testA = new Array(4);
for (i = 0; i < 4; i += 1) {
this.currency = prompt('...', '');
testA[i] = this.currency;
}
Either you push new values into the array.
var testA = [];
for (i = 0; i < 4; i += 1) {
this.currency = prompt('...', '');
testA.push(this.currency);
}
You should use the second one, which is the most simple soluce.
testA[i] = this.currency OR testA.push(this.currency)
Use Modified function below
function Test() {
var testA = [];
for (i = 0; i < 4; i++) {
this.currency = prompt("Please enter a 3-letter currency abbreviation", "");
testA[i] = this.currency; // use this.currency here if you
}
console.log(testA);
}
var index = new Test();

indexOf() : is there a better way to implement this?

EDIT
Thank you guys, and i apologize for not being more specific in my question.
This code was written to check if a characters in the second string is in the first string. If so, it'll return true, otherwise a false.
So my code works, I know that much, but I am positive there's gotta be a better way to implement this.
Keep in mind this is a coding challenge from Freecodecamp's Javascript tree.
Here's my code:
function mutation(arr) {
var stringOne = arr[0].toLowerCase();
var stringTwo = arr[1].toLowerCase().split("");
var i = 0;
var truthyFalsy = true;
while (i < arr[1].length && truthyFalsy) {
truthyFalsy = stringOne.indexOf(stringTwo[i]) > -1;
i++
}
console.log(truthyFalsy);
}
mutation(["hello", "hey"]);
//mutation(["hello", "yep"]);
THere's gotta be a better way to do this. I recently learned about the map function, but not sure how to use that to implement this, and also just recently learned of an Array.prototype.every() function, which I am going to read tonight.
Suggestions? Thoughts?
the question is very vague. however what i understood from the code is that you need to check for string match between two strings.
Since you know its two strings, i'd just pass them as two parameters. additionally i'd change the while into a for statement and add a break/continue to avoid using variable get and set.
Notice that in the worst case its almost the same, but in the best case its half computation time.
mutation bestCase 14.84499999999997
mutation worstCase 7.694999999999993
bestCase: 5.595000000000027
worstCase: 7.199999999999989
// your function (to check performance difference)
function mutation(arr) {
var stringOne = arr[0].toLowerCase();
var stringTwo = arr[1].toLowerCase().split("");
var i = 0;
var truthyFalsy = true;
while (i < arr[1].length && truthyFalsy) {
truthyFalsy = stringOne.indexOf(stringTwo[i]) > -1;
i++
}
return truthyFalsy;
}
function hasMatch(base, check) {
var strOne = base.toLowerCase();
var strTwo = check.toLowerCase().split("");
var truthyFalsy = false;
// define both variables (i and l) before the loop condition in order to avoid getting the length property of the string multiple times.
for (var i = 0, l = strTwo.length; i < l; i++) {
var hasChar = strOne.indexOf(strTwo[i]) > -1;
if (hasChar) {
//if has Char, set true and break;
truthyFalsy = true;
break;
}
}
return truthyFalsy;
}
var baseCase = "hello";
var bestCaseStr = "hey";
var worstCaseStr = "yap";
//bestCase find match in first iteration
var bestCase = hasMatch("hello", bestCaseStr);
console.log(bestCase);
//worstCase loop over all of them.
var worstCase = hasMatch("hello", worstCaseStr);
console.log(worstCase);
// on your function
console.log('mutation bestCase', checkPerf(mutation, [baseCase, bestCaseStr]));
console.log('mutation worstCase', checkPerf(mutation, [baseCase, worstCaseStr]));
// simple performance check
console.log('bestCase:', checkPerf(hasMatch, baseCase, bestCaseStr));
console.log('worstCase:', checkPerf(hasMatch, baseCase, worstCaseStr));
function checkPerf(fn) {
var t1 = performance.now();
for (var i = 0; i < 10000; i++) {
fn(arguments[1], arguments[2]);
}
var t2 = performance.now();
return t2 - t1;
}

Categories

Resources