Better way to add and remove fields dynamically? - javascript

I made a way to add and remove fields using the input[type"number"]. I use jquery to do this but the way I did is not perfect. If there's a value in the field, the value will get erase if the number value is change because of using .remove(). Is there a better way to doing this?
<body>
<input type="number" id="num" min="0" max="20" required/>
<div class="dynamicInput"></div>
</body>
<script>
$('#num').bind('keyup mouseup', function () {
$('.dynamicInput .row').remove();
$('.dynamicInput h4').remove();
if ($(this).val() > 0) {
$('.dynamicInput').append('<h4>Please fill in the name and email of each extra attendees</h4>');
var num = $(this).val();
for (var i = 0; i < num; i++) {
$('.dynamicInput').append('<div class="row"><div class="col1"><input type="text" name="attendeesName' + i + '" placeholder="Name" required /></div><div class="col2"><input type="text" name="attendeesEmail' + i + '" placeholder="Email" required /></div></div>');
}
}
});
</script>
My Fiddle

Try something like this. Instead of removing all of the inputs every time, this just removes the ones on the end, or adds more to the end.
The main difference between this one and yours is that I added var totNum = 0; to keep track of the current number of input there are. I then used that to determine how many to add/remove.
var totNum = 0;
$(document).on('keyup mouseup', '#num', function(){
var num = $(this).val();
if (num != "")
{
if (totNum == 0)
$('.dynamicInput').append('<h4>Please fill in the name and email of each extra attendees</h4>');
for (var i = num; i < totNum; i++)
{
$('.dynamicInput .row:last-child').remove();
}
for (var i = totNum; i < num; i++)
{
$('.dynamicInput').append('<div class="row"><div class="col1"><input type="text" name="attendeesName' + i + '" placeholder="Name" required /></div><div class="col2"><input type="text" name="attendeesEmail' + i + '" placeholder="Email" required /></div></div>');
}
totNum = num;
if (totNum == 0)
{
$('.dynamicInput h4').remove();
$('.dynamicInput .row').remove();
}
}
});
input[type="number"] {
width: 200px;
height: 30px;
font-family: Arial, sans-serif;
font-size: 20px;
}
.row {
display: block;
margin-bottom: 15px;
}
body {
width: 100%;
padding: 40px;
}
input[type="text"] {
width: 100%;
}
.col1,
.col2 {
width: 45%;
display: inline-block;
margin-right: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<body>
<input type="number" id="num" min="0" max="20" required/>
<div class="dynamicInput"></div>
</body>

It's easier and less likely to fail using a data structure as a skeleton upon which you can build the view. Note that this technique requires an extra computation in order to save user inputs, this is the reason why I've added the "change" event.
In the following code snippet, I've made two panels side by side. The left one is a list of inputs, very close to yours, easy to adapt to your needs, while the right one allows to see the evolution of the "data" array according to user actions.
Both panels rely on the "data" array, in other words, as soon as new items are added to or removed from "data", or a single item is updated, both panels are fully rebuilt. Note that the "change" event takes advantage of event delegation in order to deal with newly added inputs.
Finally, the "update" functions update the entire data source or a single item of the data source when the corresponding input changes, while the "render" functions draw on the data source to keep the panels in sync with the data. By the way, the right panel is rendered once at starting.
$(function () {
var data = []; // data source
var $num = $('#num'); // input for number of rows
var $left = $('#left'); // left panel
var $right = $('#right'); // right panel
// render the right panel at starting
renderRightPanel();
// when the number of rows changes:
// - rebuild the left panel entirely
// - keep the data list up to date
// - print the array to the right panel
$num.on('keyup mouseup', function () {
renderLeftPanel($(this).val());
updateList();
renderRightPanel();
});
// when a value changes:
// - keep the data item up to date
// - print the array to the right panel
$left.on('change', 'input', function () {
var i = $left.find('input').index(this);
updateItem(i, $(this).val());
renderRightPanel();
});
// updates the data list
function updateList () {
data = $left.find('input').map(function () {
return $(this).val();
}).get();
}
// updates a single data item
function updateItem (index, value) {
data[index] = value;
}
// refreshes the DOM of the right panel
function renderRightPanel () {
$right.html('<pre>data = ' + (
JSON.stringify(data, 0, 4)
) + '</pre>');
}
// refreshes the DOM of the left panel
function renderLeftPanel (nLines) {
var i;
var html = '';
if (nLines > 0) {
html = '<h4>Heading</h4>';
for (i = 0; i < nLines; i++) {
html += '<div><input value="' + (data[i] || '') + '" /></div>';
}
}
$left.html(html);
}
});
body * {
padding: 0;
margin: 0;
}
h4, input {
margin-bottom: .5em;
}
#panels {
border: 1px solid black;
}
#panels > div {
display: table-cell;
padding: 1em;
}
#right {
border-left: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Number of inputs: <input id="num" type="number" value="0" /></div>
<div id="panels">
<div id="left"></div
><div id="right"></div>
</div>

Disable and hide extra elements instead of removing them. That will prevent them from getting posted, and also retain the previous value of all values that have been entered. See fiddle
One last point, if you don't want to retain values of hidden elements, change .hide() to .hide().val("")
<body>
<input type="number" id="num" min="0" max="20" required/>
<div class="dynamicInput">
<h4>Please fill in the name and email of each extra attendees</h4>
</div>
</body>
<style>
.col1, .col2 { display: inline; width: 48%; margin-right: 2%; }
.row { padding: 5px; }
</style>
<script>
for (var i = 0; i < 20; i++) {
$('.dynamicInput').append('<div class="row"><div class="col1"><input type="text" name="attendeesName' + i + '" placeholder="Name" required /></div><div class="col2"><input type="text" name="attendeesEmail' + i + '" placeholder="Email" required /></div></div>');
}
$('#num').bind('keyup mouseup', function () {
var num = parseInt($(this).val());
$('.dynamicInput .row')
.slice(num)
.hide()
.attr('disabled','disabled');
if ( num > 0) {
$('.dynamicInput .row')
.slice(0,num).show()
.removeAttr('disabled');
$('.dynamicInput h4').show();
} else {
$('.dynamicInput h4').hide();
}
}).trigger('keyup');
</script>

