Javascript using For loop for false - javascript

I'm learning now for loops, and as an example I was given in a game this (with '.result-paras' being p classes):
<div class="form">
<label for="guess-field">Enter a guess: </label>
<input type="text" id="guess-field" class="guess-field">
<input type="submit" value="Submit guess" class="guess-submit">
</div>
<div class="result-paras">
<p class="guesses"></p>
<p class="last-result"></p>
<p class="low-or-high"></p>
</div>
const resetParas = document.querySelectorAll('.result-paras');
for (let i = 0 ; i < resetParas.length ; i++) {
resetParas[i].textContent = '';
}
I want to try to copy it on an input type which I want to disable, meaning I want 2 input fields to be disabled using a loop and I'm having trouble getting it to work, would really appreciate your help:
const disableParas = document.querySelectorAll('.form');
for (let i = 0; i < disableParas ; i++ ) {
disableParas[i].disabled = false;
}

When using a for loop to iterate over a list like that, you often use it like this, counting up a variable up to the length of the list:
const disableParas = document.querySelectorAll('.form');
for (let i = 0 ; i < disableParas.length; i++ ) {
disableParas[i].disabled = false;
}
The first part of the for loop is what you do initially, the second part is the condition to stop the loop and the last part is executed each iteration of the loop.

Related

Iterate DOM property x times with JS

I basically have an input of type number
<input type="number" id="no_pi" name="" onkeyup="des()">
<div id="extract"></div>
and function
function des() {
var ext = document.getElementById('extract');
var va = Number(document.getElementById('no_pi').value);
for (var i = 0; i = va; i++) {
ext.innerHTML = "<input type='number' name='' class='form-control'><div class='input-group-text'>cm</div>";
}
}
I just want to instantly generate x number of inputs in div based on user input.
When the user input any number, the page just crashes down. I think the page is going in infinite loop, but I think it is not the case.
Any idea how to achieve this
There's several errors :
In your loop : i = va (this is why it crashes)
You erase the content of the div ext each time you iterate, instead of adding content
By listening on keyup event, you add some content on each key hit. Finally if the user submit 12, it will generate 1 + 12 elements. You should pass the value using a form (by doing this you can also add easily the value control in the input element).
As perfectly mentionned by #Andy in the comments, innerHTML += is a very bad idea. You should generate your elements using document.createElement or insertAdjacentHTML.
Some advices :
Use an event listener instead of the onkeyup attribute
Avoid this kind of variable names, be more explicit
Use const and let instead of var
Here's a version which fixes all that issues :
document.getElementById('elementsNumberForm').addEventListener('submit', event => {
event.preventDefault();
const targetElement = document.getElementById('extract');
const inputValue = document.getElementById('no_pi').value;
for (let i = 0; i < inputValue; i++) {
targetElement.insertAdjacentHTML('beforeEnd', '<input type="number" name="" class="form-control" /><div class="input-group-text">cm</div>');
}
});
<form id="elementsNumberForm">
<input type="number" id="no_pi" min="1" />
<input type="submit" />
</form>
<div id="extract"></div>
Your key issue is how you're using your loop. i = va isn't going to accomplish what you want. It should be a check that the index in the iteration is less than the number represented by the value in your input. It should be i < va.
The other issue is that you're not adding to the HTML, just ensuring that the HTML is just one input.
I've adjusted the code in your question to remove the inline JS and use addEventListener instead, and also to use an array to store the HTML built from the loop which can then be applied to the extract element.
// Cache the elements outside of the loop
// and attach a change listener to the noPi element
const extract = document.getElementById('extract');
const noPi = document.getElementById('no_pi');
noPi.addEventListener('change', des, false);
function des() {
const limit = noPi.value;
// Check that we haven't gone into
// negative numbers
if (limit >= 0) {
// Create an array
const html = [];
// Loop, pushing HTML into the array, until
// we've reached the limit set by the value in noPi
for (let i = 0; i < limit; i++) {
html.push('<input type="number" class="form-control"><div class="input-group-text">cm</div>');
}
// `join` up the array, and add the HTML
// string to the extract element
extract.innerHTML = html.join('');
}
}
<input type="number" id="no_pi" />
<div id="extract"></div>
Additional information
join
I see that you want to use an input field to insert the number of inputs to create.
I see a better way to start learning insert the number of inputs with a prompt, and then scale the project.
You can start like this: (hope it make sense to you)
<div style="height: 300px; background-color: #ccc;" class="container"></div>
we have this div that is going to be filled with the inputs
Then we have the script:
const container = document.querySelector('.container');
const runTimes = prompt("How many inputs wnat to create?");
for(let i = 0; i < runTimes; i++){
let newInput = document.createElement('input');
newInput.innerHTML = "<input type='number' name='' class='form-control'>";
container.appendChild(newInput);
}
In the for loop, we create the element input, then with the .innerHTML we add the HTML we want. to end the loop, we need to append the created input element to the div we have.
hope it makes sense to you, :)
when you get the idea with the prompt , I´ve done this project more pro jaja.
<div style="height: 300px; background-color: #ccc;" class="container"></div>
<input type="text" class="numberTimes" onkeyup="getValue()">
we add an event listener to the input with the function getValuue, and the script like this:
const container = document.querySelector('.container');
function getValue(){
let runTimes = document.querySelector('.numberTimes').value;
document.querySelector('.numberTimes').value= "";
for(let i = 0; i < runTimes; i++){
let newInput = document.createElement('input');
newInput.innerHTML = "<input type='number' name='' class='form-control'>";
container.appendChild(newInput);
}
}
This line document.querySelector('.numberTimes').value= ""; is to reset the input field.
So whenever insert a value on the input it creates that number of inputs in the container and cleans the input field :)

