Checking if inputs fields are filled - javascript

I'm trying to check if all the input fields are filled in this form, the inputs are created based on the number of players, so I dynamically created them in JavaScript, how can I do that ?
Here is what I tried
const x = localStorage.getItem('playersNum');
for (let i = 0; i < x; i++) {
const newInput = document.createElement("INPUT");
newInput.setAttribute("type", "text");
newInput.setAttribute("class", "form-control");
newInput.setAttribute("id", `player${i}`);
newInput.setAttribute("placeholder", "Player's Name");
const parentDiv = document.getElementById('player-list');
parentDiv.appendChild(newInput);
const input = document.getElementById(`player${i}`);
const btn = document.getElementById('startGame');
btn.addEventListener('click', function() {
if (input === "") {
alert('Please fill in the players names');
}
});
}

You can try the following way:
const parentDiv = document.getElementById('player-list');
for (let i = 0; i < 2; i++) {
const newInput = document.createElement("INPUT");
newInput.setAttribute("type", "text");
newInput.setAttribute("class", "form-control");
newInput.setAttribute("id", `player${i}`);
newInput.setAttribute("placeholder", "Player's Name");
parentDiv.appendChild(newInput);
}
//get all input elements of type text and starting id with player
const input = document.querySelectorAll("[type='text'][id^='player']");
const btn = document.getElementById('startGame');
btn.addEventListener('click', function() {
//reset border style of all input elements
[...input].forEach(el => el.style.border = '');
//get all empty input elements
let empty = [...input].filter(el => el.value.trim() == "");
//check length
if (empty.length) {
//show alert
alert('Please fill in the players names');
//set border style to empty input elements
empty.forEach(el => el.style.border = '1px solid red');
}
});
<button id="startGame">Start Game</button>
<div id="player-list"></div>

You should check if the inputs are empty and attach an event listener to the start game button only after you've created them: this means after the for loop.
As an improvement you could add a required attribute on the inputs and check in CSS if they are invalid (using the :invalid pseudoclass)
const x = 3;
const parentDiv = document.getElementById('player-list');
const btn = document.getElementById('startGame');
let players;
for (let i = 0; i < x; i++) {
const newInput = document.createElement("input");
newInput.setAttribute("type", "text");
newInput.setAttribute("required", "required");
newInput.setAttribute("class", "form-control");
newInput.setAttribute("id", `player${i}`);
newInput.setAttribute("placeholder", "Player's Name");
parentDiv.appendChild(newInput);
}
/*
* Get all the inputs you have just injected
*/
players = [...document.querySelectorAll('.form-control')];
/*
* Check if there are some inputs not filled
*/
btn.addEventListener('click', function() {
if (players.some((p) => p.value === '')) {
alert('Please fill in ALL the players names');
}
else {
alert('Ok');
}
});
input {
display: block;
margin: 1rem;
border: 1px #ccc solid;
padding: .25rem;
}
input:invalid {
outline: 1px #aa0020 solid;
outline-offset: 1px;
}
<div id="player-list"></div>
<button id="startGame">Start Game</button>

Related

Page slows browser down when input is high

