Quickpois0n
Quickpois0n

Reputation: 79

Store input after submitting to show it

I am doing a rock, paper and scissors exercise and I just added a form with an input text and an input button to store the user name and show it on the DOM.

The thing is, with console.log($userName.value) it will only show me the value when it is on the box, if I delete it or submit it will show nothing or undefined, I added the form.submit() because I want the user to send the text on the input and then let the input empty (I also tried to set the .value to an empty string but it won't work either way.

I added it to a variable with innerHTML to show it on the DOM but if I clear the input it will show undefined.

I am probably skipping a few steps but I don't know how to get to it. Any guidance would be appreciated.

// Global DOM variables
const $selectBtn = document.querySelectorAll("[data-selector]");
const $displayUserScore = document.querySelector("#user-score");
const $displayComputerScore = document.querySelector("#computer-score")
const $showScore = document.querySelector("h5");
const $theWinnerIs = document.querySelector('#result-winner');
const $refreshBtnContainer = document.querySelector('#refresh-button-container');
const $icons = ["🪨", "🧻", "✂️"];
let $userForm = document.querySelector('#user-form');
let $userName = document.querySelector('#user-name');

// Score vaiables
const choices = ["rock", "paper", "scissors"];
let userScore = 0;
let computerScore = 0;

$userForm.addEventListener('submit', (event) => {
    $newUserName = $userName.value;
    $userForm.submit();
})

// For each button of buttons...
$selectBtn.forEach(function(button){
    
    button.addEventListener("click", function() {
        let computerOption = computerRandom() // Store random computer play on var
        const userOption = button.dataset.selector; // userOption is equal to data-selector attribute
        
        // Invoke functions plays the game and shows final winner.
        playGame(userOption, computerOption);
        theWinner();
        
        // Add function with results
        function playGame(userOption, computerOption) {

            if (userOption === "rock") {
                if (computerOption === "scissors") {
                    userScore++;
                    $displayUserScore.innerHTML = userScore;
                    $showScore.innerHTML = "The machine chooses "+"<span class=\"icon\">" + $icons[2] + "</span>" + ", you BEAT him!";
                } else if (computerOption === "paper") {
                    computerScore++;
                    $displayComputerScore.innerHTML = computerScore;
                    $showScore.innerHTML = "The machine chooses "+"<span class=\"icon\">" + $icons[1] + "</span>" + ", you LOSE!";
                } else if (userOption === computerOption) {
                    $showScore.innerHTML = "Draw!";
                }
            }

            if (userOption === "paper") {
                if (computerOption === "rock") {
                    userScore++;
                    $displayUserScore.innerHTML = userScore;
                    $showScore.innerHTML = "The machine chooses "+"<span class=\"icon\">" + $icons[0] + "</span>" + ", you BEAT him!";
                } else if (computerOption === "scissors") {
                    computerScore++;
                    $displayComputerScore.innerHTML = computerScore;
                    $showScore.innerHTML = "The machine chooses "+"<span class=\"icon\">" + $icons[2] + "</span>" + ", you LOSE!";
                } else if (userOption === computerOption) {
                    $showScore.innerHTML = "Draw!";
                }
            }

            if (userOption === "scissors") {
                if (computerOption === "paper") {
                    userScore++;
                    $displayUserScore.innerHTML = userScore;
                    $showScore.innerHTML = "The machine chooses "+"<span class=\"icon\">" + $icons[1] + "</span>" + ", you BEAT him!";
                } else if (computerOption === "rock") {
                    computerScore++;
                    $displayComputerScore.innerHTML = computerScore;
                    $showScore.innerHTML = "The machine chooses "+"<span class=\"icon\">" + $icons[0] + "</span>" + ", you LOSE!";
                } else if (userOption === computerOption) {
                    $showScore.innerHTML = "Draw!";
                }
            }

        }
        
        // Add a winners text function
        function theWinner() {
            if (userScore === 5) {
                $theWinnerIs.innerHTML = $userName.value;
            } else if (computerScore === 5) {
                $theWinnerIs.innerHTML = "The machine!";
            }
        }

        if (userScore === 5 || computerScore === 5) {
            const $refreshBtn = document.createElement('button');
            $refreshBtn.appendChild(document.createTextNode("Play again!"));
            $refreshBtn.className = "refresh-btn";
            $refreshBtnContainer.appendChild($refreshBtn);
            let len = $selectBtn.length;

            for (let i = 0; i < len; i++) {
                $selectBtn[i].disabled = true;
            }
            
                $refreshBtn.addEventListener('click', () => {
                userScore = 0;
                computerScore = 0;
                $displayUserScore.innerHTML = userScore;
                $displayComputerScore.innerHTML = computerScore;
                $showScore.innerHTML = "";
                $theWinnerIs.innerHTML = "";
                $refreshBtnContainer.innerHTML= "";
                for (let i = 0; i < len; i++) {
                    $selectBtn[i].disabled = false;
                }
            })   
        }

    })
    
})

// Random computer choice
function computerRandom () {
    const randomNumber = Math.floor(Math.random() * choices.length);
    return choices[randomNumber];
}
body {
    box-sizing: border-box;
}

#container {
    text-align: center;
    margin-top: 5%;
}