Is it possible to use multiple for loop at same time?

I want to create a html form, it have 2 group(Name and fruit), each group have two check boxes, When user clicks the checkbox that input name are user_checkbox[] and fruit_checkbox[] , its will do something,i need to use array and for loop to get the user which group of checkboxes was checked , but it seems not to allow me use multiple for loop.
My Html File
//group1
<input name="user_checkbox[]" type="checkbox" value="Peter" onclick="showinputtext();" >Peter
<input name="user_checkbox[]" type="checkbox" value="Billy" onclick="showinputtext();" >Billy
//group2
<input name="fruit_checkbox[]" type="checkbox" value="Apple" onclick="showinputtext();" >Apple
<input name="fruit_checkbox[]" type="checkbox" value="Banner" onclick="showinputtext();" >Banana
My Javascript file
function showinputtext() {
var name = document.getElementsByName("user_checkbox[]");
var fruit = document.getElementsByName("fruit_checkbox[]");
for (var n = 0; n < name.length; n++) && for (var f = 0; f < fruit.length; f++) {
if(name[n].checked && fruit[f].checked){
dosomething..................
}
}
but it is not work for me, any idea?? thx
Try nested for loops.
function showinputtext(){
var name = document.getElementsByName("user_checkbox[]");
var fruit = document.getElementsByName("fruit_checkbox[]");
for (var i = 0; i < name.length; i++) {
for (var j = 0; j < fruit.length; j++) {
if(name[i].checked && fruit[j].checked){
alert("ok");
}
}
}
};
if you use jquery
try it :
Example
$("[type='checkbox']").on("click",function(){
var name = document.getElementsByName("user_checkbox[]");
var fruit = document.getElementsByName("fruit_checkbox[]");
for (var i = 0; i < name.length; i++) {
for (var j = 0; j < fruit.length; j++) {
if(name[i].checked && fruit[j].checked){
alert("ok");
}
}
}
});
Why not use forEach? Looks a bit nicer and does the same job in this instance:
function showInputText() {
var nameCheckboxes = document.getElementsByName("user_checkbox[]");
var fruitCheckboxes = document.getElementsByName("fruit_checkbox[]");
nameCheckboxes.forEach(function(nameCheckbox) {
fruitCheckboxes.forEach(function(fruitCheckbox) {
if (nameCheckbox.checked && fruitCheckbox.checked) {
alert ("ok");
};
});
});
I renamed the variables and the function to make this a bit more readable!
Just remember to change the function calls in the onclick attributes if you go for this approach:
// Group 1
<input name="user_checkbox[]" type="checkbox" value="Peter" onclick="showInputText();" >Peter
<input name="user_checkbox[]" type="checkbox" value="Billy" onclick="showInputText();" >Billy
// Group 2
<input name="fruit_checkbox[]" type="checkbox" value="Apple" onclick="showInputText();" >Apple
<input name="fruit_checkbox[]" type="checkbox" value="Banner" onclick="showInputText();" >Banana
However, reading your post, you might not need to do this at all. It seems unnecessary to iterate through both groups in a nested loop. Why not instead add each item to an array and "Do stuff" with both when the form is submitted?
I would change your checkboxes to have a fruit-input and user-input class:
<input type="checkbox" name="peter" class="user-input">
<input type="checkbox" name="banana" class="fruit-input">
Then I would add an event listener to the fruit-input and user-input elements which listen for changes to the checkboxes. When a change event occurs it then checks if the input has been checked or not, and it will then add or remove from either the selectedFruits or selectedUsers arrays:
document.getElementsByClassName("fruit-input")
.forEach(function(input){
input.addEventListener("change", selectFruit);
});
document.getElementsByClassName("user-input")
.forEach(function(input){
input.addEventListener("change", selectUser);
});
var selectedFruits = [];
var selectedUsers = [];
function selectFruit() {
var fruit = this.getAttribute("name");
if (this.checked) {
selectedFuits.push(fruit);
} else {
selectedFruits.remove(fruit);
}
}
function selectUser() {
var user = this.getAttribute("name");
if (this.checked) {
selectedUsers.push(user);
} else {
selectedUsers.remove(user);
}
}
Notice how the functions grab the value to add to the arrays from the input element's name attribute. Your current name attributes are invalid as they should really be unique.
It is even possible to refactor my suggestion above to have one generic input field listener and determine the array to add to based on a data attribute or something. But this is a good starting point.
After all this you can do whatever you need with the selectedFruits or selectedUsers arrays.
Try placing the second for loop inside the first one, like so
for (var n = 0; n < name.length; n++) {
for (var f = 0; f < fruit.length; f++) {
if(chboxsEng_single[n].checked && chboxsEng_fruit[f].checked){
dosomething..................
}
}
}
Be aware that this will go through every single value of f a total of n times, which may or may not be behaviour that you desire, it's not clear in the question.

Re-feeding a variable into a looped function

I'm attempting to make a simple program for encoding things in base64 multiple times (not really for any particular reason, just more as an example and practice). I've been having quite a bit of trouble though, it could be because I've not had enough (or possibly had too much) coffee.
I can't seem to figure out how to refeed my variable (text) back into the function that encodes it until i is equal to times
Any assistance with this would be appreciated!
<html>
<head>
<script>
function encodeThis(text,times) {
var toEncode = text;
for (var i = 0; i < times, i++) {
btoa(toEncode);
}
document.getElementById("result").value = toEncode;
}
</script>
</head>
<body>
<b>Text to Encode</b><br/>
<input type="text" id="encode"><br/>
<b>Number of Times to Encode (Integers Only)<br/>
<input type="text" id="times">
<button type="submit" onclick="encodeThis(encode,times)">Test</button>
<br/>
<br/>
<b>Result</b><br/>
<input type="text" id="result">
</body>
</html>
Would I need to put a function inside of that function to refeed the variable in?
You need to assign the result of the encoding back to the variable.
function encodeThis(text, times) {
var toEncode = text;
for (var i = 0; i < times, i++) {
toEncode = btoa(toEncode);
}
document.getElementById("result").value = toEncode;
}
But in terms of the overall code in your example you also need to actually get the text from the #encode and the #times elements and fix the syntax error in the for loop.
So
function encodeThis(text, times) {
var toEncode = text.value, // read the value from the encode input element
numTimes = parseInt(times.value, 10); // read the value from the times element and convert to number
for (var i = 0; i < numTimes; i++) {
toEncode = btoa(toEncode);
}
document.getElementById("result").value = toEncode;
}
<b>Text to Encode</b><br/>
<input type="text" id="encode" /><br/>
<b>Number of Times to Encode (Integers Only)</b><br/>
<input type="text" id="times" />
<button type="submit" onclick="encodeThis(encode,times)">Test</button>
<br/>
<br/>
<b>Result</b><br/>
<input type="text" id="result">

onclick for all buttons with a data attribute

I have three different boxes which all have a button inside.
I want to register an onclick event for every button with a specific data attribute.
I've started a jsfiddle, any suggestions?
http://jsfiddle.net/mwils/w6gofb30/
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
document.querySelectorAll("button[data-donation]")[i].onclick = console.log(buttons[i]);
}
function letsGo(init) {
var input = document.body.querySelector("input[name='amount']"),
amount = parseInt(input.value, 10) * 100,
url = "https://donate.shelter.org.uk/b?cid=152&freeamount=1&amount=";
if (input.value === '' || parseInt(input.value, 10) >= 0) {
window.location.href = url + init * 100;
} else {
window.location.href = url + amount;
}
}
<div class="shopping-item">
<p><span>£33</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£33" class="shopping-1-input">
<button data-donation="33" class="donate-button shopping-1-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£50</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£50" class="shopping-2-input">
<button data-donation="50" class="donate-button shopping-2-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£188</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£188" class="shopping-3-input">
<button data-donation="188" class="donate-button shopping-3-button">donate now</button>
</div>
While there are really many ways to do that i, most of the time, prefer a simple click delegation. I set that on elements that contain the buttons(could be the window or document.body itself).
To make it simple i show you that with a container first.
<div id="container">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</div>
here is the js
document.getElementById('container').onclick=function(e){
if(e.target.nodeName=='BUTTON'){
alert(e.target.textContent);
}
}
What does this???
if i click on the container it checks if the target element is a button.
if yes it alerts the textContent of the button. simple right?
Doing so you avoid alot of extra variables.
In your case
document.onclick=function(e){
if(e.target.dataset['donation']){
alert(e.target.dataset['donation']);
}
}
shorter
document.onclick=function(e){
e=e.target.dataset; // reuse the variable e
!e['donation']||alert(e['donation']);
}
using
<button data-donation="33">donate now</button>
DEMO's
http://jsfiddle.net/j8xgqfmk/
Extra
button text followed by $ symbol done with css
http://jsfiddle.net/j8xgqfmk/1/
preceded by a £
http://jsfiddle.net/j8xgqfmk/2/
but returning the desidered value
Why?
No loops!!!
Only one event handler!!!!
Less variables!!!
Short code !!!
Faster then multiple complex eventhandlers.
other considerations:
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
document.querySelectorAll("button[data-donation]")[i].onclick=console.log(buttons[i]);
}
Should be written
var buttons=document.querySelectorAll('button[data-donation]'),
btnlength=buttons.length; //cache variables
for (var i = 0; i < btnlength; i++) { // var i
buttons[i].onclick=function(){ //buttons is already defined
console.log(this);
}
// and you need to pass a function to the onclick event
}
or even better
function handler(e){
console.log(this,e);
}
var btns=document.querySelectorAll('button[data-donation]'),
l=btns.length;
while(l--)btns[l].addEventListener('click',handler,false);
or the "Haters gonna hate" version
http://jsfiddle.net/Lbk1ueme/
var B=document.querySelectorAll('button[data-donation]'),
L=B.length,
I=0,
H=function(){console.log(this)};
for(;I<L;B[I++].onclick=H);
https://stackoverflow.com/a/21353032/2450730
if you have difficulties to understand that i can help you to write it based on your requests. For any other question just ask.
keep stuff simple
Loop through your element array (as you already are doing) and use addEventListener to bind the click event to each...
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(event) {
alert(this.getAttribute('data-donation')); // alert the value of data-donation attribute
});
}
<div class="shopping-item">
<p><span>£33</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£33" class="shopping-1-input">
<button data-donation="33" class="donate-button shopping-1-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£50</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£50" class="shopping-2-input">
<button data-donation="50" class="donate-button shopping-2-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£188</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£188" class="shopping-3-input">
<button data-donation="188" class="donate-button shopping-3-button">donate now</button>
The problem is you are not attaching events correctly to the element. You are assigning console.log and not a function to it. Seconds querySelectorAll is expensive. You should not keep looking things up in a loop. Create a variable and store the live html node collection it returns into it.
var btns = document.querySelectorAll("button[data-donation]");
for (var i=0; i<btns.length; i++) {
btns[i].onclick = function() {
console.log(this);
console.log(this.getAttribute("data-donation"));
}
}
function letsGo(init) {
var input = document.body.querySelector("input[name='amount']"),
amount = parseInt(input.value, 10) * 100,
url = "https://donate.shelter.org.uk/b?cid=152&freeamount=1&amount=";
if (input.value === '' || parseInt(input.value, 10) >= 0) {
window.location.href = url + init * 100;
} else {
window.location.href = url + amount;
}
}
<div class="shopping-item">
<p><span>£33</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£33" class="shopping-1-input">
<button data-donation="33" class="donate-button shopping-1-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£50</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£50" class="shopping-2-input">
<button data-donation="50" class="donate-button shopping-2-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£188</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£188" class="shopping-3-input">
<button data-donation="188" class="donate-button shopping-3-button">donate now</button>
</div>
You've got the selector right already, i.e. var buttons = document.querySelectorAll("button[data-donation]") is pulling in all the buttons having data-donation, but there's no need to do another querySelectorAll inside your loop, you just need to reference each button in your result with buttons[i].
Your other mistake is setting onclick = console.log(), instead of onclick = function() { console.log() }. So all you need to change to get it working is:
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
var button = buttons[i];
buttons[i].onclick = function() { console.log(button) };
}
http://jsfiddle.net/w6gofb30/4/
document.querySelectorAll("button[data-donation]").every(function(e,i,a){
e.addEventListener("click", function(){
console.log(this);
console.log(this.getAttribute("data-donation"));
}, false);
});
but before this u need:
NodeList.prototype.every = function(f){
for(var k=0;k<this.length;k++)
f(this[k],k,this);
}
http://jsfiddle.net/sa0ezut7/