I am building an etch-a-sketch browser version for the odin project.
There is a prompt message that asks input from the user and creates a grid based on the input.
If the input is 15 that should give a 15x15 grid.
Unfortunately the higher the input the more time it takes for the page to load. Any ideas why?
const container = document.querySelector('#container');
const btn = document.querySelector('#btn');
/*
btn.addEventListener('click', () => {
squares.forEach(square => {
square.style.backgroundColor = 'white';
});
});
*/
btn.addEventListener('click', () => addGrid());
function addGrid() {
let content = document.createElement('div');
let input = prompt("Please enter the number of squares per side (2 - 100)");
while ((input == null || input > 100 || input < 2 || isNaN(input))) {
input = prompt("Please enter the number of squares per side (2 - 100)");
}
for (let i = 0; i <= input * input; i++) {
container.style.cssText = 'grid-template-rows: repeat(' + input + ' , 1fr); grid-template-columns: repeat(' + input + ', 1fr)';
content = document.createElement('div');
content.classList.add('square');
container.appendChild(content);
squares = container.querySelectorAll('.square')
squares.forEach(square => {
square.addEventListener('mouseenter', () => {
square.style.backgroundColor = 'black';
});
});
squares.forEach(square => {
square.addEventListener('mouseleave', () => {
square.style.backgroundColor = 'black';
});
});
}
return content;
}
<button id="btn">Click</button>
<div id="container"></div>
You need to move the event handlers outside the loop.
Also you need to use < instead of <= in the loop
Even better, delegate from container
Here is a working version - you could use calc() in the css to size the individual squares
Using delegated event handling
const container = document.getElementById('container');
const btn = document.getElementById('btn');
const reset = document.getElementById('reset');
const mclick = e => {
const tgt = e.target;
if (tgt.matches(".square")) tgt.classList.toggle("clicked");
}
const mhover = e => {
const tgt = e.target;
if (!tgt.matches(".square")) return; // not a square
tgt.classList.toggle("active",e.type==="mouseover")
}
const resetGrid = () => container.querySelectorAll(".square")
.forEach(sq => {
["clicked","active"]
.forEach(cls => sq.classList.remove(cls))
});
const addGrid = () => {
let content = document.createElement('div');
let input = prompt("Please enter the number of squares per side (2 - 100)");
while ((input == null || input > 100 || input < 2 || isNaN(input))) {
input = prompt("Please enter the number of squares per side (2 - 100)");
}
for (let i = 0; i < input * input; i++) {
container.style.cssText = 'grid-template-rows: repeat(' + input + ' , 1fr); grid-template-columns: repeat(' + input + ', 1fr)';
let content = document.createElement('div');
content.classList.add('square');
content.textContent = i
container.appendChild(content);
}
};
btn.addEventListener('click',addGrid);
container.addEventListener("mouseover",mhover);
container.addEventListener("mouseout",mhover);
container.addEventListener("click",mclick);
reset.addEventListener("click",resetGrid);
#container { display:grid; }
div.square { height: 50px; width: 50px; border:1px solid black;}
div.square.active { background-color: black;}
div.square.clicked { background-color: red;}
<button id="btn">Start</button><button id="reset">Reset</button>
<div id="container"></div>

How to set focus on next input when the button "Enter" is pressed? (javascript)

I need some advice.
I have created a function where when spacebar is pressed, it'll create a new input field. What i would like to know is how to set focus on the input field that has been created when spacebar is pressed.
Thanks in advance.
Here is my code: (HTML included)
<div id="paper">
<div id="content">
<input type="text" class="input1">
</div>
</div>
Javascript:
'use strict';
const input1 = document.querySelector('.input1');
const add = input1.addEventListener('keydown', function(e){
if((e.keyCode === 13)){
return mover();
}
});
const mover = function(){
const mega = document.createElement('input');
const content = document.getElementById('content');
content.appendChild(mega);
mega.style.border = "0px solid";
mega.style.marginTop = "75px";
mega.style.width = "600px";
}
Something like this, could do the trick.
const container = document.getElementById("inputs-container");
let inputs = document.getElementsByTagName("input");
// Add input on press Enter
document.onkeyup = (evt) => {
if (evt.keyCode == 32) {
let input = document.createElement("input");
input.type = "text";
input.placeholder = "Input...";
input.onkeyup = inputOnEnter;
container.appendChild(input);
inputs = document.getElementsByTagName("input");
}
};
// Focus next input on Space
const inputOnEnter = (evt) => {
if (evt.keyCode == 13) {
let index = Object.keys(inputs).filter(a => inputs[a] === evt.target);
let nextIndex = parseInt(index) + 1;
if (inputs[nextIndex]) inputs[nextIndex].focus();
}
};
for (let i = 0; i < inputs.length;i++) {
inputs[i].onkeyup = inputOnEnter;
}
<div id="inputs-container">
<input type="text" placeholder="Input..." />
</div>

Delete crossed and go to line below when clicking button