h2 {
    color:rebeccapurple;
    font-size: 30px;
    letter-spacing: 4px;
    font-style: italic;
}

#user-name {
    margin-bottom: 4em;
    border-radius: 10px;
    padding: .6em;
    outline: none;
    border: none;
}

#submit-name {
    padding: .6em;
    margin-left: .5em;
    background: rebeccapurple;
    border-radius: 10px;
    border: none;
    outline: none;
}

.btn-selector {
    font-size: 4em;
    background: rebeccapurple;
    margin: .1em;
    padding: .2em;
    outline: none;
    border: none;
    cursor: pointer;
    border-radius: 20%;
    transition: 150ms;
}
.btn-selector:hover {
    transform: scale(1.2);
}

#results {
    display: flex;
    justify-content: center;
}

.score {
    margin-right: 1em;
    font-size: 11px;
    font-style: italic;
}

h3 {
    color: rebeccapurple;
    font-style: italic;
    display: flex;
    justify-content: center;
}

h5 {
    margin-top: 7px;
    color: olive;
    font-size: 20px;
    letter-spacing: 3px;
}

.icon {
    font-size: 3em;
}

.refresh-btn {
    padding: .8em;
    background: rebeccapurple;
    font-size: 30px;
    font-style: bold;
    border-radius: 20px;
    border: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rock, paper and scissors</title>
    <link rel="stylesheet" href="style.css">
    <script src="script.js" defer></script>
</head>
<body>
    <div id="container">
        <h2>What is your name?</h2>
        <form id ="user-form">
            <input type="text" id="user-name" placeholder="Please, insert your name..">
            <input type="submit" id="submit-name" value="Enviar">
        </form>
        <button class="btn-selector" data-selector="rock">🪨</button>
        <button class="btn-selector" data-selector="paper">🧻</button>
        <button class="btn-selector" data-selector="scissors">✂️</button>
        <div id="results">
        <h4>You: <span id="user-score" class="score" data-user-score>0</span></h4>
        <h4>Computer: <span id="computer-score" class="score" data-computer-score>0</span></h4>
    </div>
    <h5></h5>
        <div>
            <h3>And the winner is...</h3>
            <h3 id="result-winner"></h3>
        </div>
        <div id="refresh-button-container">    
        </div>
    </div>
</body>
</html>

Thanks a lot.

Upvotes: 0

Views: 832

Answers (3)

zer00ne
zer00ne

Reputation: 44086

Submit Event

There are few things you should be aware of when you have a <form> and you register it to the "submit" event.

  • Default behavior of a <form> is to gather all values of all form controls that are:
    • within the <form> itself
    • OR is associated with the <form> via the form attribute.
    • AND has a name attribute with a valid value. (excluding buttons)
  • Once data is collected, sent to the server, it will expect a response from the server. If there is no server, it will return a blank page (not good UX).
  • The "submit" event is "organically" triggered two ways.
    • The user uses the Return/Enter key when focused on an <input>
    • The user clicks a submit button. The following is what constitutes a submit button:
      • Figure I (Within <form id="X">)
        <button>OK</button>
        <button type='submit'>OK</button>
        <input type='submit'>
        <input type='image' src='https://loremflickr.com/48/24'>
        
      • Figure II (Outside of <form id="X">)
        <button form="X">OK</button>
        <button type='submit' form="X">OK</button>
        <input type='submit' form="X">
        <input type='image' src='https://loremflickr.com/48/24' form="X">
        

Not using a server, I assume that the behavior previously mentioned is undesirable. If so, event.preventDefault() is needed (see Example A)

Closure

Define or declare a variable outside of the function, but within scope. Within scope in this context would just require that the variable be in the "vicinity" of the function to keep things simple see Figure III.

Figure III

let playerName = '';
function eventHandler(event) {//...

Example A

let playerName = '';

function eventHandler(event) {
  // Stop the form from sending to a server
  event.preventDefault();
  // Reference all form controls
  const IO = this.elements;
  // Assign value to variable outside of function
  playerName = IO.username.value;
  // Clear input
  IO.username.value = '';
  console.log(playerName);
}

document.forms.rps.onsubmit = eventHandler;
<form id='rps'>
  <fieldset>
    <legend>Enter Name</legend>
    <input id='username' name='username'><button>OK</button>
  </fieldset>
</form>

The function and everything within the function gets garbage collected, but because you've created a closure by assigning a value from inside a function to a variable outside of the function, that value still resides within the variable after the function terminates. To verify, enter something and submit it. There should be a log entered in the console with the value of whatever you entered. That's during the run of the function, so to really be sure, right-click on the snippet directly and click "inspect", and click the "console" tab. Enter: console.log(playerName) in the console. (See Appendix on Dev Tools)

Hidden <input>

Another way to save values is by using a hidden <input>. The saved value will persist until the page is unloaded or the <input>'s value is reassigned. (see Example B). There are many ways to hide an <input> and there basically 2 types of hidden:

  • Visibly Hidden <input>

    • Users will not see the <input>, but as far as the browser and the DOM is concerned nothing special about said <input>. It takes up space and it is within the layout.
    • Typically, CSS properties such as opacity and visibility hide tags this way. Some hacky ways include, color and background having the same color value or setting lengths to 0 like width, height, font-size, etc. HTML attributes hidden and attribute/value type="hidden" are slightly different in that the latter will be included in a collection during a "submit" event.
  • display: none

    • Users will not see the <input>, nor does it occupy space in the layout. The DOM and browser still "sees" it and access it by normal means. If the <input> was made visible by display:"AnythingButNone" it would pop into existence amid other tags and probably cause unsightly shifting. So this form of hiding is best used for tags you don't plan on making visible.

Since the only reason to use a hidden <input> is to store a value display: none will be the best choice. (see Example B).

Example B

function eventHandler(event) {
  // Stop the form from sending to a server
  event.preventDefault();
  // Reference all form controls
  const IO = this.elements;
  // Assign the value of #username to #player
  IO.player.value = IO.username.value;
  // Clear input
  IO.username.value = '';
  console.log(IO.player.value);
}

document.forms.rps.onsubmit = eventHandler;
<form id='rps'>
  <fieldset>
    <legend>Enter Name</legend>
    <input id='username' name='username'><button>OK</button>
  </fieldset>
  <input id='player' style='display: none'>
</form>

Appendix

DevTools

Firefox Developer Tools

Chrome DevTools

Edge DevTools

Upvotes: 0

adevinwild
adevinwild

Reputation: 298

Not sure if your form will be sent, at least I don't think so.

If you want to display the name of the user or even store this data somewhere to display it somewhere you can do it this way

HTML code

<form id ="user-form">
  <input type="text" id="user-name" placeholder="Please, insert your name.." onchange="registerInput(this);">
  <input type="submit" id="submit-name" value="Enviar">
</form>
<h1>
</h1>

JavaScript code

// Here we initialize a global variable
var playerUsername = ""

let $userForm = document.querySelector('#user-form');
let $userName = document.querySelector('#user-name');


function registerInput(e)
{
    const value = e.value;
    // We assign the value of the input to playerUsername
    // So we can access it globally
    playerUsername = value;
}

$userForm.addEventListener('submit', (event) => {
        event.preventDefault();
        // Here we show the user
        document.querySelector('h1').innerText = 'Hello : ' + inputValue;
        
        // Now let's remove the value of the input
        // We put an empty string 
        $userName.innerValue = ""

        // Well done !

})

Link : https://jsfiddle.net/k49bgu0c/6/

In case you change the .html page you will lose access to this variable, so how to do in this case?

For that you can store the result of your input in the localStorage, this one will allow you to access to the data you have inserted inside, I let you read about the localStorage and how it works

Upvotes: 1

Barmar
Barmar

Reputation: 782564

Use a different variable in the function. There you can use the $userName global variable to access the HTML element, and .value to get its value.

let $userForm = document.querySelector('#user-form');
let $userName = document.querySelector('#user-name');

$userForm.addEventListener('submit', (event) => {
  const name = $userName.value;
  console.log(name);
  $userForm.submit();
})
<form id="user-form">
  <input type="text" id="user-name" placeholder="Please, insert your name..">
  <input type="submit" id="submit-name" value="Enviar">
</form>

Upvotes: 2

Related Questions