echo five times a input with jQuery

How is repeated code HTML for five times?
like repeated(echo) a input <input type="text" name="ok"> with a js code five times.
I mean this is that, a input by a js code echo five times
I want after run jQuery code output is this (5 input):
<input type="text" name="ok">
<input type="text" name="ok">
<input type="text" name="ok">
<input type="text" name="ok">
<input type="text" name="ok">
how is it?
Your question isn't totally clear, do you mean this?
for (var i = 0; i<5;i++) {
$("body").append("<input type='text' name='ok'>");
}
function EchoInput(html, count) {
var result = [];
for (var i = 0; i < count; i++)
result.push(html);
return result.join("");
}
To use this function, you could do something like this:
document.write(EchoInput("<input type='text' name='ok'>", 5));
var body = $('body');
for(var i = 0; i < 5; i++) {
body.append('<input type="text" name="ok">');
}
http://jsfiddle.net/ucbsh/1/
Instead of creating HTML, you can create elements directly.
Here is a way that let you set different names on each input field. Right now all five have the name "ok", but you can change that in the array:
// use ready event so that the page is loaded:
$(document).ready(function(){
// decide where to add the elements:
var container = $('body');
// loop over an array of names:
$.each(['ok','ok','ok','ok','ok'], function(idx, name) {
// create an element and add to the container:
container.append($('<input/>', { type: "text", name: name }));
});
});

Categories

Resources