So i have a program where it starts off with one input field, and if you press the plus button it adds new input field. I also have it so it gives the new input field a different id. I would prefer it so when i press calculate, it saves the values of all the input fields data into an array. I have tried using a for loop with .val(), but that didnt work.
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<title></title>
</head>
<body>
<!-- ************where the input fields are*******-->
<div id="append">
<p style="display:inline-block; margin-bottom:0px;">
<input type='text' class='minutes' id="minute1"/>
<input type='text' class='vidseconds' id="second1"/>
</p>
<div id="plusnminus">
<button id="plus">+</button>
<button id="minus">-</button>
</div>
</div>
<!-- when this is pressed i want it to save the input fields data-->
<p id="calculate">Calculate</p>
</body>
</html>
//JavaScript
$(document).ready(function(){
var mins = [];
//where it add the new input field
var idnum = 1;
$("#plus").click(function(){
idnum+=1;
var input = "<p><input type='text' class='minutes' id='minute"+idnum+"' /><input type='text' class='vidseconds' id='second"+idnum+"'/></p>";
$(input).appendTo("#append");
});
// to remove an input field
$("#minus").click(function(){
if(idnum >= 2){
$("#minute" + idnum+ ", #second" + idnum).remove();
idnum-=1;
}
});
// i want it to put all of the data from the input fields in an array in that click function
$("#calculate").click(function(){
});
});
/*StyleSheet */
#append {
display: inline-block;
}
#plusnminus {
display: inline-block;
}
button {
border-style: none;
background-color: #C0C0C0;
width: 24px;
height: 24px;
}
Everything is inline because i'm trying to keep it a single file. I have placed comments however for readability.
You can use $.map(), selectors #append input[id^=minute], #append input[id^second] to get all input elements that are descendants of #append element; return an array containing two arrays of values, utilize destructuring assignment to set variable identifiers; for example, minutes, seconds, for arrays corresponding to .value of element where id begins with "minute" or "second"
$(document).ready(function() {
var mins = [];
//where it add the new input field
var idnum = 1;
$("#plus").click(function() {
idnum += 1;
var input = "<p><input type='text' class='minutes' id='minute"
+ idnum
+ "' /><input type='text' class='vidseconds' id='second"
+ idnum
+ "'/></p>";
$(input).appendTo("#append");
});
// to remove an input field
$("#minus").click(function() {
if (idnum >= 2) {
$("#minute" + idnum + ", #second" + idnum).remove();
idnum -= 1;
}
});
// i want it to put all of the data
// from the input fields in an array
// in that click function
$("#calculate").click(function() {
var [minutes, seconds] = $.map([$("#append input[id^=minute]")
, $("#append input[id^=second]")]
, function(el) {
return [$.map(el, function(elem) {
return elem.value;
})]
});
// do stuff with `minutes`, `seconds` variables
console.log("minutes:", minutes, "seconds:", seconds);
});
});
#append {
display: inline-block;
}
#plusnminus {
display: inline-block;
}
button {
border-style: none;
background-color: #C0C0C0;
width: 24px;
height: 24px;
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<title></title>
</head>
<body>
<!-- ************where the input fields are*******-->
<div id="append">
<p style="display:inline-block; margin-bottom:0px;">
<input type='text' class='minutes' id="minute1" />
<input type='text' class='vidseconds' id="second1" />
</p>
<div id="plusnminus">
<button id="plus">+</button>
<button id="minus">-</button>
</div>
</div>
<!-- when this is pressed i want it to save the input fields data-->
<p id="calculate">Calculate</p>
</body>
</html>
You can alternatively substitute Array.from() for $.map()
var [minutes, seconds] = Array.from([$("#append input[id^=minute]")
, $("#append input[id^=second]")]
, function(el) {
return Array.from(el, function(elem) {
return elem.value;
});
});
If you wrap your input fields in a form, you can use .serialize() or .serializeArray() to serialize the whole form at once.
$(function() {
$('#my-button').on('click', function() {
var values = $('#my-form').serializeArray();
console.log(values);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="my-form">
<input type="text" name="input1" value="first field"><br/>
<input type="text" name="input2" value="second field"><br/>
<input type="text" name="input3" value="third field"><br/>
</form>
<button id="my-button">Get All Values</button>
Related
I'm trying to create a list based off of 2 input fields. The first input will be a name and the second an integer.
What I'm trying to achieve is having the name displayed multiplied by the amount of the input integer. I have got the name to display based off the input, but have been unable to have it displayed multiple times based on the input integer.
Here's an example image of what I'm looking to achieve
<html>
<head>
<style>
input {
display: block;
}
#msgs {
margin-bottom: 24px;
}
</style>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<input type="text" value="Michael" id="name" />
<input type="text" value="5" id="count" />
<input type="button" value="add to list" id="add" />
<div id="list"> </div>
</body>
<script>
document.getElementById("add").onclick = function() {
var text = document.getElementById("name").value;
var div = document.createElement("div");
div.textContent = text;
document.getElementById("list").appendChild(div);
document.getElementById("name").value = ""; // clear the value
}
</script>
</html>
Fiddle: https://jsfiddle.net/grnct2yz/
<html>
<head>
<style>
input {
display: block;
}
#msgs {
margin-bottom: 24px;
}
</style>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<input type="text" value="Michael" id="name" />
<input type="number" value="5" id="count" />
<input type="button" value="add to list" id="add" />
<div id="list"> </div>
</body>
<script>
document.getElementById("add").onclick = function() {
var text = document.getElementById("name").value;
for(let i = 0; i < document.getElementById("count").value; i++) {
var div = document.createElement("div");
div.textContent = text;
document.getElementById("list").appendChild(div);
}
document.getElementById("name").value = ""; // clear the value
}
</script>
</html>
I have added a loop and changed the input type to number so we are sure that it's going to insert a number in the loop. Is this what you wanted?
What the code I added does is cycling a number of times equal to the number inputted and then executing the code you wrote.
for loops work this way:
you set an initial statement that is executed at the beginning of the loop, only once (let i = 0 sets a new iterable variable i),
then you set a condition that is checked before every iteration of the loop to make it run (i < document.getElementById("count").value checks that it executes up to and not more than X times, where X is the number inputted),
then you set an operation to be executed at the end of each loop (i++ increments the value of i by one).
Here is another way of doing it:
const name=document.getElementById("name"),
count=document.getElementById("count"),
list=document.getElementById("list");
document.getElementById("add").onclick = function() {
list.insertAdjacentHTML("beforeend",[...Array(+count.value)].map(s=>`<div>${name.value}</div>`).join(""))
name.value = ""; // clear the value
}
<input type="text" value="Michael" id="name" /><br>
<input type="text" value="5" id="count" /><br>
<input type="button" value="add to list" id="add" />
<div id="list"> </div>
Just your Improved code based on your needs we can achieve this in many ways.
<html>
<head>
<style>
input {
display: block;
}
#msgs {
margin-bottom: 24px;
}
</style>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<input type="text" value="Michael" id="name" />
<input type="text" value="5" id="count" />
<input type="button" value="add to list" id="add" />
<div id="list"> </div>
<script>
document.getElementById("add").onclick = function() {
var text = document.getElementById("name").value;
var count = document.getElementById("count").value;
if (parseInt(count) != 'NaN') {
var list = document.getElementById("list");
while (list.firstChild) {
list.removeChild(list.firstChild);
}
count = parseInt(count);
for (var i = 0; i < count; i++) {
var div = document.createElement("div");
div.textContent = text;
document.getElementById("list").appendChild(div);
}
}
}
</script>
</body>
</html>
I created a couple inputs and one drop down that feed into a javascript command to create custom sentences. Whatever the user inputs or selects is added to a sentence framework. When the user selects submit, the sentence is created. It is quite simple. I am running into trouble adding multiple inputs from one drop down to the sentence.
If the user selects "navigation" in addition to "usb ports" within the drop down, only navigation is added to the sentence. How can I change my code so that all selections from the drop down are added to the sentence? For example if "navigation" and "usb ports" is selected, the sentence would read: "It has these options: navigation and usb ports."
Also, note that I am using the Chosen plugin.
Thanks so much for your help.
<!DOCTYPE html>
<html>
<head>
<title>Hi</title>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.css">
<style type="text/css">
table,td,th {margin-left: auto;margin-right: auto}
.display {display: flex;align-items: center;justify-content: center;}
p {text-align: center;}
textarea {display: block;margin-left:auto;margin-right: auto;}
</style>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$(".chosen-select").chosen({
disable_search_threshold: 4
});
})
</script>
<script type="text/javascript">
function sentence() {
document.getElementById("s1").value = "";// reset
document.getElementById("s1").style.display = "block";
document.getElementById("r1").style.display = "block";
if (document.getElementById("z1").value == "") {
alert("Year, Make, and Model are needed");
document.getElementById("z1").focus();
}
else if (document.getElementById("z2").value == "") {
alert("Mileage is needed");
}
else if (document.getElementById("z3").value == "") {
alert("Exterior color is needed");
}
else {
const input1 = document.getElementById("z1").value;
const input2 = document.getElementById("z2").value;
const input3 = document.getElementById("z3").value;
const input4 = document.getElementById("z4").value;
document.getElementById("s1").value =
"Up for sale is a " + input1 + " with " + input2 + " miles. It is finished in "
+ input3 + ". It has these options: " +input4+ "."
}
}
function reset() {
document.getElementById("s1").value = "";
}
function hide() {
document.getElementById("s1").style.display = "none";
document.getElementById("r1").style.display = "none";
}
</script>
</head>
<body onload="hide()">
<table>
<tr>
<td>
<input type="text" id="z1" placeholder="Year, Make, Model" name="name" maxlength="100">
</td>
<td>
<input type="text" id="z2" placeholder="Mileage" name="name" maxlength="100">
</td>
<td>
<input type="text" id="z3" placeholder="Exterior Color" name="name" maxlength="100">
</td>
<td>
<select data-placeholder="Options" name="options" id="z4" multiple class="chosen-select">
<option value=""></option>
<option value="navigation">Navigation</option>
<option value="aux">Aux</option>
<option value="usb ports">USB Ports</option>
<option value="heated seats">Heated Seats</option>
</select>
</td>
</tr>
<tr>
</table>
<br>
<div class="display">
<button onclick="sentence()"> Submit </button>
</div>
<hr>
<br>
<textarea rows="10" cols="100" id="s1"></textarea>
<br>
<div class="display">
<button onclick="reset()" id="r1">Reset</button>
</div>
</body>
</html>
You need to loop the selections to get all of them e.g.
const input1 = document.getElementById("z1").value;
const input2 = document.getElementById("z2").value;
const input3 = document.getElementById("z3").value;
var input4 = '';
for(var i=0; i< document.getElementById("z4").options.length; i++) {
if(document.getElementById("z4").options[i].selected) {
if(input4 === '') {
input4 = document.getElementById("z4").options[i].value;
} else {
input4 += ' and ' + document.getElementById("z4").options[i].value;
}
}
}
I've done an example here with a basic for loop using javascript. You could make this more efficient, but it demonstrates the idea...
[EDIT] Revising original question for better clarity
This section of this form allows the user to add as many rows as necessary, and works. My problem is that I cannot figure out how to make the character count work on the textarea of the cloned rows.
(Thanks to zer00ne for the all the awesome help here. Great, concise coding! Also provided a jQuery character count in a fraction of lines compared to my former Javascript code.)
Here's a fiddle: https://jsfiddle.net/RationalRabbit/2vmqk26b/4/
CSS
textarea,
output,
button {font-size:inherit;}
output:nth-of-type(n+2) {margin-left:3px;}
.msg {border:none;}
.clearfix:before,
.clearfix:after {display:table; content: "";}
.clearfix:after {clear:both;}
.RowDeleteButton {float:right; font-family:arial, sansserif; font-size:14px; display:inline-block; text-decoration:none; color:#AC0F0F; font-weight:900; cursor:pointer;}
.RowDeleteButton:hover, .RowDeleteButton:focus {color:#FF0000;}
HTML
<fieldset>
<div class="parent-group">
<div class="form-group">
<input id="Name" name="Name[]" size="20" value="" />
<input type="checkbox" id="HM" name="HM[]" value="X" />
<textarea class="txt" id="TA" rows="1" cols="30" name="TA[]" maxlength="100"></textarea>
<input class='msg' name="Output" id="Output" size="3" readonly value="100" />
<input type="text" name="Location[]" id="Location" size="30" value="" />
<div class="form-group RowDelete">
<a class="RowDeleteButton" id="DeleteRow" href="javascript:void(0)"> X </a>
</div>
<div class="Clear"></div>
</div>
</div>
<div class="clearfix"></div>
<div id="container"></div>
<div class="form-group">
<a id="AddRow" href="javascript:void(0)"><span style="color:#0F61AC;">Add Row</span></a>
</div>
</fieldset>
jQuery
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
// onkeyup invoke charCount
$('.txt').on('keyup', charCount);
// onclick...
$('#DeleteRow').closest('.form-group').hide();
$('#AddRow').on('click', function (e)
{
var len = $('.child-border').length;
$('.parent-group').clone(true, false).find(':input').each(function (idx, ele)
{
ele.name = ele.name + len;
ele.id = ele.id + len;
ele.value = '';
}).end().find('.form-group').toggle(true).end()
.toggleClass('parent-group child-border').hide()
.appendTo('#container').slideDown('slow');
});
$('#container').on('click', '[id^=DeleteRow]', function(e)
{
var jsonData = $(this).closest('.child-border, .parent-group')
.find(':input:not(button)').get()
.reduce(function (acc, ele)
{
acc[ele.name || ele.id] = ele.value;
return acc;
}, {});
$(this).closest('.child-border, .parent-group').remove();
console.log(jsonData);
});
function charCount(e)
{
// Get the text
var chars = this.value;
// Get maxlength as a number
var charMax = Number(this.getAttribute('maxlength'));
// Number of chars typed
var charDone = chars.length;
// Chars remaining is 100 - chars typed
var charToGo = charMax - charDone;
// Display chars remaining
$(this).next('.msg').val(charToGo);
}
</script>
2nd Update
I already said what the issue was in Update 1:
$('.parent-group').clone(true, false).find(':input')
🔺
The second parameter should be true
This will allow the clone() method to keep registered events on the clone. Notice I had said the same thing on the 1st Update, but I failed to change the code in Demo 2.
Demo 3 is a heavy modification of the most currently updated OP code. It is fully functional and it retains registered events on clones just like Demo 2. Added features are: local/sessionStorage, sends data to a live test server, and displays server response.
Demo 4 is OP code and one simple change...want to take a wild guess as to what that might be?.
1st Update
When cloning, use the first parameter to determine whether the clone keeps the registered event handlers the original node has.
$('#original').clone(true, true);
See Demo 2
Not sure what you mean by "one row". This demo is streamlined compared to OP code. I added auto height instead of cloning rows.
Details commented in demo
Demo 1
// On keyup...
$('#txt').on('keyup', function() {
// Get the text
var chars = this.value;
// if there are any linebreaks...
if (chars.match(/\n/g)) {
/* The value of rows attribute equals
|| the number of line breaks +2
*/
this.rows = chars.match(/\n/g).length + 2;
}
/* Get value of maxlength attribute convert
|| to number
*/
var charMax = Number(this.getAttribute('maxlength'));
// Number of chars typed
var charDone = chars.length;
// Chars remaining is 100 - chars typed
var charToGo = charMax - charDone;
// Display chars remaining
$('#msg').val(charToGo + ' characters remaining');
});
<textarea id='txt' rows="1" cols="30" maxlength="100"></textarea><br>
<output id='msg' for='txt'></output>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Demo 2
// onkeyup invoke charCount
$('.txt').on('keyup', charCount);
// onclick...
$('button').on('click', function() {
/* clone the first .txt and .msg
|| true: keep registered events
|| false: copy content
|| set .val('') to blank
|| add to fieldset
*/
$('.txt:first').clone(true, true).val('').appendTo('fieldset');
$('.msg:first').clone(true, true).val('').appendTo('fieldset');
});
function charCount(e) {
// Get the text
var chars = this.value;
// Get maxlength as a number
var charMax = Number(this.getAttribute('maxlength'));
// Number of chars typed
var charDone = chars.length;
// Chars remaining is 100 - chars typed
var charToGo = charMax - charDone;
// Display chars remaining
$(this).next('.msg').val(charToGo + ' characters remaining');
}
textarea,
output,
button {
font-size: inherit
}
output {
display: inline-block;
vertical-align: top;
}
output:nth-of-type(n+2) {
margin-left: 3px
}
button {
margin-left: 90%
}
<button type='button'>Add</button>
<fieldset>
<textarea class='txt' rows="1" cols="30" maxlength="100"></textarea>
<output class='msg'></output>
</fieldset>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Demo 3
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
<title></title>
<style>
textarea,
output,
button {
font-size: inherit;
}
output:nth-of-type(n+2) {
margin-left: 3px;
}
.msg {
border: none;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.del {
float: right;
margin-top: .5px;
font-family: arial, sansserif;
font-size: 14px;
display: inline-block;
text-decoration: none;
color: #AC0F0F;
font-weight: 900;
cursor: pointer;
}
.del:hover,
.del:focus {
color: #FF0000;
}
main {
display: table;
}
</style>
<script>
/* Global counter variable */
var counter = 0;
</script>
</head>
<body>
<main class="main-group">
<!--This form submits to a live test server, the [target] attribute value
is that of an iframe's name attribute. By targeting the iframe the
form can display the test server's response in the iframe
-->
<form id='main' action='https://httpbin.org/post' method='post' target='response'>
<!--The original fieldset is cloned-->
<fieldset id='set' class="form-group">
<button id="del" class='ui del' type='button'> X </button>
<input id='ID' name='ID' class='data' type='hidden'>
<input id="name" name="name" class='data name' size="25">
<input id="chx" name="chx" class='data chx' type="checkbox" value="X">
<br>
<textarea id="txt" name="txt" class='data txt' rows="1" cols="30" maxlength="100"></textarea>
<output class='ui msg'></output>
<br>
<input id="loc" name="loc" class='data loc' size="30">
</fieldset>
</form>
<nav class="btn-group">
<a id="add" href="#/" class='ui'> <b style="color:#0F61AC;">Add Row</b> </a>
<!--This submit button must use the [form] attribute with the ID of the
form to be accociated with-->
<input type='submit' form='main' class='ui'>
</nav>
<iframe src='about:blank' name='response' class='ui'></iframe>
</main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
// Click...
$('#add').on('click', function(e) {
// Increment counter
counter++;
/* clone fieldset#set true: clone descendants /
|| TRUE: KEEP EVENTS ON CLONES
|| Gather all of the .data in clone then on each clone...
*/
var dupe = $('#set').clone(true, true);
dupe[0].id = 'set' + counter;
dupe.find('.data').each(function(idx, ele) {
// Set all .data with name and id, the counter suffix makes them unique
ele.name = this.name + counter;
ele.id = this.id + counter;
// Clear all data in each .data
ele.value = '';
// Cool animation and append clone to form#main
}).end().find('.form-group').toggle(true).end().hide().appendTo('#main').slideDown('slow');
// Clear .ui of data
dupe.find('output').val('');
dupe.find(':checkbox').prop('checked', false);
});
// Clicking any button.del...
$('.del').on('click', function(e) {
// Define arrays
var jsonData = [];
var JSONKeys = [];
// This collects all accossiated .data of ,del
var dataRow = $(this).nextAll('.data').toArray();
// This map() will create an object literal and add it to an array
jsonData = dataRow.map(function(data, idx) {
var D = {};
D.k = data.id;
D.v = data.value;
return D;
});
console.log(jsonData);
// Proceedure to timestamp data
var stamp = new Date();
var jKey = stamp.toJSON();
// Fill an array of keys for future reference
JSONKeys.push(jKey);
/* Store JSON data in sessionStorage (can be localStorage also) */
setData(jKey, jsonData);
// Save an index of the jsondata
setData('JSONKeys', jKey);
// if there's only one fieldset, reset the form if user tries to delete it
if ($('fieldset').is(':only-child')) {
$('#main')[0].reset();
} else {
// Remove fieldset
$(this).parent('.form-group').remove();
}
});
// onkeyup invoke charCount
$('.txt').on('keyup', charCount);
function charCount(e) {
// Get the text
var chars = this.value;
// Get maxlength as a number
var charMax = Number(this.getAttribute('maxlength'));
// Number of chars typed
var charDone = chars.length;
// Chars remaining is 100 - chars typed
var charToGo = charMax - charDone;
// Display chars remaining
$(this).next('.msg').val(charToGo);
}
function setData(dataKey, dataVal) {
sessionStorage.setItem(dataKey, JSON.stringify(dataVal));
}
function getData(dataKey) {
return JSON.parse(sessionStorage.getItem(dataKey));
}
</script>
</body>
</html>
Demo 4
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
<title></title>
</head>
<body>
<fieldset>
<div class="parent-group">
<div class="form-group">
<input id="Name" name="Name[]" size="20" value="" />
<input type="checkbox" id="HM" name="HM[]" value="X" />
<textarea class="txt" id="TA" rows="1" cols="30" name="TA[]" maxlength="100"></textarea>
<input class='msg' name="Output" id="Output" size="3" readonly value="100" />
<input type="text" name="Location[]" id="Location" size="30" value="" />
<div class="form-group RowDelete">
<a class="RowDeleteButton del" href="javascript:void(0)"> X </a>
</div>
<div class="Clear"></div>
</div>
</div>
<div class="clearfix"></div>
<div id="container"></div>
<div class="form-group">
<a id="AddRow" href="javascript:void(0)"><span style="color:#0F61AC;">Add Row</span></a>
</div>
</fieldset>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
// onclick...
$('#DeleteRow').closest('.form-group').hide();
$('#AddRow').on('click', function(e) {
var len = $('.child-border').length;
$('.parent-group').clone(true, true).find(':input').each(function(idx, ele) {
ele.name = ele.name + len;
ele.id = ele.id + len;
ele.value = '';
}).end().find('.form-group').toggle(true).end()
.toggleClass('parent-group child-border').hide()
.appendTo('#container').slideDown('slow');
});
$('.del').on('click', function(e) {
var jsonData = $(this).closest('.child-border, .parent-group')
.find(':input:not(button)').get()
.reduce(function(acc, ele) {
acc[ele.name || ele.id] = ele.value;
return acc;
}, {});
$(this).closest('.child-border, .parent-group').remove();
console.log(jsonData);
});
function charCount(e) {
// Get the text
var chars = this.value;
// Get maxlength as a number
var charMax = Number(this.getAttribute('maxlength'));
// Number of chars typed
var charDone = chars.length;
// Chars remaining is 100 - chars typed
var charToGo = charMax - charDone;
// Display chars remaining
$(this).next('.msg').val(charToGo);
}
// onkeyup invoke charCount
$('.txt').on('keyup', charCount);
</script>
</body>
</html>
Using zer00ne's Demo 4, this is what I finally came up with. the differences are:
1. Set the first working row as array for database insert using regex. Also designated unique row input id's using parentheses.
2. Set delete button so that it does not appear on first row.
3. My script sets a max number of rows (8).
4. Global variable used to hold row count. Important in the event that the user deletes a row or rows in the middle of the set, then adds rows below.
5. Set checkbox so that the value is kept in cloned rows. "checked" set to false.
The PHP shows how I handled the array server-side so that I come out with arrays in numerical order. This could probably be handled differently, but worked for me. Without using the LastArrayValue variable to handle the last array value, and the ChildCount variable, which says how many rows there actually are, if you delete, for instance, rows 2 & 3 out of eight, you would only have 6 rows, but not be allowed to add additional. Also, without those variables, when rows are deleted in the middle, you will end up with duplicate array keys. This becomes even more critical when you have a max number of rows to deal with.
https://jsfiddle.net/uyz2zjj6/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
<title></title>
<style type="text/css">
textarea,
output,
button {font-size:inherit;}
output:nth-of-type(n+2) {margin-left:3px;}
.msg {border:none;}
.clearfix:before,
.clearfix:after {display:table; content: "";}
.clearfix:after {clear:both;}
.RowDeleteButton {float:right; font-family:arial, sansserif; font-size:14px; display:inline-block; text-decoration:none; color:#AC0F0F; font-weight:900; cursor:pointer;}
.RowDeleteButton:hover, .RowDeleteButton:focus {color:#FF0000;}
</style>
</head>
<body>
<fieldset>
<div class="parent-group">
<div class="form-group">
<input id="Name(0)" name="Name[0]" size="20" value="" />
<input type="checkbox" id="HM(0)" name="HM[0]" value="X" />
<textarea class="txt" id="TA(0)" rows="1" cols="30" name="TA[0]" maxlength="100"></textarea>
<input class='msg' name="Output" id="Output(0)" size="3" readonly value="100" />
<input type="text" name="Location[0]" id="Location(0)" size="30" value="" />
<div class="form-group" style="display:inline-block;">
<a class="RowDeleteButton del" id="DeleteRow" href="javascript:void(0)"> X </a>
</div>
<div class="Clear"></div>
</div>
</div>
<div class="clearfix"></div>
<div id="container"></div>
<div class="form-group">
<a id="AddRow" href="javascript:void(0)"><span style="color:#0F61AC;">Add Row</span></a>
</div>
</fieldset>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
// onclick...
window.LastArrayValue = 0;
$('#DeleteRow').closest('.form-group').hide();
$('#AddRow').on('click', function(e)
{
var ChildCount = $('.child-group').length;
if(ChildCount == 7)
{
alert("Sorry, 8 is the maximum number of rows");
}
else
{
var len = window.LastArrayValue;
window.LastArrayValue = len + 1;
$('.parent-group').clone(true, true).find(':input').each(function(idx, ele)
{
var ename = ele.name;
var eid = ele.id
var ArrayValue = len+1;
ele.name = ename.replace(/(\[\/?[^\]]*\])/g, "["+ArrayValue+"]");
ele.id = eid.replace(/(\(\/?[^\]]*\))/g, "("+ArrayValue+")");
if(ele.type == "checkbox"){ele.checked = false;}
else{ele.value = '';}
}).end().find('.form-group').toggle(true).end()
.toggleClass('parent-group child-group').hide()
.appendTo('#container').slideDown('slow');
}
});
$('.del').on('click', function(e)
{
var jsonData = $(this).closest('.child-group, .parent-group')
.find(':input:not(button)').get()
.reduce(function(acc, ele)
{
acc[ele.name || ele.id] = ele.value;
return acc;
}, {});
$(this).closest('.child-group, .parent-group').remove();
console.log(jsonData);
});
function charCount(e)
{
// Get the text
var chars = this.value;
// Get maxlength as a number
var charMax = Number(this.getAttribute('maxlength'));
// Number of chars typed
var charDone = chars.length;
// Chars remaining is 100 - chars typed
var charToGo = charMax - charDone;
// Display chars remaining
$(this).next('.msg').val(charToGo);
}
// onkeyup invoke charCount
$('.txt').on('keyup', charCount)
</script>
</body>
</html>
PHP
// Get the last key number in the array in the event that rows were deleted
// TA is the only required field. If that field is not filled, the row is ignored
end($_POST['TA']); // move the internal pointer to the end of the array
$key = key($_POST['TA']); // fetches the key of the element pointed to by the internal pointer
$Ct = $key+1; // account for array start at 0
reset($_POST['TA']); // Reset the array back to the top for processing.
$j=0; // Count only if TA has a value (revaluate $Ct when complete for later use ($Ct = $j))
for($i=0;$i<$Ct;$i++)
{
if(empty($_POST['TA'][$i])) // Empty may be that field is empty or there is no such row.
{
continue;
}
$Name[$j] = $_POST['Name'][$i];
$HM[$j] = $_POST['HM'][$i];
$TA[$j] = $_POST['TA'][$i];
$Location[$j] = $_POST['Location'][$i];
$j++;
}
$Ct = $j; // $Ct now holds the number of records and those records are in numerical order, 1-8
how would I remove a list item from my to do list onclick! And how would i set up a counter to add and display how many tasks i have and how many left once one is deleted.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Task 1</title>
<link rel="stylesheet" href="styles.css" type="text/css">
<script src="script.js"></script>
</head>
<body>
<div id="container">
<h1>My To Do List</h1>
<input type="text" id="input_field" name="input_field" placeholder="Enter New Task" required>
<button type="button" id="add" onclick="addtask()" > Add Task</button>
</div>
<ul id="todo_list"></ul>
</body>
</html>
JavaScript
function addtask() {
var input = document.getElementById('input_field').value;
if (input == "") {
window.alert("You must enter a value in the New Task field.");
}
else {
var noteList = document.getElementById('todo_list');
noteList.innerHTML += "<li>" + input + "<button id='delete'>clear</button></li>";
}
}
Add an onclick event to clear button and call the function clearItem() that deletes the item.
For your second question,
And how would i set up a counter to add and display how many tasks i
have and how many left once one is deleted.
Add a variable total_added that increment when the user adds an item, and another variable remaining that decrement when the user clears an item.
var total_added = 0; //initialize the var to zero
var remaining = 0; //initialize the var to zero
function addtask() {
var input = document.getElementById('input_field').value;
if (input == "") {
window.alert("You must enter a value in the New Task field.");
}
else {
var noteList = document.getElementById('todo_list');
noteList.innerHTML += "<li>" + input + "<button id='delete' onclick='clearItem()'>clear</button></li>";
total_added++;
remaining++; //increment total_added and remaining when user adds an item
document.getElementById('total_added').innerHTML = "Total number of tasks added = " + total_added;
document.getElementById('remaining').innerHTML = "Number of tasks remaining = " + remaining;
}
}
function clearItem() {
event.currentTarget.parentElement.remove();
remaining--; //decrement remaining when user clears an item
document.getElementById('remaining').innerHTML = "Number of tasks remaining = " + remaining;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Task 1</title>
<link rel="stylesheet" href="styles.css" type="text/css">
<script src="script.js"></script>
</head>
<body>
<div id="container">
<h1>My To Do List</h1>
<input type="text" id="input_field" name="input_field" placeholder="Enter New Task" required>
<button type="button" id="add" onclick="addtask()" > Add Task</button>
</div>
<ul id="todo_list"></ul>
<p id="total_added">Total number of tasks added = 0</p>
<p id="remaining">Number of tasks remaining = 0</p>
</body>
</html>
I think counter of the list is unnecessary. You could always count childNode in your todo_list for the left todo list. But counter for deleted list is still useful.
var list_now = document.getElementById('todo_list').childNodes.length;
Add the removeTask() function in the onClick event of the delete button and add the removeTask function.
Like this :
JS :
function addtask() {
var input = document.getElementById('input_field').value;
if (input == "") {
window.alert("You must enter a value in the New Task field.");
} else {
var noteList = document.getElementById('todo_list');
noteList.innerHTML += "<li>" + input + "<button id='delete' onclick='removeTask()' >clear</button></li>";
countItems();
}
}
function removeTask() {
event.currentTarget.parentElement.remove();
countItems();
}
function countItems() {
var count = document.querySelectorAll("#todo_list > li").length;
document.getElementById("count").innerHTML = count + ' item(s)';
}
HTML :
<div id="container">
<h1 id="title">My To Do List</h1>
<p id="count"></p>
<input type="text" id="input_field" name="input_field" placeholder="Enter New Task" required>
<button type="button" id="add" onclick="addtask()"> Add Task</button>
</div>
<ul id="todo_list"></ul>
CodePen
I'm making an application where the user fills out all the information for a logo and adds it to a list where he can then add more logos or delete them.
Imagine I add a logo to the list with the following information:
Name: Pepsi
Location: Front, Back
Dimensions: 90mm, 60mm
Colors: Red, Blue, White
Options: Whitebg
Comment: This is a cool logo.
The array would be:
logos[logo[name, loc[], dim[], col[], opt[], com]]
Now I can do this to retrieve some info:
logos[0][0] //Prints "Pepsi"
logos[0][1][0] //Prints "Front"
logos[0][2][1] //Prints "60mm"
Now comes the problem. Whenever the user completes all the info and adds the logo the list I want to empty all the arrays except the main "logos" one so the user can add another logo to the list.
I tried to empty the "logo" array at the end of the "add" button function:
logo.length = 0;
But now the main array "logos" contains one "logo" array witch is empty. I want to keep that information there.
I think you could look at this differently.
I think you should just have a main logos array. And a Logo Object.
The Logo Object.
function Logo(name,loc, dim, col, opt, com){
return {
name:name,
loc:loc,
dim:dim,
col:col,
opt:opt,
com:com
}
}
var logos = [];
logos.push(Logo("blah",somthing[],else[]....);
Then reference by:
logos[0].name;
logos[0].dimensions[0];
....
you can add another...
logos.push(Logo("another",....));
Another Option
Same thing as before.
But instead of a Logos[]
Use a Logos = {} object.
You can dynamically add properties by given input like this.
Logos["First"] = Logo(loc,dim,col,opt,com);
Logos["Second"] = Logo(loc2,dim2,col2,opt2,com2);
If the user inputs that they want the "First" logo.
You can use
var firstlogo = Logos["first"];
firstlogo.loc[0] etc.
Play around with it, using objects provides a better understanding of the data you are dealing with, esp when multidimensional arrays are not "required"
I think you want do this :
var tempLogo = new Array();
tempLogo[0] = logos[0]; // or the logo you have choose
// Clear the logo
logos.clear();
// Set the logos with the tempLogo value
logos = tempLogo;
Finally I used objects instead of arrays as "Bodman" suggested. Works much better and is simpler.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<meta charset="utf-8" />
<link href="css/reset.css" rel="stylesheet" type="text/css"/>
<link href="css/master.css" rel="stylesheet" type="text/css" media="screen"/>
</head>
<body>
<form action="/" method="post" id="form">
<p><label for="">Name:</label><input type="text" id="name"/></p>
<p><label for="">Location:</label><input type="checkbox" name="loc" value="Front"/> Front <input type="checkbox" name="loc" value="Back"/> Back <input type="checkbox" name="loc" value="Right"/> Right <input type="checkbox" name="loc" value="Left"/> Left</p>
<p><label for="">Dimensions:</label>H: <input type="text" size="4" id="dimH"/> W: <input type="text" size="4" id="dimW"/></p>
<p><label for="">Colors:</label><input type="text" size="4" id="col1" /> <input type="text" size="4" id="col2" /> <input type="text" size="4" id="col3" /> <input type="text" size="4" id="col4" /></p>
<p><label for="">Comments:</label><textarea id="com" cols="30" rows="2"></textarea></p>
<p><label for=""> </label><input type="button" id="add" value="Add" /> <input type="button" id="del" value="Del" /></p>
</form>
<ul id="results"></ul>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script type="text/javascript" src="js/scripts.js"></script>
</body>
</html>
CSS:
body { padding: 50px; }
p { margin: 10px 0; }
label { float: left; width: 100px; }
input { margin: 0 }
ul input[type="checkbox"]{ float:left; }
ul { list-style: none;}
li { margin: 10px 0; }
li div { margin-left: 20px; }
h2 { font: bold 14px Arial; margin-bottom: 5px; }
jQuery:
$(function(){
function logo(name, loc){
var locSize = loc.length;
return {
name: name,
loc: loc,
locSize: locSize
}
}
var logos = [];
$("#add").click(function(){
var name = $("#name").val();
var loc = [];
$("input[name='loc']:checked").each(function(){
loc.push($(this).val());
});
logos.push(logo(name, loc));
$("#results").children().remove();
$.each(logos, function(n){
$("#results").append("<li><input type='checkbox'/><div><h2>" + logos[n].name + "<h2/> Locations(" + logos[n].locSize + "): " + logos[n].loc.join(", ") + "<div/></li>");
});
});
$("#del").click(function(){
$("#results input[type='checkbox']:checked").each(function(){
var index = $(this).closest("li").index();
logos.splice(index, 1);
$(this).closest("li").remove();
});
});