Build a Palindrome Checker Project - Build a Palindrome Checker

Tell us what’s happening:

Hi community!
Could you help me what am i doing wrong? The browser console says Uncaught TypeError: Cannot read properties of null (reading ‘addEventListener’), fCC console says: Uncaught TypeError: Cannot read properties of null (reading ‘value’)
[TypeError: Cannot read properties of undefined (reading ‘trim’)]
So I thought i didn’t link the html and the js file correctly, Before the link was i the body, now it’s in the head, but it’s not working and I don’t know what I am doing wrong.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
    <title>Palindrome Checker</title>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>

  <body>
    

    <input id="text-input" placeholder="Enter what to test"></input>

    <button id="check-btn">Test</button>

    <div>
      <h1>Result:</h1>
      <p id="result"></p>
    </div>

  </body>
</html>
/* file: script.js */
const inputField = document.getElementById("text-input")
const checkButton = document.getElementById("check-btn")
const result = document.getElementById("result")
const inputText = inputField.value;

checkButton.addEventListener('click', noInputAlert);
checkButton.addEventListener('click', removeNonAlphanumeric);
checkButton.addEventListener('click', checkPalindrome);

function noInputAlert () {
  if (inputText === "") {
    window.alert("Please input a value");
  }
}

function removeNonAlphanumeric(inputText) {
    inputText = inputText.split('').filter(char => /[a-zA-Z0-9]/.test(char)).join('');
    inputText.upperCase();
}

const inputArr = removeNonAlphanumeric(inputText);
console.log(result);

function checkPalindrome () {
  let reversedText = inputArr.toReverse()
  if (reversedText === inputField) {
    result.innerText = `${inputText} is a palindrome`
  } else {
    result.innerText = `${inputText} is not a palindrome`
  }

  /*
  let length = inputField.length;
  if (length === 1) {
    result.innerText = `${inputField} is a palindrome`
  }*/
}


/* file: styles.css */

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36

Challenge Information:

Build a Palindrome Checker Project - Build a Palindrome Checker

Hi there! Check the href value. You have missing a s in styles.

Hi, thanks for your reply! True and corrected.
But I haven’t even started to write any css yet. It’s the js part that’s not functioning.
Could you check that too please?

By accessing inputField.value globally here, inputText always be an empty string, as it’s reading the value before any user input is received. You’ll want to access inputField.value only after the user has clicked the Check button (i.e. inside your checkPalindrome function).

Also, you really don’t want several click events for the same button. You’d be better if the Check button fired the checkPalindrome function only. You can call the other functions from within this main function.

You also have some other issues:

  1. removeAlphaNumeric doesn’t return a value so you will get a lot of undefined errors when you try to incorporate it in checkPalindrome.
  2. toReverse is not a function. It is toReversed. Also, this is an array method, so won’t work on string values.

There are some other issues but fixing these ones will set you on the right path.

TIP: I would defined your inputText variable at the top of checkPalindrome. Then you can pass it to your other functions (e.g. noInputAlert) within this function.

Thanks for your tips! I didn’t know you shouldn’t call so many onlock events. I found on w3schools that it’s possible.
I updated what you mentioned, but the console still says the same. What are the other topics i must correct that you mentioned? Sorry but i ma learning on my own and don’t know whom to ask.

// console output
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
[TypeError: Cannot read properties of undefined (reading 'trim')]
const inputField = document.getElementById("text-input")
const checkButton = document.getElementById("check-btn")
const result = document.getElementById("result")

checkButton.addEventListener('click', checkPalindrome);

function checkPalindrome () {
  noInputAlert();
  const inputText = inputField.value;
  removeNonAlphanumeric();
  const inputArr = removeNonAlphanumeric(inputText);
  let reversedText = inputArr.toReversed()
  if (reversedText === inputField) {
    result.innerText = `${inputText} is a palindrome`
  } else {
    result.innerText = `${inputText} is not a palindrome`
  }

function noInputAlert () {
  if (inputText === "") {
    window.alert("Please input a value");
  }
}

function removeNonAlphanumeric(inputText) {
    inputText = inputText.split('').filter(char => /[a-zA-Z0-9]/.test(char)).join('');
    inputText.upperCase();
    return inputText;
}

  /*
  let length = inputField.length;
  if (length === 1) {
    result.innerText = `${inputField} is a palindrome`
  }*/
}