Off-hand, you could cache the values within javascript to resist losing them between #num changes. e.g.
(function($){
var $num = $('#num'),
$dynamic = $('.dynamicInput');
cache = {};
$dynamic.on('change', 'input', function(e){
cache[$(this).prop('name')] = $(this).val();
});
$num.on('change keyup mouseup', function(e){
$dynamic.empty();
var val = parseInt($(this).val(), 10);
if (!isNaN(val) && val > 0){
$('<h4>')
.text('Please fill in the name and email of each extra attendees')
.appendTo($dynamic);
for (var i = 0; i < val; i++){
var nameName = 'attendeesName' + i,
emailName = 'attendeesEmail' + i;
var $row = $('<div>',{'class':'row'}),
$col1 = $('<div>',{'class':'col1'}).appendTo($row),
$col2 = $('<div>',{'class':'col2'}).appendTo($row);
$('<input>',{
'type': 'text',
'name': nameName,
'placeholder': 'Name',
'required': 'true'
}).val(cache[nameName] || '').appendTo($col1);
$('<input>',{
'type': 'email',
'name': emailName,
'placeholder': 'Email',
'required': 'true'
}).val(cache[emailName] || '').appendTo($col2);
$row.appendTo($dynamic);
}
}
});
})(jQuery);
input[type="number"] {
width:200px;
height:30px;
font-family:Arial, sans-serif;
font-size:20px;
}
.row {
display:block;
margin-bottom:15px;
}
body{
width:100%;
padding:40px;
}
input[type="text"]{
width:100%;
}
.col1, .col2{
width:45%;
display:inline-block;
margin-right:10px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="number" id="num" min="0" max="20" required/>
<div class="dynamicInput"></div>

Here is an attempt to improve the accepted answer:
$(function () {
var $num = $('#num');
var $panel = $('#panel');
var h4 = '<h4>Heading</h4>';
var row = '<div><input /></div>';
$num.on('mouseup keyup', function () {
var n, $inputs;
var value = $(this).val();
if (value <= 0) {
$panel.empty();
}
else {
$inputs = $panel.find('input');
// get the number of inputs already added
n = $inputs.size();
// add your heading if there is no input
if (n === 0) {
$panel.append(h4);
}
// the user wants less inputs
if (value < n) {
$inputs.slice(value).remove();
}
// the user wants more inputs
else if (value > n) {
$panel.append(
// a little trick, see below
new Array(value - n + 1).join(row)
);
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Number of inputs: <input id="num" type="number" value="0" /></div>
<div id="panel"></div>
A word on the "array join trick":
var a = [1, 2, 3, 4];
console.log(a.join('+'));
// prints "1+2+3+4"
var b = new Array(4); // an array of 4 undefined items
console.log(b.join('+'));
// prints "+++"
var c = new Array(3);
console.log('<ul>' + c.join('<li>item</li>') + '</ul>');
// prints "<ul><li>item</li><li>item</li></ul>"

This is what exactly you are looking for,
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#num").keyup(function(){
$('.dynamicInput .row').remove();
$('.dynamicInput h4').remove();
if ($(this).val() > 0) {
$('.dynamicInput').append('<h4>Please fill in the name and email of each extra attendees</h4>');
var num = $(this).val();
for (var i = 0; i < num; i++) {
$('.dynamicInput').append('<div class="row"><div class="col1"><input type="text" name="attendeesName' + i + '" placeholder="Name" required /></div><div class="col2"><input type="text" name="attendeesEmail' + i + '" placeholder="Email" required /></div></div>');
}
}
});
});
</script>
</head>
<body>
<input type="number" id="num" min="0" max="20" required/>
<div class="dynamicInput"></div>
</body>
</html>

Related

Add a value of multiple textarea to another textarea submit

****UPDATE****
I was able to have below issue work with the help of #JasonB.
In addition, I also have another 3 textareas on the same form that will only show when its checkbox is clicked. How will I add that on my current script? I tried grouping it the same way as TextBoxesGroup but just giving another id but when I hit submit, even if I didn't clicked the checkbox, values inside are being submitted. Thank you so much in advance. I'm really new to programming and I'm trying to learn the basics.
HERE'S MY CODE for the checkbox
<textarea id="text" >NAME-
ADDRESS-
ETC-</textarea>
<textarea id="text1">NAME-
ADDRESS-
ETC-</textarea>
<textarea id="text2">NAME-
ADDRESS-
ETC-</textarea>
<input type="checkbox" id="myCheck" onclick="myFunction()">DETAILS
<input type="checkbox" id="myCheck1" onclick="myFunction1()">DETAILS
<input type="checkbox" id="myCheck2" onclick="myFunction2()">OTHERS
<script>
function myFunction() {
var checkBox = document.getElementById("myCheck");
var text = document.getElementById("text");
if (checkBox.checked == true){
text.style.display = "block";
} else {
text.style.display = "none";
}
}
function myFunction1() {
var checkBox1 = document.getElementById("myCheck1");
var text1 = document.getElementById("text1");
if (checkBox1.checked == true){
text1.style.display = "block";
} else {
text1.style.display = "none";
}
}
function myFunction2() {
var checkBox2 = document.getElementById("myCheck2");
var text2 = document.getElementById("text2");
if (checkBox2.checked == true){
text2.style.display = "block";
} else {
text2.style.display = "none";
}
}
</script>
PREVIOUS QUESTION
I have a form with multiple textareas. I'm not familiar with any databases so instead of using one, I prefer using or saving the values/inputs of my textarea to another textarea on submit. I was able to make it work but with those textareas being added dynamically, I only get the first textarea.
here's my script
$(document).ready(function () {
var counter = 1;
$("#addButton").click(function () {
if (counter > 15) {
alert("Only 15 textboxes allowed");
return false;
}
$('<div/>',{'id':'TextBoxDiv' + counter}).html(
$('<textarea/>',{'id':'myTextArea' + counter ,'class':'myTextArea'}).html( 'STEP ' + counter + ' : ' )
)
.appendTo( '#TextBoxesGroup' )
$("#myTextArea" + counter).each(function () {
this.setAttribute('style', 'height:' + (this.scrollHeight) + 'px;overflow-y:hidden;');
}).on('input', function () {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
counter++;
});
$("#removeButton").click(function () {
if (counter == 1) {
alert("No more textbox to remove");
return false;
}
counter--;
$("#TextBoxDiv" + counter).remove();
});
});
$(document).ready(function() {
$("#btn-primary").click(function() {
e=1;
var text55 = $('#textarea55').val();
var text56 = $('#textarea56').val();
var text57 = $('#textarea57').val();
var text58 = $('#textarea58').val();
var text59 = $('#textarea59').val();
var text60 = $('#textarea60').val();
var text61 = $('#textarea61').val();
var text62 = $('#textarea62').val();
var myTextArea = $('#myTextArea'+e).val();
$('#inputTextToSave').val( $('#inputTextToSave').val()+text55+'\n'+text56+'\n'+text57+'\n'+'TROUBLESHOOTING NOTES'+'\n'+myTextArea+'\n'+text58+'\n'+text59+'\n'+text60+'\n'+text61+'\n'+text62+'\n');
e++;
});
here's my html
<textarea id="textarea55" name="caller"></textarea><br>
<textarea id="textarea56" name="auth"></textarea><br>
<textarea id="textarea57" name="issue"></textarea><br>
<label>TROUBLESHOOTING NOTES:</label><br>
<body>
<div id='TextBoxesGroup'>
<div id="TextBoxDiv"></div></div>
<input type='button' value='ADD TS STEPS' id='addButton' class="bubbly-button">
<input type='button' value='REMOVE TS' id='removeButton' class="bubbly-button"><br><\body>
<textarea id="textarea58" name="acct"></textarea><br>
<textarea id="textarea59" name="tid"></textarea><br
<textarea id="textarea60" name="resolution"></textarea><br>
<textarea id="textarea61" name="case"></textarea><br>
<textarea id="textarea62" rows="1" disabled>YANA</textarea>
<input type='button' value='SUBMIT' id='btn-primary' class="bubbly-button"><br>
my css
div {
padding: 1px;
}
textarea {
outline: none;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.myTextArea {
width: 535px;
min-height: 14px;
overflow-y: hidden;
font-size: 14px;
border: 3px solid orange;
background-color:white;color:mediumvioletred;
display: block;
}
body{
font-size: 14px;
font-family: 'tempus sans ITC', 'Arial';
color: mediumvioletred;
text-align: center;
background-color: pink;
}
Your dynamically created textareas are all in #TextBoxesGroup.
To select them all at the time of submission, you can call $('#TextBoxesGroup textarea'). To append their contents into a string with '\n' characters separating them you can use jQuery's .map function to get the text of each element in an array wrapped in a jQuery object, .get to get the underlying array, and .join to concatenate the strings with '\n' as the glue.
var contents = $('#TextBoxesGroup textarea')
.map(function() {
return $(this).text();
})
.get()
.join('\n');
console.log( contents );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="TextBoxesGroup">
<div><textarea>One</textarea></div>
<div><textarea>Two</textarea></div>
<div><textarea>Three</textarea></div>
</div>

how to hide a div container if input dynamically added with choice in checkbox are empty

how to hide a div container if input dynamically added with choice in checkbox are empty
So here what I looked on the forums but I did not find a subject similar to mine
As I explained, I created a booking form for an evening with dynamic inputs to choose on a checkbox
example: I choose the number of adults / number of children and depending on the number of inputs created creates appear ... until all is well ...
I add a PayPal object api (dynamic payment method depending on choice) from their site
what I would like to do
option 1: it is a "required" on the inputs if the fields are all filled the PayPal button (which is a div) gets gray
or
option 2: hide the button if empty input.
Friends if you could give me a hand this would be super nice thank you !!
/* set global variable i */
var i=0;
const adult_price = 20;
const child_price = 10;
/*
---------------------------------------------
function to remove fom elements dynamically
---------------------------------------------
*/
function updateIds(type) {
if ( type == "adult" ) {
var j=1;
// Replace all id_adult_x by id_adult_j, with "j" an ordered list starting with j=1
$('[id^=id_adult_]').each(function() {
// Replace the LABEL text
document.getElementById("lbl_"+this.id).innerHTML = "<hr>"+"Adulte"+" "+j;
var res = this.id.split("id_adult_").join('');
var spanContent = document.getElementById(this.id).innerHTML;
var strToReplace = new RegExp('_adult_'+res, "gi");
document.getElementById(this.id).innerHTML = spanContent.replace( strToReplace, '_adult_'+j);
this.id = "id_adult_"+j;
j= ++j;
});
} else if ( type == "child" ) {
var j=1;
$('[id^=id_child_]').each(function() {
// Replace the LABEL text
document.getElementById("lbl_"+this.id).innerHTML = "<hr>"+"Enfant"+" "+j;
var res = this.id.split("id_child_").join('');
var spanContent = document.getElementById(this.id).innerHTML;
var strToReplace = new RegExp('_child_'+res, "gi");
document.getElementById(this.id).innerHTML = spanContent.replace( strToReplace, '_child_'+j);
this.id = "id_child_"+j;
j= ++j;
});
}
}
/*
---------------------------------------------
function to remove fom elements dynamically
---------------------------------------------^
*/
function removeElement(parentDiv, childDiv){
if (childDiv == parentDiv) {
alert("The parent div cannot be removed.");
}
else if (document.getElementById(childDiv)) {
var child = document.getElementById(childDiv);
var parent = document.getElementById(parentDiv);
parent.removeChild(child);
if (childDiv.includes("adult")) {
document.getElementById("nbrAdult").value = $("[id^=id_adult_]").length ;
// Calculate the new total price
setTotalPrice();
// Update IDs
updateIds("adult");
}
else if (childDiv.includes("child")) {
document.getElementById("nbrChild").value = $("[id^=id_child_]").length ;
// Calculate the new total price
setTotalPrice();
// Update IDs
updateIds("child");
}
else {
/* do nothing */
}
}
else {
alert("Child div has already been removed or does not exist.");
return false;
}
}
/*
----------------------------------------------------------------------------
functions that will be called upon, when user change the list "Nombre Adulte(s)"
---------------------------------------------------------------------------
*/
function onAdultChange()
{
// Retrieve the number of "Adult" selected by the user
var nbrAdultValue = document.getElementById("nbrAdult").value;
// Count the total number of "Adult" Div that are actually created on the html file
var idAdultCount = $("[id^=id_adult_]").length;
// Calculate the delta btw these variables, in order to create or delete the right number of "Adult" Div
var x = nbrAdultValue - idAdultCount;
// Check if the delta is negative, if so, we must delete the last "x" number of "Adult" Div
if ( x < 0 ) {
// Convert "x" from negative to absolute
x = Math.abs(x);
// alert("This action will remove last "+x+" Adult Fields");
// Remove the last "x" "Adult" Div
for (j = 0; j < x ; j++) {
var max = 0;
$("[id^=id_adult_]").each(function() {
var res = this.id.split("id_adult_").join('');
max = Math.max(res, max);
});
removeElement("myForm","id_adult_"+max);
}
}
else {
// Create "x" new "Adult" Div
for (j = 0; j < x; j++) {
i = ++i;
var r = document.createElement('span');
r.setAttribute("id", "id_adult_"+i);
document.getElementById("myForm").appendChild(r);
var l = document.createElement("LABEL");
l.setAttribute("id", "lbl_id_adult_"+i);
l.innerHTML = "Adulte "+i;
document.getElementById("id_adult_"+i).appendChild(l);
lastNameFunction("adult_"+i);
firstNameFunction("adult_"+i);
emailFunction("adult_"+i);
telFunction("adult_"+i);
var g = document.createElement("IMG");
g.setAttribute("src", "delete.jpg");
g.setAttribute("onclick", "removeElement('myForm','id_adult_"+ i +"')");
document.getElementById("id_adult_"+i).appendChild(g);
}
}
// Calculate the new total price
setTotalPrice();
// Update IDs
updateIds("adult");
}
/*
----------------------------------------------------------------------------
functions that will be called upon, when user change the list "Nombre Enfant(s)"
---------------------------------------------------------------------------
*/
function onChildChange()
{
// Retrieve the number of "Child" selected by the user
var nbrChildValue = document.getElementById("nbrChild").value;
// Count the total number of "Child" Div that are actually created on the html file
var idChildCount = $("[id^=id_child_]").length;
// Calculate the delta btw these variables, in order to create or delete the right number of "Child" Div
var x = nbrChildValue - idChildCount;
// Check if the delta is negative, if so, we must delete the last "x" number of "Child" Div
if ( x < 0 ) {
// Convert "x" from negative to absolute
x = Math.abs(x);
// alert("This action will remove last "+x+" Child Fields");
// Remove the last "x" "Child" Div
for (j = 0; j < x ; j++) {
var max = 0;
$("[id^=id_child_]").each(function() {
var res = this.id.split("id_child_").join('');
max = Math.max(res, max);
});
removeElement("myForm","id_child_"+max);
}
}
else {
// Create "x" new "Child" Div
for (j = 0; j < x; j++) {
i = ++i;
var r = document.createElement('span');
r.setAttribute("id", "id_child_"+i);
document.getElementById("myForm").appendChild(r);
var l = document.createElement("LABEL");
l.setAttribute("id", "lbl_id_child_"+i);
l.innerHTML = "Enfant "+i;
document.getElementById("id_child_"+i).appendChild(l);
lastNameFunction("child_"+i);
firstNameFunction("child_"+i);
var g = document.createElement("IMG");
g.setAttribute("src", "delete.jpg");
g.setAttribute("onclick", "removeElement('myForm','id_child_"+ i +"')");
document.getElementById("id_child_"+i).appendChild(g);
}
}
// Calculate the new total price
setTotalPrice();
// Update IDs
updateIds("child");
}
/*
----------------------------------------------------------------------------
functions that will create an input field for the lastName
---------------------------------------------------------------------------
*/
function lastNameFunction(type)
{
var y = document.createElement("INPUT");
y.setAttribute("type", "text");
y.setAttribute("id","nom-de-famille");
y.setAttribute("placeholder","Nom");
y.setAttribute("Name","lastname_"+type);
document.getElementById("id_"+type).appendChild(y);
document.getElementById("nom-de-famille").required=true;
}
/*
----------------------------------------------------------------------------
functions that will create an input field for the firstName
---------------------------------------------------------------------------
*/
function firstNameFunction(type)
{
var y = document.createElement("INPUT");
y.setAttribute("type", "text");
y.setAttribute("placeholder","Prenom");
y.setAttribute("Name","firstname_"+type);
document.getElementById("id_"+type).appendChild(y);
}
/*
----------------------------------------------------------------------------
functions that will create an input field for the Email
---------------------------------------------------------------------------
*/
function emailFunction(type)
{
var y = document.createElement("INPUT");
y.setAttribute("type", "email");
y.setAttribute("placeholder", "Email");
y.setAttribute("Name","email_"+type);
document.getElementById("id_"+type).appendChild(y);
}
/*
----------------------------------------------------------------------------
functions that will create an input field for the phone number
---------------------------------------------------------------------------
*/
function telFunction(type)
{
var y = document.createElement("INPUT");
y.setAttribute("type", "tel");
y.setAttribute("placeholder", "Tel");
y.setAttribute("Name","tel_"+type);
document.getElementById("id_"+type).appendChild(y);
}
/*
---------------------------------------------
function that calculate the total price
---------------------------------------------
*/
function setTotalPrice()
{
document.getElementById("totalPrice").value = document.getElementById("nbrAdult").value*adult_price + document.getElementById("nbrChild").value*child_price;
}
/*
---------------------------------------------
function that create the Items List formatted for Paypal
---------------------------------------------
*/
function getJsonItemsList()
{
var itemsList = [];
var j=0;
$('[id^=id_adult_]').each(function() {
itemsList.push({ "name":"Adulte "+(j+1) , "description": document.getElementsByName
("lastname_adult_"+(j+1))[0].value
+ " " + document.getElementsByName("firstname_adult_"
+(j+1))[0].value + " " + document.getElementsByName
("email_adult_"+(j+1))[0].value
+ " " + document.getElementsByName("tel_adult_"
+(j+1))[0].value , "quantity": "1", "price": + adult_price , "currency":"EUR" });
j= ++j;
});
var h=0;
$('[id^=id_child_]').each(function() {
itemsList.push({ "name":"Enfant "+(h+1) ,
"description": document.getElementsByName("lastname_child_"+(h+1))[0].value
+ " " + document.getElementsByName("firstname_child_"+(h+1))[0].value , "quantity": "1", "price":
+ child_price , "currency":"EUR" });
h= ++h;
});
if ( j == "0" && h == "0") {
itemsList ="' '";
}
return itemsList ;
}
/*
-----------------------------------------------------------------------------
functions that will be called upon, when user click on the Reset Button
------------------------------------------------------------------------------
*/
function resetElements(){
document.getElementById('myForm').innerHTML = '';
document.getElementById("nbrAdult").value = "0";
document.getElementById("nbrChild").value = "0";
document.getElementById("totalPrice").value = "0";
i = 0;
}
.three {
width: 80%;
border: solid 1px lightgray;
margin-top: 30px ;
margin-bottom: 30px ;
margin-left: auto;
margin-right: auto;
background-color: #FFFFFF;
}
.jta-before-form {
text-align: center;
}
.jta-form-layout {
line-height: 30px;
margin: 20px;
}
#mainform > .jta-form-content {
padding: 10px;
}
#myForm {
display: inline;
padding: 10px;
}
input {
width: 40%;
padding: 12px 20px;
margin: 20px;
box-sizing: border-box;
border-radius: 4px;
display: inline-block;
}
input:focus {
background-color: lightgoldenrodyellow;
border-radius: 4px;
}
#lbl_id_adult_1,
#lbl_id_adult_2,
#lbl_id_adult_3,
#lbl_id_adult_4,
#lbl_id_adult_5,
#lbl_id_adult_6,
#lbl_id_adult_7,
#lbl_id_adult_8,
#lbl_id_adult_9 {
margin: 15px 0px 15px 0px ;
border-bottom: solid 1px lightgray;
display: block;
}
#id_adult_1> img,
#id_adult_2> img,
#id_adult_3> img,
#id_adult_4> img,
#id_adult_5> img,
#id_adult_6> img,
#id_adult_7> img,
#id_adult_8> img,
#id_adult_9 > img {
float: right;
}
#lbl_id_child_1,
#lbl_id_child_2,
#lbl_id_child_3,
#lbl_id_child_4,
#lbl_id_child_5,
#lbl_id_child_6,
#lbl_id_child_7,
#lbl_id_child_8,
#lbl_id_child_9 {
margin: 15px 0px 15px 0px ;
border-bottom: solid 1px lightgray;
display: block;
}
#id_child_1> img,
#id_child_2> img,
#id_child_3> img,
#id_child_4> img,
#id_child_5> img,
#id_child_6> img,
#id_child_7> img,
#id_child_8> img,
#id_child_9 > img {
float: right;
}
#totalPrice {
border: solid 1px;
border-radius: 20px;
width: 150px;
margin-top: 40px;
margin-left: 10px;
display: inline-block;
text-align: center;
}
#paypal-button-container {
width: 100%;
text-align: center;
margin-bottom: 20px;
}
<!DOCTYPE html>
<html>
<head>
<title>Create Dynamic form Using JavaScript - Demo Preview</title>
<meta name="robots" content="noindex, nofollow" />
<script src="js/repas-annuel-form.js" type="text/javascript"></script>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="form-style.css">
</head>
<body>
<div class ="main_content">
<div class="three">
<div class="jta-before-form">
<span id="jta-form-title" class="jta-form-title">
<h3>reservation</h3></span>
<div class="">Les champs marqués d’un astérisque * sont obligatoires</div>
</div>
<div class="jta-form-layout">
<form action="#" type="sbubmit" method="get" id="mainform" >
<div class="jta-before-form-content" >
<div class="label" >
<label for="nbrAdult" >Nombre Adulte(s)</label>
</div>
<select id="nbrAdult" onchange="onAdultChange()">
<option value="0" selected=>0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
</select>
</div>
<div class="label">
<label for="nbrChild">Nombre Enfant(s)</label>
</div>
<select id="nbrChild" onchange="onChildChange()" >
<option value="" >0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
</select>
</div>
</div>
<div class="jta-form-content ">
<span id="myForm"></span>
</div>
<div class="jta-after-form-content">Prix Total (Euro)
<INPUT id="totalPrice" type="text" disabled="disabled" placeholder="0" Size=8></INPUT>
</div>
</form>
<div class="jta-after-form">
<div name="button-paypal" id="paypal-button-container"></div>
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
// Render the PayPal button
paypal.Button.render({
// Set your environment
env: 'production', // sandbox | production
// Specify the style of the button
style: {
layout: 'vertical', // horizontal | vertical
size: 'medium', // medium | large | responsive
shape: 'pill', // pill | rect
color: 'silver' // gold | blue | silver | white | black
},
// Specify allowed and disallowed funding sources
//
// Options:
// - paypal.FUNDING.CARD
// - paypal.FUNDING.CREDIT
// - paypal.FUNDING.ELV
funding: {
allowed: [
paypal.FUNDING.CARD,
],
disallowed: [
paypal.FUNDING.CREDIT,
],
},
// Enable Pay Now checkout flow (optional)
commit: true,
// PayPal Client IDs - replace with your own
// Create a PayPal app: https://developer.paypal.com/developer/applications/create
client: {
sandbox: 'AXnE7qNrnFxL4IsXrCSFP_mQPvjPNdGo_UA1pHvcw0p_hnmrLQR3_XOlqRTGe7POwHj8urXcd1DmmwWo',
production: 'Afe_0oViyEcryagJtFBf34Gkf_hbTgsIjPBkCKIdyD5jYNQF_Kyu3s1nawS46kTMBRoT25STeSnNkFF7'
},
// Set up a payment
payment: function(data, actions) {
return actions.payment.create({
transactions: [{
amount: {
total: document.getElementById("totalPrice").value,currency: 'EUR'},
description: 'Reservation - Repas Annuel 2018.',
item_list: { items: getJsonItemsList() }
}],
note_to_payer: 'Contact us for any questions on your order.'
});
},
onAuthorize: function (data, actions) {
return actions.payment.execute()
.then(function () {
window.alert('Merci pour votre réservation !');
});
}
}, '#paypal-button-container');
</script>
</script>
</div>
</body>
</html>
I am going to go out on a limb here and say all this ID management is pretty messy, difficult to maintain and frankly really unnecessary here. Use classes instead and make life a lot simpler for yourself.
I modified your markup to use a pair of hidden cloned input groups that I append to the form.
I removed a good bit of excess code - still pretty verbose but that is to allow you to see what is happening on each action.
I did NOT wire up the reset but that should be easy if you have the button somewhere.
I removed a good bit of markup for extra jQuery and unknown js etc.
I found and fixed a few (more than a few maybe) typos as well.
/* set global variable i */
//var i = 0;
const adult_price = 20;
const child_price = 10;
/*
---------------------------------------------
function to remove form elements dynamically
---------------------------------------------
*/
function updateIds() {
let adults = ".adult-container";
let children = ".child-container"
let containers = $('#myForm').find('.container-group');
containers.each(function() {
let containerDiv = $(this);
let idx = 0;
if (containerDiv.is(adults)) {
idx = $(adults).index($(this)) + 1;
}
if (containerDiv.is(children)) {
idx = $(children).index($(this)) + 1;
}
containerDiv.find('.numerator').html(idx);
});
}
/*
---------------------------------------------
function to remove form elements dynamically
---------------------------------------------^
*/
function removeElement(event) {
var parentDiv = $(event.delegateTarget);
let containerDiv = $(this).closest('.container-group');
if (containerDiv.is('.adult-container')) {
containerDiv.remove();
document.getElementById("nbrAdult").value = $('#myForm').find('.adult-container').length;
}
if (containerDiv.is('.child-container')) {
containerDiv.remove();
document.getElementById("nbrChild").value = $('#myForm').find('.child-container').length;
}
// Calculate the new total price
setTotalPrice();
updateIds();
$('#mainform').trigger('setpaypal');
}
/*
----------------------------------------------------------------------------
functions that will be called upon, when user change the list "Nombre"
---------------------------------------------------------------------------
*/
function onSelectChange(e) {
let containerSel = $(this).data('target');
let nbrValue = this.value;
let formid = "#myForm";
let myform = $(formid);
let items = myform.find(containerSel);
let itemsCount = items.length;
// Calculate the delta
var x = nbrValue - itemsCount;
// If the delta is negative, delete x
if (x < 0) {
let el = items.slice(x).remove();
} else {
// Create "x" new
let j = 0;
let clonex = $('#holder').find(containerSel).eq(0);
for (j; j < x; j++) {
let c = clonex.clone(true);
c.appendTo(formid);
}
}
updateIds();
setTotalPrice();
$('#mainform').trigger('setpaypal');
}
/*
---------------------------------------------
function that calculate the total price
---------------------------------------------
*/
function setTotalPrice() {
document.getElementById("totalPrice").value = document.getElementById("nbrAdult").value * adult_price + document.getElementById("nbrChild").value * child_price;
}
/*
---------------------------------------------
function that create the Items List formatted for Paypal
---------------------------------------------
*/
function getJsonItemsList() {
var itemsList = [];
var selAdultTarget = $('#nbrAdult').data('target');
var adults = $(selTarget);
adults.each(function() {
let item = {
"name": $(this).find('.type-text') + " " + $(this).find('.numerator').text(),
"description": $(this).find('.nom-de-famille').val() + "," + $(this).find('.firstname-input').val() + " " + $(this).find('.email-input').val() +
" " + $(this).find('.tel-input').val(),
"quantity": "1",
"price": +adult_price,
"currency": "EUR"
};
itemsList.push(item);
});
var selChildTarget = $('#nbrChild').data('target');
var children = $(selChildTarget);
children.each(function() {
let item = {
"name": $(this).find('.type-text') + " " + $(this).find('.numerator').text(),
"description": $(this).find('.nom-de-famille').val() + "," + $(this).find('.firstname-input').val(),
"quantity": "1",
"price": +child_price,
"currency": "EUR"
};
itemsList.push(item);
});
if (!!children.length && !!adults.length) {
itemsList = "' '";
}
return itemsList;
}
/*
-----------------------------------------------------------------------------
functions that will be called upon, when user click on the Reset Button
------------------------------------------------------------------------------
*/
function resetElements() {
// the select change events do this in a controlled way
// document.getElementById('myForm').innerHTML = '';
document.getElementById("nbrAdult").value = "0";
document.getElementById("nbrChild").value = "0";
//when you change the selects they do this, i not needed any more
//document.getElementById("totalPrice").value = "0";
// i = 0;
}
function setPayPal() {
// put other custom stuff here
let showhide = !$('#myForm').find('.container-group').length;
// hide if we have none, show if we have some
$('.length paypal-button-container')
.toggleClass('hidden', showhide);
}
$(function() {
$('#myForm').on("click", ".remove-group", removeElement);
$('#mainform').on('change', "#nbrAdult, #nbrChild", onSelectChange);
$('#mainform').on('setpaypal', setPayPal);
});
.three {
width: 80%;
border: solid 1px lightgray;
margin-top: 30px;
margin-bottom: 30px;
margin-left: auto;
margin-right: auto;
background-color: #FFFFFF;
}
.numerator {
margin-left: 1em;
}
.jta-before-form {
text-align: center;
}
.jta-form-layout {
line-height: 30px;
margin: 20px;
}
#mainform>.jta-form-content {
padding: 10px;
}
#myForm {
display: inline;
padding: 10px;
}
input {
width: 40%;
padding: 12px 20px;
margin: 20px;
box-sizing: border-box;
border-radius: 4px;
display: inline-block;
}
input:focus {
background-color: lightgoldenrodyellow;
border-radius: 4px;
}
#myForm .group-container .adult-label,
#myForm .group-container .child-label {
margin: 15px 0px 15px 0px;
border-bottom: solid 1px lightgray;
display: block;
}
#myForm img {
float: right;
}
#myForm .group-container .adult-label,
#myForm .group-container .child-label {
margin: 15px 0px 15px 0px;
border-bottom: solid 1px lightgray;
display: block;
}
#totalPrice {
border: solid 1px;
border-radius: 20px;
width: 150px;
margin-top: 40px;
margin-left: 10px;
display: inline-block;
text-align: center;
}
#paypal-button-container {
width: 100%;
text-align: center;
margin-bottom: 20px;
}
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
<div class="main_content">
<div class="three">
<div class="jta-before-form">
<span id="jta-form-title" class="jta-form-title">
<h3>reservation</h3></span>
<div class="">Les champs marqués d’un astérisque * sont obligatoires</div>
</div>
<div class="jta-form-layout">
<form action="#" type="submit" method="get" id="mainform">
<div class="jta-before-form-content">
<div class="label">
<label for="nbrAdult">Nombre Adulte(s)</label>
</div>
<select id="nbrAdult" data-target='.adult-container'>
<option value="0" selected=>0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
</select>
<div class="label">
<label for="nbrChild">Nombre Enfant(s)</label>
</div>
<select id="nbrChild" data-target='.child-container'>
<option value="">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
</select>
</div>
<div class="jta-form-content ">
<span id="myForm"></span>
</div>
<div class="jta-after-form-content">Prix Total (Euro)
<input id="totalPrice" type="text" disabled="disabled" placeholder="0" Size=8 />
</div>
</form>
<div class="jta-after-form">
<div name="button-paypal" id="paypal-button-container">Paypal Pal</div>
</div>
<div id="holder" class="hidden">
<div class="adult-container container-group">
<hr /><label class="adult-label"><span class="type-text">Adulte</span><span class="numerator"></span></label><input type="text" class="nom-de-famille" placeholder="Nom" name="lastname_adult" required=""><input type="text" class="firstname-input"
placeholder="Prenom" name="firstname_adult" /><input type="email" class="email-input" placeholder="Email" name="email_adult" /><input type="tel" class="tel-input" placeholder="Tel" name="tel_adult" /><img class="remove-group" src="delete.jpg"
/></div>
<div class="child-container container-group">
<hr /><label class="child-label"><span class="type-text">Enfant</span><span class="numerator"></span></label><input type="text" class="nom-de-famille" placeholder="Nom" name="lastname_child" /><input type="text" placeholder="Prenom" name="firstname_child"
/><img src="delete.jpg" /></div>
</div>
</body>
You can accomplish this by adding an event listener to your form that listens for keypresses. The listener will listen to all the dynamically created fields and the input elements in them.
var filledInputs = []
$("document").ready(function() {
$("#myForm").on("keypress", function(e) {
var elem = e.target.name + " " + e.target.id
if (e.target.value.length > 0) {
if (filledInputs.indexOf(elem) === -1) { filledInputs.push(elem) }
} else {
var elemIndex = filledInputs.indexOf(elem)
if (elemIndex !== -1) { filledInputs.splice(elemIndex, 1) }
}
})
})
EDITTED NOTE: there are two global variables to keep track of all the available inputs in the form, "allInputElements", and the ones that are currently filled "filledInputs". You need to increase "allInputElements" by the number of inputs elements for a field that's being added to the form during it's creation (4 for adults, 2 for children). The code above will add and remove names of the inputs to filledInputs whenever the user types in one.
function onAdultChange() {
// ...
if (x < 0) {
// ...
for (j = 0; j < x; j++) {
// ...
removeElement("myForm", "id_adult_" + max);
// decrease the global variable when removing input elements
allInputElements -= 4
}
} else {
for (j = 0; j < x; j++) {
// ...
document.getElementById("id_adult_" + i).appendChild(g);
// increase the global variable when adding input elements
allInputElements += 4
}
}
// ...
}
// ...
function onChildChange() {
// ...
if (x < 0) {
// ...
for (j = 0; j < x; j++) {
// ...
removeElement("myForm", "id_child_" + max);
// decrease the global variable when adding input elements
allInputElements -= 2
}
} else {
for (j = 0; j < x; j++) {
// ...
document.getElementById("id_child_" + i).appendChild(g);
// increase the global variable when adding input elements
allInputElements += 2
}
}
}
Aswell as setting allInputElements and filledInputs back to 0 when you clear the form of all input elements:
function resetElements() {
// ...
allInputElements = 0
filledInputs = []
}
PS: if "$(document).ready" doesn't work, move your jQuery to the very bottom of your HTML body element.
EDIT: your options for "disabling" the paypal button are to hide it with css' "display: none" or, the better alternative is to simply check if all inputs are filled before running your paypal code.
if (filledInputs.length === allInputElements) {
// paypal code
}
// else nothing happens

