What could be causing the malfunction in my JavaScript random selector?

Can anyone assist me with this issue? I'm attempting to implement JavaScript functionality to highlight randomly selected picks that I input, but it's not functioning correctly.

Every time I inspect my JS code on the webpage, I encounter an error message that reads:

"Uncaught TypeError: Cannot read properties of undefined (reading 'classList')
    at highlightTag (script.js:52:9)
    at script.js:38:9" 

Here is the complete code snippet below:

const tagsEl = document.getElementById('tags')
const textarea = document.getElementById('textarea')

textarea.focus()

textarea.addEventListener('keyup', (e) => {
  createTags(e.target.value)

  if (e.key === 'Enter') {
    setTimeout(() => {
      e.target.value = ''
    }, 10)

    randomSelect()
  }
})

function createTags(input) {
  const tags = input.split(',').filter(tag => tag.trim() !==
    '').map(tag => tag.trim())

  tagsEl.innerHTML = ''

  tags.forEach(tag => {
    const tagEl = document.createElement('span')
    tagEl.classList.add('tag')
    tagEl.innerText = tag
    tagsEl.appendChild(tagEl)
  })
}

function randomSelect() {
  const times = 30

  const interval = setInterval(() => {
    const randomTag = pickRandomTag()

    highlightTag(randomTag)

    setTimeout(() => {
      unHighlightTag(randomTag)
    }, 100)
  }, 100);
}

function pickRandomTag() {
  const tags = document.querySelectorAll('.tag')
  return tags[Math.floor(Math.random() * tags.length)]
}

function highlightTag(tag) {
  tag.classList.add('hightlight')
}

function unHighlightTag(tag) {
  tag.classList.remove('hightlight')
}
* {
  box-sizing: border-box;
}

body {
  background-color: #2b88f0;
  font-family: 'Roboto', sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  overflow: hidden;
  margin: 0;
}

h3 {
  color: #fff;
  margin: 10px 0 20px;
  text-align: center;
}

.container {
  width: 500px;
}

textarea {
  border: none;
  display: block;
  width: 100%;
  height: 100px;
  font-family: inherit;
  padding: 10px;
  margin: 0 0 20px;
  font-size: 16px;
}

.tag {
  background-color: #f0932b;
  color: #fff;
  border-radius: 50px;
  padding: 10px 20px;
  margin: 0 5px 10px 0;
  font-size: 14px;
  display: inline-block;
}

.tag.highlight {
  background-color: #273c75;
}
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap&ext=.css" rel="stylesheet" />

<div class="container">
  <h3>Enter all of the choices divided by a comma (','). <br> Press Enter when you are done</h3>
  <textarea placeholder="Enter choices here..." id="textarea"></textarea>
  <div id="tags">

  </div>
</div>
<script src="script.js"></script>

Answer №1

The issue at hand arises from the constant creation of intervals. This results in a scenario where an element is removed, causing the random code to attempt selection and finding nothing, thereby causing the problem. To resolve this, it is crucial to cease the intervals when modifying the tags and validate the existence of an element before attempting to reference it when using innerHTML to generate new tags.

const tagsEl = document.getElementById('tags')
const textarea = document.getElementById('textarea')

textarea.focus()

textarea.addEventListener('keyup', (e) => {
  createTags(e.target.value)

  if (e.key === 'Enter') {
    setTimeout(() => {
      e.target.value = ''
    }, 10)

    randomSelect()
  }
})

function createTags(input) {
  const tags = input.split(',').filter(tag => tag.trim() !==
    '').map(tag => tag.trim())

  tagsEl.innerHTML = ''

  tags.forEach(tag => {
    const tagEl = document.createElement('span')
    tagEl.classList.add('tag')
    tagEl.innerText = tag
    tagsEl.appendChild(tagEl)
  })
}

let selectInterval = null;
function randomSelect() {
  const times = 30
  
  // Is there an interval running? cancel it
  if (selectInterval) window.clearInterval(selectInterval);

  selectInterval = setInterval(() => {
    const randomTag = pickRandomTag()
    
    // Do we have something to toggle? If no, exit
    if (!randomTag) return;

    highlightTag(randomTag)

    setTimeout(() => {
      unHighlightTag(randomTag)
    }, 1000)
  }, 1000);
}

function pickRandomTag() {
  const tags = document.querySelectorAll('.tag')
  return tags[Math.floor(Math.random() * tags.length)]
}

function highlightTag(tag) {
  tag?.classList?.add('hightlight')
}

function unHighlightTag(tag) {
  tag?.classList?.remove('hightlight')
}
* {
  box-sizing: border-box;
}

body {
  background-color: #2b88f0;
  font-family: 'Roboto', sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  overflow: hidden;
  margin: 0;
}

h3 {
  color: #fff;
  margin: 10px 0 20px;
  text-align: center;
}

.container {
  width: 500px;
}

textarea {
  border: none;
  display: block;
  width: 100%;
  height: 100px;
  font-family: inherit;
  padding: 10px;
  margin: 0 0 20px;
  font-size: 16px;
}

.tag {
  background-color: #f0932b;
  color: #fff;
  border-radius: 50px;
  padding: 10px 20px;
  margin: 0 5px 10px 0;
  font-size: 14px;
  display: inline-block;
}

.tag.hightlight {
  background-color: #273c75;
}
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap&ext=.css" rel="stylesheet" />