I’ve edited your code for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

Thanks for that! Now I know :slight_smile:
Still unsure why it’s not working. As per the console message I would think, the 2 files aren’t correctly linked (copied HTML below). Should I somehow modify my HTML too?
JS

const inputField = document.getElementById("text-input")
const checkButton = document.getElementById("check-btn")
const result = document.getElementById("result")

checkButton.addEventListener('click', checkPalindrome);

function checkPalindrome () {
  noInputAlert();
  const inputText = inputField.value;
  removeNonAlphanumeric();
  const inputArr = removeNonAlphanumeric(inputText);
  let reversedText = inputArr.toReversed()
  if (reversedText === inputField) {
    result.innerText = `${inputText} is a palindrome`
  } else {
    result.innerText = `${inputText} is not a palindrome`
  }

function noInputAlert () {
  if (inputText === "") {
    window.alert("Please input a value");
  }
}

function removeNonAlphanumeric(inputText) {
    inputText = inputText.split('').filter(char => /[a-zA-Z0-9]/.test(char)).join('');
    inputText.upperCase();
    return inputText;
}

  /*
  let length = inputField.length;
  if (length === 1) {
    result.innerText = `${inputField} is a palindrome`
  }*/
}

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
    <title>Palindrome Checker</title>
    <link rel="stylesheet" href="styles.css">
    <script src="script.js"></script>
  </head>

  <body>
    

    <input id="text-input" placeholder="Enter what to test"></input>

    <button id="check-btn">Test</button>

    <div>
      <h1>Result:</h1>
      <p id="result"></p>
    </div>

  </body>