Adding labels to QR codes

I have created a QR code generator. The user can create multiple QR codes.
I would like the user to be able to name each QR code (referred to as a checkpoint) by writing the desired checkpoint name in the text input field, clicking the Assign Name button and having the text input field disappear, being replaced by the name the user typed into the field.
The user can input checkpoint names, however, it only works for the first QR code printed, and the label only appears below the QR code. Below is the code that I have so far. Any help or suggestions to help me get the ball rolling on this would be very much appreciated. Thank you!
Note: If you try to run this to see the QR codes, you will have to enter something in the text field and press generate. They won't appear automatically.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: arial, sans-serif;
}
section {
margin: 50px auto;
max-width: 350px;
text-align: center;
}
textarea {
width: 50%;
height: 50px;
margin-bottom: 10px;
}
#size {
max-width: 64px;
}
label {
display: inline-block;
width: 140px;
text-align: left;
}
</style>
<script src="/scripts/snippet-javascript-console.min.js?v=1"></script>
</head>
<body>
<section>
<h1>QR Code Generator</h1>
<p>Enter a URL or some text bellow and hit the Generate button (<kbd>Ctrl</kbd>+<kbd>Enter</kbd>)!</p>
<textarea id="textarea" autofocus></textarea>
<div class="block">
<label for="size">Size (px):</label>
<input align="left" id="size" type="number" value="150" min="50" max="500" step="50">
<label for="amount">Amount of Labels:</label>
<input align="left" id="amount" type="number" value="1" min="1" max="500" step="1">
<button id="genQRcode">Generate</button>
</div>
<div id="content" style="display: none;"></div>
</section>
<p id="demo" align="center"></p>
<script>
function myFunction() {
var x = document.getElementById("cpname").value;
document.getElementById("demo").innerHTML = x;
}
</script>
<script id="template-qr-code" type="text/html">
<p> <img id="qrcode" src="{{src}}" /></p>
<label for="checkpoint"> Checkpoint Name:</label>
<input id="cpname" type="text" value="">
<button onclick="myFunction()">Assign Name</button>
</script>
<script type="text/javascript">
window.addEventListener('load', function() {
var textarea = document.getElementById("textarea"),
content = document.getElementById("content"),
amount = document.getElementById("amount"),
qrTemplate = document.getElementById('template-qr-code');
function genQRcode() {
var data = encodeURIComponent(textarea.value),
size = document.getElementById("size").value,
chart = "http://chart.googleapis.com/chart?cht=qr&chs=" + size + "x" + size + "&choe=UTF-8&chld=L|0&chl=" + data;
if (data === "") {
alert("Please enter valid data!");
textarea.focus();
content.style.display = "none";
} else {
for (var i = 0; i < amount.value; i++) {
var qrSrc = qrTemplate.innerHTML;
qrSrc = qrSrc.replace(new RegExp('{{src}}', 'g'), chart);
qrSrc = qrSrc.replace(new RegExp('{{i}}', 'g'), i);
content.insertAdjacentHTML('beforeEnd', qrSrc);
}
content.style.display = "";
}
}
document.getElementById("genQRcode").addEventListener("click", genQRcode);
document.addEventListener("keydown", function(e) {
if (e.ctrlKey && e.keyCode == 13) {
genQRcode();
}
});
});
</script>
</body>
</html>
Your click function
function myFunction() {
var x = document.getElementById("cpname").value;
document.getElementById("demo").innerHTML = x;
}
is getting and setting an element by ID. That will only ever affect a single element on the page (usually the first one that the browser runs into with that specific id). You need to use a different selector / way of getting the label you want to change because you can't reuse ids.
Basically you need to make your label fields distinct so you can actually select them