Every time you click on "Add grade" button, I want the next things that will appear to be in the line below that one.
And when I click on the button "-", I want everything in that line to be erased.
delete
nextline
Just try the code below and you'll see what I'm talking about.
input[type="number"]{
color : transparent;
text-shadow : 0 0 0 #000;
}
input[type="number"]:focus{
outline : none;
}
</style>
<button type="button" id="dugme1" onclick="javascript:dodajocenu();"> Add grade</button>
<br><br>
<div id="stranica">
</div>
<script>
var ocena = 0;
function removeElement(obrisi) {
var dugme = obrisi.target;
var input = dugme.previousSibling;
var brisi = dugme.parentElement;
brisi.removeChild(dugme);
brisi.removeChild(input);
}
function dodajocenu() {
ocena++;
//create textbox
var input = document.createElement('input');
input.type = "number";
input.setAttribute("max",5);
input.setAttribute("min",1);
var myParent = document.body;
//Create array of options to be added
var array = ["Volvo","Saab","Mercades","Audi"];
//Create and append select list
var selectList = document.createElement('select');
selectList.id = "mySelect";
myParent.appendChild(selectList);
//Create and append the options
for (var i = 0; i < array.length; i++) {
var option = document.createElement('option');
option.value = array[i];
option.text = array[i];
selectList.appendChild(option);
}
//create remove button
var remove = document.createElement('button');
remove.onclick = function(obrisiocenu) {
removeElement(obrisiocenu);
}
remove.setAttribute("type", "dugme");
remove.innerHTML = "-";
stranica.appendChild(input);
stranica.appendChild(selectList);
stranica.appendChild(remove);
}
</script>```
Try to run the following code, let me know if this is what you want to do.
var ocena = 0;
var stranica = document.querySelector("#stranica")
function removeElement(obrisi) {
var dugme = obrisi.target;
stranica.removeChild(dugme.parentElement)
}
function dodajocenu() {
ocena++;
//create textbox
var input = document.createElement('input');
input.type = "number";
input.setAttribute("max",5);
input.setAttribute("min",1);
var myParent = document.body;
//Create array of options to be added
var array = ["Volvo","Saab","Mercades","Audi"];
//Create and append select list
var selectList = document.createElement('select');
selectList.id = "mySelect";
myParent.appendChild(selectList);
//Create and append the options
for (var i = 0; i < array.length; i++) {
var option = document.createElement('option');
option.value = array[i];
option.text = array[i];
selectList.appendChild(option);
}
//create remove button
var remove = document.createElement('button');
remove.onclick = function(obrisiocenu) {
removeElement(obrisiocenu);
}
remove.setAttribute("type", "dugme");
remove.innerHTML = "-";
var item = document.createElement('div')
item.classList.add("item")
item.appendChild(input);
item.appendChild(selectList);
item.appendChild(remove);
stranica.appendChild(item)
}
input[type="number"]{
color : transparent;
text-shadow : 0 0 0 #000;
}
input[type="number"]:focus{
outline : none;
}
<button type="button" id="dugme1" onclick="javascript:dodajocenu();"> Add grade</button>
<br><br>
<div id="stranica">
</div>

Remove form tags but maintain input functionality

I found a piece of code that works pretty close to how I want. The end result is that when you type something in the input field a list of relevant options appears below based on the text input. You can then click on one of these options instead of having to type of the full string.
The only problem is that when i try and adapt this code to my existing project it breaks because the input field is wrapped in a form. How would I modify this code so that it functions in the exact same way without having to wrap the input tag in a form element? I.e. just have an input field.
(
function()
{
var lookFor = [
"Paris",
"Canada",
"England",
"Scotland",
"Brazil",
"Manila",
"Atlanta"
];
var form = document.getElementById("theForm");
var resultsDiv = document.getElementById("results");
var searchInput = form.search;
// first, position the results:
var node = searchInput;
var x = 0;
var y = 0;
while ( node != null )
{
x += node.offsetLeft;
y += node.offsetTop;
node = node.offsetParent;
}
resultsDiv.style.left = x + "px";
resultsDiv.style.top = (y + 20) + "px";
// now, attach the keyup handler to the search field:
searchInput.onkeyup = function()
{
var txt = this.value.toLowerCase();
if ( txt.length == 0 ) return;
var txtRE = new RegExp( "(" + txt + ")", "ig" );
// now...do we have any matches?
var top = 0;
for ( var s = 0; s < lookFor.length; ++s )
{
var srch = lookFor[s];
if ( srch.toLowerCase().indexOf(txt) >= 0 )
{
srch = srch.replace( txtRE, "<span>$1</span>" );
var div = document.createElement("div");
div.innerHTML = srch;
div.onclick = function() {
searchInput.value = this.innerHTML.replace(/\<\/?span\>/ig,"");
resultsDiv.style.display = "none";
};
div.style.top = top + "px";
top += 20;
resultsDiv.appendChild(div);
resultsDiv.style.display = "block";
}
}
}
// and the keydown handler:
searchInput.onkeydown = function()
{
while ( resultsDiv.firstChild != null )
{
resultsDiv.removeChild( resultsDiv.firstChild );
}
resultsDiv.style.display = "none";
}
}
)();
.searchInput {
width: 200px;
}
#results {
display: none;
position: absolute;
width: 200px;
background-color: lightyellow;
z-index: 10;
}
#results div {
position: absolute;
width: 200px;
height: 20px;
background-color: white;
cursor: pointer;
overflow: hidden;
}
#results div:hover {background: lightblue;}
#results div span {
color: red;
font-weight: bold;
}
<form id="theForm">
Search for: <input name="search" class="searchInput"/>
</form>
<div id="results"></div>
Because in this section of code it relies on the form element to get the input element:
var form = document.getElementById("theForm");
var resultsDiv = document.getElementById("results");
var searchInput = form.search;
Other than that the form isn't needed. As such you could instead make it:
var resultsDiv = document.getElementById("results");
var searchInput = document.getElementsByClassName("searchInput")[0];
Or instead change your input element to have an id of "searchInput" instead of a class and do:
var resultsDiv = document.getElementById("results");
var searchInput = document.getElementById("searchInput");

Removing the corresponding textbox of the anchor tag

I have created a simple application in javascript. The application is that a value is selected from a dropdown list and if the button next to it is clicked then the specified number of texboxes selected in the dropdown are added to the DOM with a a to their right sides.
Here's the HTML:
<form>
<select style="width: 250px;" id="numMembers" <!--onchange="addMembers();" -->>
<option value="0">Add More Members...</option>
<script>
for (var i = 1; i <= 10; i++) {
document.write('<option value=' + i + '>' + i + '</option>');
};
</script>
</select>
<button onclick="addMembers();" type="button">Add</button>
<div style="margin-top: 10px; border: 1px solid #eee; padding: 10px;">
<input type="text" />
<br/>
<input type="text" />
<br/>
<input type="text" />
<br/>
</div>
<div id="extras"></div>
</form>
And here's the script:
function addMembers() {
var num = document.getElementById("numMembers").options["selectedIndex"];
for (var i = 0; i < num; i++) {
var lineBreak = document.createElement("br")
var txtInput = document.createElement("input");
txtInput.type = "text";
txtInput.style.display = "inline";
var removeHref = document.createElement("a");
removeHref.href = "#";
removeHref.innerHTML = "Remove(x)";
removeHref.style.marginLeft = "5px";
removeHref.style.display = "inline";
removeHref.onclick = function () {
document.removeChild(this);
};
document.getElementById("extras").appendChild(lineBreak);
document.getElementById("extras").appendChild(txtInput);
document.getElementById("extras").appendChild(removeHref);
}
}
How can I remove the textbox on the left of the anchor tag which is when clicked. For example:
[XXXXXXX] Remove(x)
[XXXXXXX] Remove(x)
If the last "Remove(x)" is clicked then the last textbox should be removed hence the one to the left of it.
How can I do it?
Note: No JQuery solutions please! I could do that even myself :P.
You can pass the id on anchorTag and can pass same id with some addition for input text, like
If you pass the id input1 for a then use the id input1Text for relative text box,
So you when you click on particular link, you will get a with input1 and get relative input text with 'input1Text'.
This would be apply for input2, input3, ... Something like this.
DEMO
function addMembers() {
var num = document.getElementById("numMembers").options["selectedIndex"];
for (var i = 0; i < num; i++) {
var lineBreak = document.createElement("br")
var txtInput = document.createElement("input");
txtInput.type = "text";
txtInput.id = "input"+i+"Text"; //give the id with Text
txtInput.style.display = "inline";
var removeHref = document.createElement("a");
removeHref.href = "#";
removeHref.innerHTML = "Remove(x)";
removeHref.style.marginLeft = "5px";
removeHref.style.display = "inline";
//when you click on this link you will get relative textbox by "input"+i+"Text";
removeHref.id = "input"+i;
removeHref.onclick = function () {
var removeNodeText = document.getElementById(this.id+"Text");
removeNodeText.parentNode.removeChild(removeNodeText);
var removeNodeLink = document.getElementById(this.id);
removeNodeLink.parentNode.removeChild(removeNodeLink);
};
document.getElementById("extras").appendChild(lineBreak);
document.getElementById("extras").appendChild(txtInput);
document.getElementById("extras").appendChild(removeHref);
}
}
Try This
function addMembers() {
var num = document.getElementById("numMembers").options["selectedIndex"];
for (var i = 0; i < num; i++) {
var lineBreak = document.createElement("br")
var txtInput = document.createElement("input");
txtInput.id = "text_"+i;
txtInput.type = "text";
txtInput.style.display = "inline";
var removeHref = document.createElement("a");
removeHref.href = "#";
removeHref.id = "href_"+i;
removeHref.innerHTML = "Remove(x)";
removeHref.style.marginLeft = "5px";
removeHref.style.display = "inline";
removeHref.onclick = function(){
var id= this.id.split('_')[1];
console.log(id)
document.getElementById("extras").removeChild(document.getElementById('text_'+id));
document.getElementById("extras").removeChild(this);
}
document.getElementById("extras").appendChild(lineBreak);
document.getElementById("extras").appendChild(txtInput);
document.getElementById("extras").appendChild(removeHref);
}
}

Categories