I'm working on a TO DO List.
here's the HTML body-
<div class="cardDiv">
<input type="text" class="titleText" placeholder="Today's Battle Plans🤠">
<div class="taskList">
<div class="indiv-task task1">
<input type="checkbox" class="checkBox">
<input type="text" class="textBox" placeholder="task1">
</div>
</div>
<button class="addTask-btn" onclick="addTask()">Add More Tasks</button>
</div>
<script src="index.js"></script>
Basically, the button at the end adds a code block for a new task each time the button gets pressed as per this JS code-
let taskList = document.querySelector(".taskList");
let taskCode = '<div class="indiv-task"> <input type="checkbox" class="checkBox"> <input type="text" class="textBox" placeholder="task1"> </div>';
function addTask() {
taskList.innerHTML += taskCode;
let taskListLength = document.querySelectorAll(".indiv-task").length;
for(i=0; i<taskListLength; i++) {
document.querySelectorAll(".textBox")[i].placeholder = "task"+(i+1);
document.querySelectorAll(".indiv-task")[i].classList.add("task"+(i+1));
}
}
But the problem is that whenever the button is pressed all the input text in textBox(es) gets erased. Is there a way I can avoid that, or is it possible only with databases?
PS- I'm still on my learning path...
Like what epascarello said we need to create an element and add it to the taskList element and not use innerHTML to add elements.
let taskList = document.querySelector(".taskList");
let taskHTML = '<input type="checkbox" class="checkBox"> <input type="text" class="textBox" placeholder="task1">';
function addTask() {
let taskCode = document.createElement("DIV");
taskCode.innerHTML = taskHTML;
taskCode.classList.add("indiv-task")
taskList.appendChild(taskCode)
let taskListLength = document.querySelectorAll(".indiv-task").length;
for(i=0; i<taskListLength; i++) {
document.querySelectorAll(".textBox")[i].placeholder = "task"+(i+1);
document.querySelectorAll(".indiv-task")[i].classList.add("task"+(i+1));
}
}
This means that the innerHTML for the taskList element is not reset to have empty text boxes, rather, it just adds another element.
This is because the innerHTML will replace the current html of the element. You can try with:
function addTask() {
const taskList = document.querySelector(".taskList");
const taskCode = '<div class="indiv-task"> <input type="checkbox" class="checkBox"> <input type="text" class="textBox" placeholder="task1"> </div>';
const taskCodeDocument = new DOMParser().parseFromString(taskCode, "text/html");
const taskCodeChild = taskCodeDocument.body.firstChild;
taskList.appendChild(taskCodeChild);
let taskListLength = document.querySelectorAll(".indiv-task").length;
for (i = 0; i < taskListLength; i++) {
document.querySelectorAll(".textBox")[i].placeholder = "task" + (i + 1);
document.querySelectorAll(".indiv-task")[i].classList.add("task" + (i + 1));
}
}
ref: https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString
& https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
Related
So I have this code in ejs to load all the item in the menu table in MongoDB to the front-end
<form action="/order" method="post">
<div class="food-container">
<% for(i = 0; i < menu.length; i++){ %>
<label for="name"><%= menu[i].name %></label>
<input
type="text"
value="<%= menu[i].name %>"
name="menu[<%= [i] %>][name]"
class="name"
id="name"
hidden
/>
<input
type="number"
name="menu[<%= [i] %>][quantity]"
id="name"
min="0"
value="0"
class="input"
/>
<% } %>
<textarea name="notes" id="notes" cols="30" rows="10"></textarea>
</div>
<button type="submit">Order</button>
</form>
now I want to add a text below the form everytime a value for one of the number input is changed to mark a new order item. so I use this in the script tag
const input = document.querySelectorAll(".input");
const name = document.querySelectorAll(".name");
const container = document.querySelector(".food-container");
for (i = 0; i < input.length; i++) {
const name1 = name[i].value.replaceAll(" ", "-");
input[i].addEventListener("change", function (evt) {
const className = document.querySelectorAll(`.${name1}`);
if (parseInt(this.value) == 1 && className.length === 0) {
const className = document.querySelector(`.${name1}`);
const div = document.createElement("div");
const h1 = `<h5 class="${name1}">${name1} X1</h5>`;
div.innerHTML = h1;
container.appendChild(div);
} else if (parseInt(this.value) >= 1){
const className = document.querySelector(`.${name1}`);
className.innerHTML = `<h5 class="${name1}">${name1} X${this.value}</h5>`;
} else {
const className = document.querySelector(`.${name1}`);
className.remove();
}
});
the code above loop through all the text input length and add an event listener to each of the element so if there isn't a h5 element with the item name class it will make a new h5 element and if the number input goes back to 0 it will remove the h5 element with the corresponding class name. I'm wondering if there's a more shorter and elegant way to do this because I know this code is very very confusing and spaghetti-like
I have 1 input. And it has to print out 2 outputs 1 with -1 to the output and the other with -2. But the output doesn't show anything. can someone tell me what I'm doing wrong here.
Code:
// Meters en Centimeters value
function updateTotal() {
const list = document.getElementsByClassName("AutosubmitCalculator");
const values = [];
for (let i = 0; i < list.length; ++i) {
values.push(parseFloat(list[i].value));
}
let total = values.reduce(function(previousValue, currentValue) {
return previousValue + currentValue;
});
document.getElementById("schermentotaal").value = total - 2;
document.getElementById("schermentotaal2").value = total - 1;
}
HTML Input:
<div class="InputField InputMeters">
<input type="tel" name="iFenceMeters" id="FenceMeters" class="AutosubmitCalculator" data-minimum-length="1" tabindex="1" placeholder="00" maxlength="3" value="">
<div class="FormExclamation Tipped Hidden" id="FormCalculatorExclamationFence">0</div>
</div>
HTML Output:
<div class="SummaryRow">
<strong>Schermen</strong>
<input name="schermentotaal" type="text" id="schermentotaal" value=""></input>
</div>
<div class="SummaryRow">
<strong>Palen en onderplaten</strong>
<input name="schermentotaal2" type="text" id="schermentotaal2" value=""></input>
</div>
Thanks in advance :D
You're not calling your updateTotal anywhere. I suggest you run this function on the oninput event on your input field. This will make it so that whenever you enter a number it will run the function updateTotal.
You also have some additional errors, such as you are trying to get the element with the id total but don't have an element with this id in your HTML.
document.getElementById("total").value
I've changed this to be schermentotaal2 which is a valid id in your HTML:
document.getElementById("schermentotaal2").value
See working example below:
function updateTotal() {
const list = document.getElementsByClassName("AutosubmitCalculator");
const values = [];
for (let i = 0; i < list.length; i++) {
values.push(parseFloat(list[i].value));
}
let total = values.reduce(function(previousValue, currentValue) {
return previousValue + currentValue;
});
document.getElementById("schermentotaal").value = (total - 2) || '';
document.getElementById("schermentotaal2").value = (total - 1) || '';
}
<div class="InputField InputMeters">
<input type="tel" name="iFenceMeters" id="FenceMeters" class="AutosubmitCalculator" data-minimum-length="1" tabindex="1" placeholder="00" maxlength="3" value="" oninput="updateTotal()" />
<div class="FormExclamation Tipped Hidden" id="FormCalculatorExclamationFence">0</div>
</div>
<div class="SummaryRow">
<strong>Schermen</strong>
<input name="schermentotaal" type="text" id="schermentotaal" value="" />
</div>
<div class="SummaryRow">
<strong>Palen en onderplaten</strong>
<input name="schermentotaal2" type="text" id="schermentotaal2" value="" />
</div>
Also, if you only have one input you may want to reconsider using a class to get the input value for this as you don't require a loop to get the value from one input field.
I need help extending this JavaScript (borrowed from https://www.quirksmode.org/dom/domform.html):
var appCounter = 0;
function anotherApp() {
appCounter = appCounter + 1;
var newAppField = document.getElementById("keyApp").cloneNode(true);
newAppField.id = '';
newAppField.style.display = 'block';
var newApp = newAppField.childNodes;
for (var i = 0; i < newApp.length; i++) {
var theName = newApp[i].name
if (theName) {
newApp[i].name = theName + appCounter;
}
}
var insertApp = document.getElementById('keyApp');
insertApp.parentNode.insertBefore(newAppField, insertApp);
document.getElementById('appCount').value = appCounter
}
This works fine when element in my form is:
<div id="keyApp" style="display:none">
<input type="text" name="application" id="application">
<input type="text" name="usage" id="usage">
<\div>
But when I add div's around the inputs (bootstrap styling reasons) I loose the ability to update the input names:
<div id="keyApp" style="display:none">
<div class="col-md-2">
<input type="text" name="application" id="application">
</div>
<div class="col-md-2">
<input type="text" name="usage" id="usage">
</div>
<\div>
How do I extend the script to modify the input names in these new div's?
Since there is now another layer, you need to get newApp[i].childNodes[0] now in order to get the actual input elements.
newApp now holds a list of the div elements with col-md-2 styling, and you need to get the children inside of these div elements.
I am creating a website that has a list of user inputs, however at a certain stage I want users to see a summarized page of all their inputs. If the input was not chosen it should not show as part of the summary (as in the script example below).
Here is my problem: there will be multiple user inputs and to write a JS script to achieve what I had done in an example script below will be lots of work and unfeasible. Is there a way the two JS scripts for the individual ID's can be combined into one as in the script below?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div>
<label>For the first test</label>
<input type="text" placeholder="Enter Number" name="clientinfo" id="test1" required>
</div>
<div>
<label>For the second test</label>
<input type="text" placeholder="Enter Number" name="clientinfo" id="test2" required>
</div>
<button id="myBtn">Test</button>
<div style="color:blue;">
<p id="result1"></p>
</div>
<div style="color:red">
<p id="result2"></p>
</div>
<script>
function getUserName() {
var test1 = document.getElementById('test1').value;
var result1 = document.getElementById('result1');
if (test1.length > 0) {
result1.textContent = 'Test1: ' + test1;
} else {
null;
}
}
var myBtn = document.getElementById('myBtn');
myBtn.addEventListener('click', getUserName, false);
</script>
<script>
function getUserName() {
var test2 = document.getElementById('test2').value;
var result2 = document.getElementById('result2');
if (test2.length > 0) {
result2.textContent = 'Test2: ' + test2;
} else {
null;
}
}
var myBtn = document.getElementById('myBtn');
myBtn.addEventListener('click', getUserName, false);
</script>
</body>
</html>
P.s. I would also like to know if a user were to press the test button with an input, remove the input and press the test button again, that the first input would be removed?
You can get all inputs and loop throw the result and create an dom element which will contain the value of the input
and each created element will be added to lets say a result element
See code snippet
function getUserName() {
var inputList = document.getElementsByTagName("INPUT");
var res = document.getElementById("result");
res.innerHTML = "";
var indx = 1;
for (i = 0; i < inputList.length; i++) {
if (inputList[i].value != "") {
var ele = document.createElement("p");
ele.innerHTML ="test " + indx + " : " + inputList[i].value
res.appendChild(ele);
indx++;
}
}
}
var myBtn = document.getElementById('myBtn');
myBtn.addEventListener('click', getUserName, false);
<div>
<label>For the first test</label>
<input type="text" placeholder="Enter Number" name="clientinfo" id="test1" required>
</div>
<div>
<label>For the second test</label>
<input type="text" placeholder="Enter Number" name="clientinfo" id="test2" required>
</div>
<button id="myBtn">Test</button>
<div id="result">
</div>
I apologize for the wordy title but I haven't found a solution to my problem yet. I am a newbie with jQuery and web development so any guidance would be appreciated.
I have a <input> that allows user to enter a value (number) of how many rows of a set of input fields they want populated. Here's my example:
<div id="form">
<input id="num" name="num" type="text" />
</div>
<p> </p>
<div id="form2">
<form action="" method="post" class="form_main">
<div class="data">
<div class="item">
<input id="name" name="name[]" type="text" placeholder="name" /><br/>
<input id="age" name="age[]" type="text" placeholder="age" /><br/>
<input id="city" name="city[]" type="text" placeholder="city" /><br/>
<hr />
</div>
</div>
<button type="submit" name="submit">Submit</button>
</form>
My jQuery:
<script>
var itemNum = 1;
$("#num").on("change", function() {
var count = this.value;
var item = $(".item").parent().html();
//item.attr('id', 'item' + itemNum);
for(var i = 2; i <= count; i++) {
itemNum++;
$(".data").append(item);
}
})
</script>
I'm having problems adding an ID item+itemNum increment to <div class="item">... item.attr() didn't work. It doesn't append once I added that line of code.
Also, how can I get it so that once a user enters a number that populates rows of input fields, that if they change that number it will populate that exact number instead of adding to the already populated rows? Sorry if this doesn't make any sense. Please help!
Here is a DEMO
var itemNum = 1;
$("#num").on("change", function() {
$('.data div').slice(1).remove(); //code for removing previously populated elements.
var count = this.value;
console.log(count);
var item;
//item.attr('id', 'item' + itemNum);
var i;
for(i = 1; i <= count; i++) {
console.log(i);
item = $("#item0").clone().attr('id','item'+itemNum);
//prevent duplicated ID's
item.children('input[name="name[]"]').attr('id','name'+itemNum);
item.children('input[name="age[]"]').attr('id','age'+itemNum);
item.children('input[name="city[]"]').attr('id','city'+itemNum);
itemNum++;
$(".data").append(item);
}
})
Use clone() instead of html()
Try
var itemNum = 1,
item = $(".data .item").parent().html();;
$("#num").on("change", function () {
var count = +this.value;
if (itemNum < count) {
while (itemNum < count) {
itemNum++;
$(item).attr('id', 'item' + itemNum).appendTo('.data')
}
} else {
itemNum = count < 1 ? 1 : count;
$('.data .item').slice(itemNum).remove();
}
})
Demo: Fiddle