</html>
```

You’re right, you can have multiple event listeners on a single button. In cases like this however, I find it cleaner to fire a single function for a button click. I guess that’s just my preference.

Ok, let’s break this down:

function noInputAlert () {
  if (inputText === "") {
    window.alert("Please input a value");
  }
}

This function cannot access inputText before it is declared, so you’ll need to define inputText before you call it. Also, there is an issue in that the regardless of how you trigger the alert, the rest of the checkPalindrome function will execute when textInput is empty. It may be easier to use a simple conditional statement instead of calling this as a separate function, so that you can return out of the checkPalindrome function (after triggering the alert) when the user doesn’t input a value.

You don’t need the first removeNonAlphanumeric call. You only need to trigger it when you define inputArr. The other issue here is that the value returned by this function is a string, not an array, so you can’t then apply the toReversed method to it, as it stands. Also, upperCase is not a valid method. It’s toUpperCase.

This conditional statement is not working as inputField is a reference to the HTML element, not to its value:

if (reversedText === inputField) 

Also, you’ll need to compare the reversed text with the original input value once the non-alphanumeric characters have been removed. So you’d be better off removing these first and only then comparing the string with its reverse.

Thanks for your valuable inputs. I went through your suggestions, but still have some questions.
How should I interpret what the console says?
// console output
Uncaught TypeError: Cannot read properties of null (reading ‘value’)
[TypeError: Cannot read properties of undefined (reading ‘trim’)]

  1. function cannot access inputText before it is declared, so you’ll need to define inputText before you call it - made it global, is that okay?

  2. It may be easier to use a simple conditional statement instead of calling this as a separate function, so that you can return out of the checkPalindrome function (after triggering the alert) when the user doesn’t input a value. - done

  3. You don’t need the first removeNonAlphanumeric call. You only need to trigger it when you define inputArr. - done

  4. The other issue here is that the value returned by this function is a string, not an array, so you can’t then apply the toReversed method to it, as it stands. - Is the split method the right one to use in this case?

  5. Also, upperCase is not a valid method. It’s toUpperCase. - ok

  6. This conditional statement is not working as inputField is a reference to the HTML element, not to its value - done

  7. Also, you’ll need to compare the reversed text with the original input value once the non-alphanumeric characters have been removed. So you’d be better off removing these first and only then comparing the string with its reverse. - Updated, is this what you meant?

const inputField = document.getElementById("text-input")
const checkButton = document.getElementById("check-btn")
const result = document.getElementById("result")
const inputText = inputField.value;


checkButton.addEventListener('click', checkPalindrome);

function checkPalindrome () {
  noInputAlert();
    if (inputText === "") {
      window.alert("Please input a value");
      return;
    }
  
  const inputArr = removeNonAlphanumeric(inputText);
  let reversedText = inputArr.toReversed()
  if (reversedText === inputText) {
    result.innerText = `${inputText} is a palindrome`
  } else {
    result.innerText = `${inputText} is not a palindrome`
  }

/*
function noInputAlert () {
  if (inputText === "") {
    window.alert("Please input a value");
  }
}
*/

function removeNonAlphanumeric(inputText) {
    let cleanInput = inputText.replace(/[^a-zA-Z0-9]/g, '').trim();
    cleanInput.toUpperCase();
    return cleanInput.split(" ");
}

  /*
  let length = inputField.length;
  if (length === 1) {
    result.innerText = `${inputField} is a palindrome`
  }*/
}

That global constant variable will not works within the local code block. Declared it within the required function.

toReverse() is not works on string value.

That trim() is not required. Make the input replace, and case formation (upper/lower) on clearInput assignment. split and reverse and join it, when you need to reverse it.

Yes, as I explained before, you’ll need to access inputField.value after the user clicks the Check button, so you can’t set it as a global variable. Instead, declare the textInput variable right at the top of your checkPalindrome function.

Then a logical approach would be:

  1. Check if user input is empty, trigger alert and exit function if so.
  2. Remove non-alphanumeric characters from user input and convert to lower/upper case.
  3. Create a reversed copy of the string and compare the two strings.

Hi again!
Thanks for your asnwer a lot, here are my remarks:

  • Check if user input is empty, trigger alert and exit function if so. - done
  • Remove non-alphanumeric characters from user input and convert to lower/upper case. - This was done in removeNonAlphanumeric function, also removed the trim() as hasanzaib1389 suggested above. I know already that toReversed() doesn’t work on strings, that’s why I used the split method. Is that not right?
  • Create a reversed copy of the string and compare the two strings. - I believe I did this or is it not done properly?
    [/quote]
    I find the console output confusing though, it still mentions trim, even though this was remeoved and I don’t know why the addeventlistener is referenced.
    console:
    Uncaught TypeError: Cannot read properties of null (reading ‘addEventListener’)
    [TypeError: Cannot read properties of undefined (reading ‘trim’)]
const inputField = document.getElementById("text-input")
const checkButton = document.getElementById("check-btn")
const result = document.getElementById("result")

checkButton.addEventListener('click', checkPalindrome);

function checkPalindrome () {
  const inputText = inputField.value;
  if (inputText === "") {
      window.alert("Please input a value");
      return;
    }
  const inputArr = removeNonAlphanumeric(inputText);
  let reversedText = inputArr.toReversed()
  if (reversedText === inputText) {
    result.innerText = `${inputText} is a palindrome`
  } else {
    result.innerText = `${inputText} is not a palindrome`
  }

function removeNonAlphanumeric(inputText) {
    let cleanInput = inputText.replace(/[^a-zA-Z0-9]/g, '');
    cleanInput.toUpperCase();
    return cleanInput.split(" ");
}
}

Code within the function isn’t correct. You should chain the .toUpperCase() method to .replace(). And in the return statement you should reverse and join the string after split it using chain method.

Remove the above declaration and assignment.

Within the if condition, add inputArr as a condition.

Thanks a lot! I finally managed to solve this task :cold_sweat:

2 Likes