Having trouble passing a value from one input to another with jquery

I'm doing a little noob project and making a simple "to-do list" and I'm stuck on something that seems so simple! I'm trying to pass the main up top from #myInput and pass it to the next down and so on. Right now, if you enter something then click add, it creates a blank new line at first for some reason then if you type something else and click add, what you typed before shows up on the next line. It will keep doing that for as long as you type something different in the input, but if you keep hitting add a couple times with the same thing in the input, nothing shows up. Then change the input again to something different and click add and all that will show up lol, but still no current line outputs from what you typed...going nuts. Any suggestions on the proper way to do this? I left a JSfiddle link to see exactly what is happening down below.
<div>
<form id="addThings" type="text">
<input type="text" id="myInput" placeholder="add to your to-do list" size="50" maxlength="40" autocomplete="off" autofocus>
<input type="button" id="addButton" value="add">
</form>
</div>
Also, when you click the button and it creates a new line down below it shifts everything around a bit..ideas on what needs to be changed in the css? Trying to get it a little smoother. Thanks!
$(function() {
var i = 2;
$('#addButton').click(function(e) {
var input = $('#myInput').val();
console.log(input);
var id = "newLine" + i;
var line = '<input type=\"text\" id=\"' + id + '\" size=\"50\" disabled><input type=\"checkbox\" >';
$('form').append(line);
var newId = "#" + id;
$('#myInput').change(function() {
$(newId).val(input);
});
i += 1;
});
});
JSFiddle
Try this. Providing a value to the input field before you append it works well.In your case there is an issue with javascript closure. To solve it just define the input variable outside of the click function
$(function() {
var i = 2;
$('#addButton').click(function(e) {
var input = $('#myInput').val();
console.log(input);
var id = "newLine" + i;
var line = '<input type=\"text\" id=\"' + id + '\" value=\"'+input+'\" size=\"50\" disabled><input type=\"checkbox\" >';
console.log(line);
$('form').append(line);
i += 1;
});
});
JSFIDDLE
Try assigning the input value to the value attribute of your new input when you create the new line:
$(function() {
var i = 2;
$('#addButton').click(function(e) {
var input = $('#myInput').val();
var id = "newLine" + i;
var line = '<input type=\"text\" id=\"' + id + '\" size=\"50\" value="' + input + '" disabled><input type=\"checkbox\">';
$('form').append(line);
var newId = "#" + id;
/*$('#myInput').change(function() {
$(newId).val(input);
});*/
i += 1;
});
});
body {
background-color: white;
}
div {
width: 750px;
margin: 0 auto;
margin-top: 200px;
margin-bottom: 0;
padding: 0;
}
form {
margin: 0 auto;
display: inline-block;
margin-bottom: 0px;
}
input {
padding: 10px 18px;
float: bottom;
}
input[type=text] {
border-left: white;
border-right: white;
border-top: white;
font-size: 20px;
i height: 21px;
text-align: center;
outline: none;
float: right;
background-color: white;
}
input[type=button] {
display: inline-block;
height: 25px border: 0;
margin: 0 auto;
font-size: 20px;
float: right;
}
input[type=checkbox] {
vertical-align: top;
width: 10%;
margin: 15px auto;
float: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<body>
<div>
<form id="addThings" type="text">
<input type="text" id="myInput" placeholder="add to your to-do list" size="50" maxlength="40" autocomplete="off" autofocus>
<input type="button" id="addButton" value="add">
</form>
</div>
</body>
It's a closure/scope issue. Your variable input is inside the click function. Therefore it is not going to be in the scope of the change function.
Move the declaration of inputoutside of the click function.
Create a wrapper function.
That way all the variables needed are in the scope of addButtonScopeFunc and there only.
Those variables aren't needed in the global scope window. nor in the scope of the '#addButton' event function.
$(function() {
var addButtonScopeFunc = function (input, inputValChangeEl) {
var i = 2,
id = "newLine" + i,
newId = "#" + id,
line = '<input type=\"text\" id=\"' + id + '\" size=\"50\" disabled><input type=\"checkbox\" >';
console.log(input);
console.log(line);
$('form').append(line);
$(inputValChangeEl).change(function() {
$(newId).val(input);
});
i += 1;
};
$('#addButton').click(function(e) {
addButtonScopeFunc($('#myInput').val(), '#myInput');
});
});
To give an other example, just for showing up things.
You could "outscope" the $(inputValChangeEl).change(...) event function outside of addButtonScopeFunc in its own wrapper function handling over the input value as parameter.
$(function() {
var addButtonScopeFunc = function (input, inputValChangeEl) {
/* ... */
$('form').append(line);
changeInputVal(inputValChangeEl, newId, input);
i += 1;
},
changeInputVal = function (el, id, input) {
$(el).change(function() {
$(id).val(input);
});
};
$('#addButton').click(function(e) {
addButtonScopeFunc($('#myInput').val(), '#myInput');
});
});
Further reading: Javascript Scopes well explained

Multiple plus and minus buttons

I am using - and + buttons to change the number of the text box, I am having troubles dealing with different text fields, here is my code:
var unit = 0;
var total;
// if user changes value in field
$('.field').change(function() {
unit = this.value;
});
$('.add').click(function() {
unit++;
var $input = $(this).prevUntil('.sub');
$input.val(unit);
unit = unit;
});
$('.sub').click(function() {
if (unit > 0) {
unit--;
var $input = $(this).nextUntil('.add');
$input.val(unit);
}
});
button {
margin: 4px;
cursor: pointer;
}
input {
text-align: center;
width: 40px;
margin: 4px;
color: salmon;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id=field1>
field 1
<button type="button" id="sub" class=sub>-</button>
<input type="text" id="1" value=0 class=field>
<button type="button" id="add" class=add>+</button>
</div>
<div id=field2>
field 2
<button type="button" id="sub2" class=sub>-</button>
<input type="text" id="2" value=0 class=field>
<button type="button" id="add2" class=add>+</button>
</div>
And here's the DEMO
You can see in the demo that the values change correctly only if you click buttons on the same field, but if you alternate between fields the values don't change properly.
This should be all you need:
$('.add').click(function () {
$(this).prev().val(+$(this).prev().val() + 1);
});
$('.sub').click(function () {
if ($(this).next().val() > 0) $(this).next().val(+$(this).next().val() - 1);
});
By using the unit variable you were tying both inputs together. And the plus in +$(this) is a shorthand way to take the string value from the input and convert it to a number.
jsFiddle example
You're using the same variable to hold the values of your two inputs. One simple option would be to use two variables instead of one:
var unit_1 = 0;
$('#add1').click(function() {
unit_1++;
var $input = $(this).prev();
$input.val(unit_1);
});
/* Same idea for sub1 */
var unit_2 = 0;
$('#add2').click(function() {
unit_2++;
var $input = $(this).prev();
$input.val(unit_2);
});
/* Same idea for sub2 */
and unit = unit just assigns the value of unit to itself, so that's no very useful and you can certainly leave it out.
An alternative approach is to use data attributes and have each element store its own value. Edit: it already stores its own value. Just access it.
var total;
// if user changes value in field
$('.field').change(function() {
// maybe update the total here?
}).trigger('change');
$('.add').click(function() {
var target = $('.field', this.parentNode)[0];
target.value = +target.value + 1;
});
$('.sub').click(function() {
var target = $('.field', this.parentNode)[0];
if (target.value > 0) {
target.value = +target.value - 1;
}
});
button {
margin: 4px;
cursor: pointer;
}
input {
text-align: center;
width: 40px;
margin: 4px;
color: salmon;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id=field1>
field 1
<button type="button" id="sub" class=sub>-</button>
<input type="text" id="1" value=0 class=field>
<button type="button" id="add" class=add>+</button>
</div>
<div id=field2>
field 2
<button type="button" id="sub2" class=sub>-</button>
<input type="text" id="2" value=0 class=field>
<button type="button" id="add2" class=add>+</button>
</div>

Categories