<div class="container">
  <h3>Enter all of the choices divided by a comma (','). <br> Press Enter when you are done</h3>
  <textarea placeholder="Enter choices here..." id="textarea"></textarea>
  <div id="tags">

  </div>
</div>
<script src="script.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Avoid duplicate submissions while still enforcing mandatory fields

Let's start with a basic form that only asks for an email address: <form action="NextPage.php" method="post"> <input type="email" name="contact[email]" required id="frmEmailA" autocomplete="email"> <button type="submit">Subm ...

Ways to display the ChaptersButton in Videojs-Player

I'm trying to incorporate videojs (version 8.10.0) into my project and provide viewers with a way to select chapters within the video. According to the official documentation, it seems that simply including a track element linking to a VTT file within ...

Attempting deletion with Node.js's Mongoose Framework

Having some trouble with the following code snippet. It doesn't seem to be functioning correctly and is resulting in a 404 error. Any insights on how to troubleshoot this issue? app.delete("/tm/v1/tasks", (req,res) => { Task.findOneAndDelete ...

Creating a bot that will only respond once when a user sends multiple photos simultaneously

I'm currently working on a Telegram bot using nodejs. I am utilizing the node-telegram-bot-api library and have implemented the on('photo') method to handle when a user sends a photo to my bot. However, I am facing an issue where if a user ...

Troubleshooting a Laravel 5.2 modal popup issue for password recovery, experiencing a 500 internal server error with the Ajax function execution

Is there a way to check if an email exists in order to send a reset password link using an AJAX function? I keep encountering a 500 internal server error before the AJAX runs. I understand that a 500 error is usually due to a token mismatch, but do I actua ...

Automatically Refresh a Div Element Every 5 Seconds Using jQuery's setInterval() Function

My goal is to refresh the left div every 5 seconds using $.ajax to get JSON data and display 4 random elements in that div. However, even though the left div block refreshes, the content remains the same with the same images always showing. view image desc ...

The use of res.sendFile() in node.js is not recognized

While utilizing node.js along with mySQL, I encountered a problem. Upon starting the server, everything seems to be fine. However, upon accessing 127.0.0.1:3000, an error message stating that res.sendFile() is not defined appears. My intention is to send ...

Proper HTML style linking with CSS

Describing the file structure within my project: app html index.html css style.css The problem arises when trying to link style.css as follows: <link rel="stylesheet" type="text/css" href="css/style.css"/> S ...

Ways to conceal ng repeat using ng if

My autocomplete feature is set up using ng-repeat to display suggestions and ng-click to change the textbox value. However, I am facing an issue where the suggestion does not disappear when the textbox value is already the same as the suggestion. How can I ...

Invoke the parent method within the child application

I have a checkbox on the child app controller. When the user clicks it, I need to call a method from the parent controller: Parent app controller: <div ng-controller="ParentCntr as parentCntr"> <child-app></child-app> </div> C ...

Guide on submitting a multi-step form using jQuery

Greetings, I am in need of assistance with submitting a jQuery step wizard form. Although I have a plugin that helps, it primarily uses jQuery rather than HTML. So far, I have accomplished the following steps: - Set up the necessary database and table - C ...

Using AngularJS to dynamically update the DOM with the response from a service method

Here's the HTML code: <div ng-controller="AutoDeployController as autoDeploy"> <input type="text" ng-model="autoDeploy.message"> <p>Message: {{ autoDeploy.message }}</p> </div> <button ng-click="autoDeploy.chan ...

Trouble persisting values with Heroku due to variable issues

Here is a concise example: let value = null; const getValues = () => { fetch('/third-party-api') .then(res => res.json()) .then(data => { value = data; }) } getValues(); app.get("/values", async (req, res) ...

What is the best way to prevent a form from being submitted and conduct validation using JavaScript?

Encountered a form that is unchangeable in appearance: <form id="mx_locator" name="mx_locator" method="post" action="search-results"> <!-- form elements --> <span><input type="image" src="/images/search.png" onclick="loader()"> ...

Conceal the Angular Material toolbar (top navigation bar) automatically when scrolling downwards

In my Angular application, the main navigation consists of a standard toolbar positioned at the top of the page. My goal is to have this navigation bar smoothly scroll up with the user as they scroll down, and then reappear when they scroll back up. I at ...

Unable to send message to iframe from a different origin

I am encountering an issue with the code below while attempting to post a message and receiving a Blocked autofocusing on a <input> element in a cross-origin subframe. error. import React from 'react' const MyFiles = () => { React.us ...

Customizing the color of a select dropdown in Bootstrap using CSS styling

I am having difficulty changing the default blue color for Bootstrap select dropdowns. Despite trying :hover and :active selectors on both option and select, I have not been successful in making the desired changes. Could anyone provide insight regarding ...

When CSS 3 checkbox value is toggled to "off", it returns as null

I am currently using a checkbox element with the following HTML: <div class="onoffswitch"> <input type="checkbox" name="showOnNavigation" class="onoffswitch-checkbox" id="showOnNavigation" checked> <label class="onoffswitch-label" f ...

Opening the Gmail app from a link using JavaScript

What is the best way to open the Gmail app from a hyperlink? This link opens WhatsApp <a href="https://wa.me/">whatsapp</a> <a href="mailto:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6a1f190f ...

Enhancing the smoothness of parallax scrolling

My header is going to be twice the height of the viewport. I added a simple parallax effect so that when you scroll down, it reveals the content below. However, I'm experiencing flickering in the content as I scroll, possibly due to the CSS style adju ...