Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Trent Stenoien
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Trent Stenoien
Full Stack JavaScript Techdegree Graduate 21,632 Points

For loop returning value of null from an array. How do I fix this?

I created a Yahtzee game as a challenge for myself and turns out it's quite a bit more challenging than I thought. I have 99% of the code done, but I'm having trouble with one last thing and I was hoping I could get some help.

What's happening is that as the user uses different options on the scorecard, I replace the HTML radio input with a string, '---'.

tr.firstElementChild.innerHTML = '---';

When I go to loop through the radio buttons, my function returns the first one that's been replaced and overwrites the score in place. For example if I score 1 then 2, the first round will be fine then when I score the second round, upperScores[one] is overwritten and the following error shows. "Uncaught TypeError: Cannot read property 'parentNode' of null at printTR (functions.js:80) at HTMLButtonElement.<anonymous> (htmlElements.js:48)"

Let's dig into the code. I'm storing the radio buttons in an array. And scrolling through to find the checked button.

//Find all radio buttons on the document and store them as an array. I have no other <input> elements besides radio buttons.
const radioInput = document.querySelectorAll('input');

//For loop intended to return the checked radio button. This is what breaks down when it runs into a missing index
const scrollInput = () => {
    for (let i = 0; i < radioInput.length; i++) {
        if (radioInput[i].checked) {
            return radioInput[i];
        };
    };
};

//This triggers the prior function. If no scoring option (radio button) is selected, you receive an alert, otherwise run the scoring function and print the new values to the page
//This event listener should be fine, I believe the problem needs to be handled either in scrollInput() with a conditional statement or in removeRadio() by removing the element from the array
scoreButton.addEventListener('click', function() {
    let element = scrollInput();
    if (!element) {
        alert('Please choose a scoring option.');
    } else {
        score[element.id]();
        printTR(element);
    };
});

//This is option 2, figure out some way to remove radioInput[i] (here, stored as 'element') from the array
const removeRadio = (element, tr) => {
    //if scoring anything besides Yahtzee, or if you threw away your yahtzee score, replace the radio button
        //You can potentially score multiple Yahtzees so that's what this is
    if (element.id !== 'yahtzee' || ((lowerScores.yahtzee === 0) || overwriteYahtzee === true)) {
        tr.firstElementChild.textContent = '---';
        //code to remove element from the array
    };
};

//This is specifically where the code breaks; you can't call parentNode on null.
const printTR = (element) => {
    let tr = element.parentNode.parentNode.parentNode;
    removeRadio(element, tr);
    printOneScore(element, tr);
};

If you need other info let me know, but this should be enough right? I know that when I scroll through a radioInput[0] and it doesn't exist it returns null clearly has no parentNode, but I'm trying to figure out the best way around that. Do I splice? Use a conditional statement to get around the missing radio button? Combination? Something else? I feel like I'm close, but I'm having trouble with the syntax. Any help would be appreciated!

EDIT: Added comments in the script to explain what I'm doing and one more function that might be at fault. I'll try to post the full project on GitHub later.

EDIT2: Here you go! Full project! https://github.com/TJaySteno/Yahtzee

Charles Wanjohi
Charles Wanjohi
9,235 Points

It could help if you provided the entire code for easier understanding

2 Answers

Steven Parker
Steven Parker
231,072 Points

When scrollInput does not return a value, the test should cause an alert instead of calling printTR. So it doesn't look like the cause of the issue is present in this code snippet.

To facilitate a complete analysis, always provide complete code (including HTML and CSS if used). If using workspaces, you can make a snapshot of your workspace and post the link to it here. to share all the code at once.

Trent Stenoien
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Trent Stenoien
Full Stack JavaScript Techdegree Graduate 21,632 Points

It's coming up on 1000 lines of code spread over 5 .js files, a css file, and an html file. I'll try to post it on GitHub or something, but I felt it was too much to post everything here.

I know the problem has to do with attempting to read an array index that's supposed to contain an HTML element that doesn't exist anymore, but I don't know how to fix it.

EDIT: Full project can be found here https://github.com/TJaySteno/Yahtzee

Steven Parker
Steven Parker
231,072 Points

Ahh — so much easier when the program can be run.

So I was half right, the test should have caused an alert instead, but that wasn't happening because the button(s) that had been "removed" were still part of the radioInput collection, and still checked.

So a quick fix would be to add a line to this function:

const removeRadio = (element, tr) => {
    if (element.id !== 'yahtzee' || ((lowerScores.yahtzee === 0) || overwriteYahtzee === true)) {
        element.checked = false;                  // add this line to un-check the hidden button
        tr.firstElementChild.textContent = '---';
    };
};

Note that modifying textContent of a parent orphans any children but does not destroy them.

Steven Parker
Steven Parker
231,072 Points

Program code is very sensitive. It can take only a single letter typo to completely break it!