Search code examples
javascripthtmlvariablesuser-input

Use a JavaScript user-inputted variable more than only the first time in HTML


I'm making a game with HTML/CSS and JavaScript, and would like players to enter their name into a text input field. After they enter their name, I would like to save that name as a variable and continuously use it throughout the entire game, not just once. For clarity's sake, I am using a separate file for all JavaScript because I like having the JavaScript separate from my HTML and would prefer not to use <script> tag - although if it will be easier to use <script> tag then I guess I'll be fine with that.

Example of what I'd like to accomplish:

  • Player enters their name, let's say, Abc
  • The game saves the name Abc and for the entire rest of the game, uses that user input (Abc) to talk directly to the player: "Hello, Abc." or "Abc, that was a good choice" etc.

I first made a function in my JavaScript file, where I declared a variable that would retrieve the user input in my HTML. Another variable would be used to insert itself into the HTML, to show the player's inputted name.

After that, I created an if-statement that would check if the player inputted anything, and if they had, the result and input would be equal to each other. I then coded the submit button for this input. This attempt only displayed the user inputted name for the first instance, inside the <h2> Your name is <span id = 'resultingInput'></span> ? </h2>. However, it was empty for the second instance I tried using the same user input, <p>Thank you, <span id = 'resultingInput'></span> . </p> In the very next section of the game, the input wasn't shown as well. Only the very first usage of the user inputted variable displayed what the user actually inputted, the rest were just blank. This first attempt is shown below:

HTML attempt 1

<form id = 'form'>
   <input type = 'text' id = 'userInput'/>


   <button type = 'submit' id = 'submitButton'> 
      <a href = '#submit-input'> enter this name </a>
    </button> 

 </form> 

<div id = 'submit-input' class = 'event'>
   <h2> Your name is <span id = 'resultingInput'></span> ? </h2>
    
   <p>Thank you, <span id = 'resultingInput'></span> . </p> 
     
</div>

JavaScript attempt 1

$(document).ready(function() {
  function getName() {

    var input = document.getElementById('userInput').value;
    var result = document.getElementById('resultingInput');

        if (input.length > 0) {
            result.textContent = input;
        }


   }


    var submit = document.getElementById('submitButton');
    submit.addEventListener('click', getName); 

    getName();

});

Result attempt 1 Image of result of code, with words "Your name is Abc? Thank you. ,

Attempt 2 had the same exact results as Attempt 1. After this attempt, I remembered that id's were unique, and that they couldn't really be used twice. So, I tried to use classes instead of id's, but going about the logic in a similar way. This second attempt is shown below. Also, instead of using "resultingInput" and "result" in this attempt, I used "player" and "playerName" in order to differentiate the two attempts. Sorry for any confusion.

HTML attempt 2

<form id = 'form'>
   <input type = 'text' id = 'userInput'/>


   <button type = 'submit' id = 'submitButton'> 
      <a href = '#submit-input'> enter this name </a>
    </button> 

 </form> 

<div id = 'submit-input' class = 'event'>
   <h2> Your name is <span class = 'player'></span> ? </h2>
    
   <p>Thank you, <span class = 'player'></span> . </p> 
     
</div>

JavaScript attempt 2

$(document).ready(function() {
  function getName() {

    var input = document.getElementById('userInput').value;
    var playerName = document.getElementsByClassName('player')[0];

        if (input.length > 0) {
            playerName.textContent = input;

        }

   }
    var submit = document.getElementById('submitButton');
    submit.addEventListener('click', getName); 

    getName();

});

Result attempt 2 Image of result of code, with words "Your name is Abc? Thank you. ,

In this second attempt, the same results happened, where only the first instance of the variable that saved the user input was shown. For my third attempt, I found another answer that would use querySelectorAll. The HTML remained the same, but for the third attempt's JavaScript, I did as follows.

JavaScript attempt 3 (HTML stayed the same at attempt 2)

$(document).ready(function() {
  function getName() {

    var input = document.getElementById('userInput').value;
    const playerName = document.querySelectorAll('player');

    for (let i = 0; i < playerName.length; i++) {
       playerName[i].src = input;

   }

    var submit = document.getElementById('submitButton');
    submit.addEventListener('click', getName); 

    getName();

});

Result attempt 3 Image of result of code, with words "Your name is ? Thank you. ,

This was my last attempt, as I found with console.log statements that the code never even made it inside the loop, and as such, not even the first instance of the user input variable (<h2> Your name is <span class = 'player'></span> ? </h2>) was shown. I have looked into .innerHTML as well, but have also ran into problems with this as it will just display the actual HTML or show up blank, rather than show the user input.

What would be a good way to go about solving this issue, as it seems like no matter what I tried or could search up, the HTML will only display the user-inputted variable once, rather than every single time after that.

Thank you very much, and sorry for a long question.


Solution

  • You could store a global state in JavaScript.

    Whenever the name field is re-submitted, just rerender.

    Note: If you are going to use jQuery, avoid using addEventListener, getElementById, querySelectorAll, and modifying DOM elements directly. If you want to do this, then you probably don't need to use jQuery.

    const state = {
      username: null
    };
    
    $('#input-form').on('submit', handleSubmit);
    
    function handleSubmit(e) {
      e.preventDefault(); // Stop page navigation
      updateState({
        username: getFormField($(e.target), 'username').value
      });
      render();
    }
    
    function getFormField($form, name) {
      return $form.serializeArray().find(field => field.name === name);
    }
    
    function updateState(updates) {
      $.extend(state, updates);
    }
    
    function render() {
      $('.player').each(function() {
        $(this).text(state.username);
      });
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <form id="input-form">
      <input type="text" name="username" placeholder="Enter username" />
      <button type="submit">Submit</button>
    </form>
    <div class="event">
      <h2>Your name is <span class="player"></span>?</h2>
      <p>Thank you, <span class="player"></span>.</p>
    </div>

    Here is the jQuery-less version for comparison:

    const state = {
      username: null
    };
    
    document.querySelector('#input-form')
      .addEventListener('submit', handleSubmit);
    
    function handleSubmit(e) {
      e.preventDefault(); // Stop page navigation
      updateState({
        username: getFormField(e.target, 'username').value
      });
      render();
    }
    
    function getFormField(form, name) {
      return form.elements[name];
    }
    
    function updateState(updates) {
      deepAssign(state, updates);
    }
    
    function render() {
      document.querySelectorAll('.player').forEach(player => {
        player.textContent = state.username;
      });
    }
    
    function deepAssign(target, source) {
      Object.keys(source).forEach(key => {
        if (isObject(target[key]) && isObject(source[key])) {
          deepAssign(target[key], source[key]);
        } else {
          target[key] = source[key];
        }
      });
      return target;
    }
    
    function isObject(item) {
      return item && typeof item === 'object' && !Array.isArray(item);
    }
    <form id="input-form">
      <input type="text" name="username" placeholder="Enter username" />
      <button type="submit">Submit</button>
    </form>
    <div class="event">
      <h2>Your name is <span class="player"></span>?</h2>
      <p>Thank you, <span class="player"></span>.</p>
    </div>