Trying to add "this" object to an array (Javascript) - javascript

I'm trying to make it so when you push a button you add a note to the page. When I push the button, the new note flashes. I'm trying to get it to stay.
When I use a regular bracket object the new note stays. I could just switch to using one, but I wanna know if it's possible to make it work with a "this" object before switching.
The button used to add the note is under the "Note Drop-down" button
var dummyNotes = [];
class NewNote {
constructor(id, title, details, date) {
this.id = id;
this.title = title;
this.details = details;
this.date = date;
this.titleFormat = function() {
return `<span class="titleSpan">
<input type="text" class="noteTitle inputControls" value="${this.title}" maxlength="50">
<label class="editLabel detailScript">0/50</label>
<label class="editLabel errorMessage">Character limit reached!</label>
<span class="noteButtons">
<button class="editTitle">Edit</button>
<button class="deleteNote">Delete</button>
</span>
<span class="noteInfo">
<label class="theDate">${this.date}</label>
<label class="theID">${this.id}</label>
</span>
</span>`;
}
this.detailsFormat = function() {
return `<span class="detailsSpan">
<details><summary>Click for Details</summary>
<textarea class="noteDetails inputControls" maxlength="100">${this.details}</textarea>
<label class="editLabel detailScript">0/100</label>
<label class="editLabel errorMessage">Character limit reached!</label>
<button class="editDetails">Edit</button>
</details>
</span>`;
}
}
}
let newNoteInput = document.getElementById("newNoteInput");
newNoteInput.addEventListener('submit', addANote);
function addANote(){
/*If this fails, just copy paste what's under, insert values */
const pushNote = new NewNote(generateID(), newNoteTitle.value, newNoteDetails.value, dateNote.toLocaleDateString());
dummyNotes.push(pushNote);
addNewNote(pushNote);
newNoteTitle.value = "";
newNoteDetails.value = "";
}
function addNewNote(pushNote) {
const theNewNote = document.createElement("div");
theNewNote.classList.add("newNote");
const theNewNoteForm = document.createElement("form");
theNewNoteForm.classList.add("noteForm");
theNewNote.appendChild(theNewNoteForm);
theNewNoteForm.innerHTML = pushNote.titleFormat() + pushNote.detailsFormat();
noteList.appendChild(theNewNote); /*APPEND CHILD to get every item on the list*/
}
function init() {
dummyNotes.forEach(addNewNote);
noteList.innerHTML = "";
}
init();
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="Notes.css">
<meta name="viewport" content="width=device-width" initial-scale="1.0">
<title>Notes</title>
</head>
<body>
<div id="container">
<div id="noteContainer">
<details id="buttonContainer">
<summary id="toggleContainer">Note Drop-Down</summary>
<span id="newNoteToggle">
<form id="newNoteInput">
<span>
<input type="text" id="newNoteTitle" class="inputControls" placeholder="Title" maxlength="50">
<label class="newLabel detailScript">0/50</label>
<label class="newLabel errorMessage">Character limit reached!</label>
</span>
<span>
<input type="textarea" id="newNoteDetails" class="inputControls" placeholder="Details" maxlength="100">
<label class="newLabel detailScript">0/100</label>
<label class="newLabel errorMessage">Character limit reached!</label>
</span>
<button id="addButton">Add New Note</button>
</form>
</span>
</details>
<div id="noteList">
<div class="newNote">
<form class="noteForm">
<span class="titleSpan">
<input type="text" class="noteTitle" value="Note Title">
<button class="editTitle">Edit</button>
<button class="deleteNote">Delete</button>
<label class="theDate">The Date</label>
<label class="theDate">ID</label>
</span>
<span class="detailsSpan">
<details><summary>Click for Details</summary>
<textarea class="noteDetails"></textarea>
<button class="editDetails">Edit</button>
<span id="wordCount"></span>
</details>
</span>
</form>
</div>
</div>
</div>
<div id="searchContainer">
<details id="searchForm">
<summary><h4>Search Notes</h4></summary>
<form>
<input id="searchDate" type="date" placeholder="Date">
<input id="searchTitle" type="text" placeholder="Title">
<button id ="searchButton">Search</button>
</form>
</details>
</div>
</div>
<script src="Notes.js"></script>
</body>
</html>

Yep, as I suspected, your form was definitely posting without preventing default.
Please review the code, I've commented everywhere I made changes.
//was getting errors for these variables not being defined.
var dummyNotes = [],
dateNote = new Date();
class NewNote {
constructor(id, title, details, date) {
this.id = id;
this.title = title;
this.details = details;
this.date = date;
this.titleFormat = function() {
return `<span class="titleSpan">
<input type="text" class="noteTitle inputControls" value="${this.title}" maxlength="50">
<label class="editLabel detailScript">0/50</label>
<label class="editLabel errorMessage">Character limit reached!</label>
<span class="noteButtons">
<button class="editTitle">Edit</button>
<button class="deleteNote">Delete</button>
</span>
<span class="noteInfo">
<label class="theDate">${this.date}</label>
<label class="theID">${this.id}</label>
</span>
</span>`;
}
this.detailsFormat = function() {
return `<span class="detailsSpan">
<details><summary>Click for Details</summary>
<textarea class="noteDetails inputControls" maxlength="100">${this.details}</textarea>
<label class="editLabel detailScript">0/100</label>
<label class="editLabel errorMessage">Character limit reached!</label>
<button class="editDetails">Edit</button>
</details>
</span>`;
}
}
}
let newNoteInput = document.getElementById("newNoteInput");
//changed this function to run an anonymous function, prevent default and then call addANote():
newNoteInput.addEventListener('submit', function(e) {
e.preventDefault();
addANote();
});
function addANote(){
/*If this fails, just copy paste what's under, insert values */
const pushNote = new NewNote(generateID(), newNoteTitle.value, newNoteDetails.value, dateNote.toLocaleDateString());
dummyNotes.push(pushNote);
addNewNote(pushNote);
newNoteTitle.value = "";
newNoteDetails.value = "";
return false;
}
function addNewNote(pushNote) {
const theNewNote = document.createElement("div");
theNewNote.classList.add("newNote");
const theNewNoteForm = document.createElement("form");
theNewNoteForm.classList.add("noteForm");
theNewNote.appendChild(theNewNoteForm);
theNewNoteForm.innerHTML = pushNote.titleFormat() + pushNote.detailsFormat();
noteList.appendChild(theNewNote); /*APPEND CHILD to get every item on the list*/
}
function init() {
dummyNotes.forEach(addNewNote);
noteList.innerHTML = "";
}
//was getting error due to this function not existing, so I threw this in here:
function generateID() {
return parseInt(Math.random() * 10000);
}
init();
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="Notes.css">
<meta name="viewport" content="width=device-width" initial-scale="1.0">
<title>Notes</title>
</head>
<body>
<div id="container">
<div id="noteContainer">
<details id="buttonContainer">
<summary id="toggleContainer">Note Drop-Down</summary>
<span id="newNoteToggle">
<form id="newNoteInput">
<span>
<input type="text" id="newNoteTitle" class="inputControls" placeholder="Title" maxlength="50">
<label class="newLabel detailScript">0/50</label>
<label class="newLabel errorMessage">Character limit reached!</label>
</span>
<span>
<input type="textarea" id="newNoteDetails" class="inputControls" placeholder="Details" maxlength="100">
<label class="newLabel detailScript">0/100</label>
<label class="newLabel errorMessage">Character limit reached!</label>
</span>
<button id="addButton">Add New Note</button>
</form>
</span>
</details>
<div id="noteList">
<div class="newNote">
<form class="noteForm">
<span class="titleSpan">
<input type="text" class="noteTitle" value="Note Title">
<button class="editTitle">Edit</button>
<button class="deleteNote">Delete</button>
<label class="theDate">The Date</label>
<label class="theDate">ID</label>
</span>
<span class="detailsSpan">
<details><summary>Click for Details</summary>
<textarea class="noteDetails"></textarea>
<button class="editDetails">Edit</button>
<span id="wordCount"></span>
</details>
</span>
</form>
</div>
</div>
</div>
<div id="searchContainer">
<details id="searchForm">
<summary><h4>Search Notes</h4></summary>
<form>
<input id="searchDate" type="date" placeholder="Date">
<input id="searchTitle" type="text" placeholder="Title">
<button id ="searchButton">Search</button>
</form>
</details>
</div>
</div>
<script src="Notes.js"></script>
</body>
</html>

All I had to do to make the remove button work was write init like this:
function init() {
noteList.innerHTML = "";
dummyNotes.forEach(addNewNote);
}
noteList.innerHTML just needed to be on top!

Related

How to get an span from its textnode or text content?

I have a form with 3 fields:
<form id="book-form">
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" class="form-control" placeholder="Enter a title">
</div>
<div class="form-group">
<label for="author">Author</label>
<input type="text" name="author" class="form-control" placeholder="Enter the author of the book">
</div>
<div class="form-group">
<label for="isbn">ISBN#</label>
<input type="text" name="isbn" class="form-control" placeholder="Enter the book isbn">
</div>
<button type="submit" class="btn btn-primary btn-block">Add Book to store</button>
</form>
Here are I am retrieving the value of these fields that I will insert in their respective span in the html.
const title = document.getElementsByName('title')[0].value
const author = document.getElementsByName('author')[0].value
const isbn = document.getElementsByName('isbn')[0].value
Now I have three span tags where the value of these form fields are suppose to be inserted.
<span class="title">// the value of title</span>
<span class="author">// the value of author</span>
<span class="isbn">// the value of isbn</span>
Now I have a function that checks if the retrieve from the fields of the form is not empty(null) if that is the case I want to remove the span that is was suppose to be in the dom.
function insertMe(fieldValue) {
if (fieldValue === "") {
// How to remove the span that it was suppose to go
} else {
return fieldValue
}
}
It's not clear how you're calling insertMe, and the name of that function is misleading because you're only removing elements, not adding them.
I'd approach it this way.
When the button is clicked/onSubmit call the function and use querySelectorAll to target all the inputs by class. Iterate over them and if the value is an empty string remove the span whose class matches the name of the input, otherwise set the text content of the span to the input value.
const button = document.querySelector('button');
button.addEventListener('click', handleClick, false);
function handleClick() {
const inputs = document.querySelectorAll('.form-control');
inputs.forEach(({ name, value }) => {
const el = document.querySelector(`span.${name}`);
if (el && !value) {
el.remove();
} else {
el.textContent = value;
}
});
}
<input type="text" class="form-control" name="title" placeholder="Enter a title">
<input type="text" class="form-control" name="author" placeholder="Enter an author">
<input type="text" class="form-control" name="isbn" placeholder="Enter an ISBN number">
<button>Click</button>
<br/><br/>
<span class="title">Title</span><br/>
<span class="author">Author</span><br/>
<span class="isbn">ISBN</span><br/>

I'm getting an NaN error whenever I run this?

I heard that NaN errors are when you are trying to pass an object as a number, yet in my HTML, 'productquantity' is set as a number, so why is it giving me this error? These files operate with another HTML file and another JavaScript file to retrieve data and these 2 display the data. 'productquantity is what is my only hurdle and where the NaN error comes up. If you need the other HTML and Javascript file, please let me know. Thanks in advance!
"use strict";
function getBooking() {
var laptopsprice = 0;
if (sessionStorage.fname != undefined) { //if sessionStorage for username is not empty
//confirmation text
//outputs user details in payment page and stores values to be sent to server in hidden input tags
document.getElementById("confirm_name").textContent = sessionStorage.fname + " " + sessionStorage.lname;
document.getElementById("confirm_email").textContent = sessionStorage.email;
document.getElementById("confirm_phone").textContent = sessionStorage.phone;
document.getElementById("confirm_streetname").textContent = sessionStorage.streetname;
document.getElementById("confirm_suburb").textContent = sessionStorage.suburb;
document.getElementById("confirm_state").textContent = sessionStorage.state;
document.getElementById("confirm_postcode").textContent = sessionStorage.postcode;
document.getElementById("confirm_laptops").textContent = sessionStorage.laptops;
document.getElementById("confirm_productquantity").textContent = Number(sessionStorage.productquantity);
document.getElementById("confirm_cost").textContent = laptopsprice;
laptopsprice = totalproductcost(sessionStorage.laptops, Number(sessionStorage.productquantity));
//values for hidden input tags that send data to the server
document.getElementById("a_name").value = sessionStorage.fname + " " + sessionStorage.lname;
document.getElementById("a_email").value = sessionStorage.email;
document.getElementById("a_phone").value = sessionStorage.phone;
document.getElementById("a_streetname").value = sessionStorage.streetname;
document.getElementById("a_suburb").value = sessionStorage.suburb;
document.getElementById("a_state").value = sessionStorage.state;
document.getElementById("a_postcode").value = sessionStorage.postcode;
document.getElementById("a_laptops").textContent = sessionStorage.laptops;
document.getElementById("a_productquantity").textContent = Number(sessionStorage.productquantity);
document.getElementById("a_cost").value = laptopsprice;
}
}
function totalproductcost(laptops , productquantity) {
var laptopsprice;
if (laptops == "Workstation_Laptop") {
laptopsprice = (productquantity * 2499);
} else if (laptops == "Gaming_Laptop") {
laptopsprice = (productquantity * 1789);
} else if (laptops == "Laptop_Stand") {
laptopsprice = (productquantity * 64);
} else if (laptops == "Office_Laptop") {
laptopsprice = (productquantity * 1499);
}
return laptopsprice;
}
function cancelBooking(){
window.location = "enquiries.html";
sessionStorage.clear();
}
//function for invoking getbooking and validate, cancel booking
function init() {
document.getElementById("paymentform").onsubmit = validate;
document.getElementById("cancelpurchase").addEventListener("click", cancelBooking);
getBooking();//invokes getbooking function
}
//invokes init fuction on window load
window.onload = init;
<!DOCTYPE html>
<html lang="en">
<head>
<script src="scripts/payment.js"></script>
<title>SwinTech</title>
<link rel="stylesheet" type="text/css" href="css/style.css"> </head>
<header class="enquiriespage">
<div class="main">
<div class="logo"> <img src="logo.png" alt="logo"> </div>
<ul>
<li>Home</li>
<li>Products</li>
<li>Enquiries</li>
<li class="active">>Payment</li>
<li>About</li>
</ul>
</div>
</header>
<section class="paymentthing">
<div class="paymentcontainer">
<fieldset>
<legend>Order Summary:</legend>
<p>Your Name: <span id="confirm_name"></span></p>
<p>Your Email: <span id="confirm_email"></span></p>
<p>Your Phone Number: <span id="confirm_phone"></span></p>
<p>Street name: <span id="confirm_streetname"></span></p>
<p>Suburb: <span id="confirm_suburb"></span></p>
<p>State: <span id="confirm_state"></span></p>
<p>Postcode: <span id="confirm_postcode"></span></p>
<p>Product: <span id="confirm_laptops"></span></p>
<p>Product Quantity: <span id="confirm_productquantity"></span></p>
<p>Total Cost: $<span id="confirm_cost"></span></p>
<input type="hidden" name="name" id="a_name" />
<input type="hidden" name="email" id="a_email" />
<input type="hidden" name="phone" id="a_phone" />
<input type="hidden" name="streetname" id="a_streetname" />
<input type="hidden" name="suburb" id="a_suburb" />
<input type="hidden" name="state" id="a_state" />
<input type="hidden" name="cost" id="a_cost" />
<input type="hidden" name="laptops" id="a_laptops" />
<input type="hidden" name="postcode" id="a_postcode" />
<input type="hidden" name="productquantity" id="a_productquantity" />
</fieldset>
<br>
<br>
<form id="paymentform" method="post" action="https://mercury.swin.edu.au/it000000/formtest.php">
<label for="cardType">Please Choose a Card Type:</label>
<br>
<br>
<select name="cardType" id="cardType" required="required">
<option value="">Please Select</option>
<option value="Visa">Visa</option>
<option value="Mastercard">Mastercard</option>
<option value="American Express">AmEx</option>
</select>
<br>
<br>
<label for="cardName" id="cardName">Please Enter Name On Card:</label>
<input type="text" name="cardName" maxlength="40" required="required">
<br>
<br>
<label>Please Enter Credit Card Expiration Date:</label> <span class="expiration">
<input type="tel" name="month" placeholder="MM" maxlength="2" size="2" required="required" />
<span>/</span>
<input type="tel" name="year" placeholder="YY" maxlength="2" size="2" required="required" /> </span>
<br>
<br>
<br>
<label for="cardNo">Credit Card Number:</label>
<input id="cardNo" type="tel" inputmode="numeric" pattern="[0-9\s]{13,19}" autocomplete="cc-number" maxlength="16" placeholder="xxxx xxxx xxxx xxxx" required="required">
<br>
<br>
<input type="submit" value="Check Out">
<br>
<br>
<button type="button" id="cancelpurchase">Cancel Purchase</button>
</form>
</div>
</section>
<div class="footer">
<div class="footer-content"></div>
<div class="footer-bottom"></div> © swintech.com | Designed by Bilal El-leissy </div>
</html>
Anytime you retrieve or set a value to go in a html tag or form element it is a string. Even if you cast that item as a Number(), the DOM will store it as a string. Whenever that string is to be used in a calculation, convert it to a number then with the plus operator, parseInt or parseFloat, as in:
function totalproductcost(laptops , productquantity) {
productquantity = +productquantity;
// OR productquantity = parseInt(productquantity);
// OR productquantity = parseFloat(productquantity); if you have a decimal to consider
var laptopsprice;
if (laptops == "Workstation_Laptop") {
laptopsprice = (productquantity * 2499);
} else if (laptops == "Gaming_Laptop") {
laptopsprice = (productquantity * 1789);
} else if (laptops == "Laptop_Stand") {
laptopsprice = (productquantity * 64);
} else if (laptops == "Office_Laptop") {
laptopsprice = (productquantity * 1499);
}
return laptopsprice;
}
There are two things you might want to check for.
One is that productquantity has a value. If it's undefined or null, Number will return NaN.
The other is that if productquantity is being set as a string, that the string doesn't contain non-numerical characters.
Adding ".value" to the input helped me

How to create a 'add more' feature in HTML forms [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am creating a HTML form in which I need to create a 'add more' button so another field appears. Any help would be appreciated
This isn't possible in pure HTML, but it can easily be achieved using javascript!
Basic example
In the basic example, you have one input field. When you click the add field button an extra input gets added after the last inserted input.
$(document).on('click', '.add_field', function() {
$('<input type="text" class="input" name="field[]" value="">').insertAfter('.input:last');
})
form {
padding: 20px;
}
input {
width: 100%;
margin-bottom: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input type="text" class="input" name="field[]" value="">
</form>
<button type="button" class="add_field">Add field</button>
Copy value
This example is almost the same as the example above with one difference. It copies the value of the previous input. This is done with help of the JQuery .val() method
$(document).on('click', '.add_field', function() {
let value = $('.input:last').val(); // gets the value of the previous input
$('<input type="text" class="input" name="field[]" value="' + value + '">').insertAfter('.input:last');
})
form {
padding: 20px;
}
input {
width: 100%;
margin-bottom: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input type="text" class="input" name="field[]" value="">
</form>
<button type="button" class="add_field">Add field</button>
Input groups
You could also copy an entire input group with multiple input fields.
$(document).on('click', '.add_field', function() {
$('<div class="input-group"><input type="email" class="input" name="email[]" value="" placeholder="Your email"><input type="password" class="input" name="password[]" value="" placeholder="Your password"></div>').insertAfter('.input-group:last');
})
form {
padding: 20px;
}
input {
width: 100%;
margin-bottom: 5px;
}
.input-group {
border-bottom: 1px solid gray;
padding: 5px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="input-group">
<input type="email" class="input" name="email[]" value="" placeholder="Your email">
<input type="password" class="input" name="password[]" value="" placeholder="Your password">
</div>
</form>
<button type="button" class="add_field">Add field</button>
If you need any more examples please leave a comment!
Please try instead,
$(".Addmore").click(function(e) {
e.preventDefault();
// make a separation line
$("#FormItems").append('<hr width="300px">');
// append the input field as your needs
$("#FormItems").append('<input name="user" type="text" placeholder="Username"><br>');
$("#FormItems").append('<input name="email" type="email" placeholder="Email Address">');
});
.formwrapper{
text-align:center;
}
input{
padding:3px;
margin-bottom:5px;
display:inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="formwrapper">
<form>
<div id="FormItems">
<input name="user" type="text" placeholder="Username"><br>
<input name="email" type="email" placeholder="Email Address">
</div>
<input type="button" value="Add More" class="Addmore">
<input type="submit" value="Submit">
</form>
</div>
In a few lines of js and html you can get that :
<button class="add-input">Add one more input</button>
<form action="." method="GET">
<div class="inputs">
<input type="text" name="text[]">
</div>
<input type="submit" value="submit">
</form>
<script>
const addButton = document.querySelector('button.add-input')
const inputDiv = document.querySelector('form .inputs')
addButton.addEventListener('click', ()=>{ // button to add the inputs
let newInput = document.createElement('input')
newInput.name = 'text[]' // add the name of the input
newInput.type = 'text' // add the type of the input
// you can add other attributes before appeding the node into the html
inputDiv.appendChild(newInput)
})
</script>
and you will have this as a result (I used php to prompt the result)
you can add as many input you want/need.
Next step is just doing some css
I hope this is, what you mean
<form>
<input type="text">
<input type="submit" value="cta">
</form>
<button>Add More</button>
<script>
document.querySelector('button').addEventListener('click', () => {
let field = document.createElement('input');
// change field however you'd like
document.querySelector('form').insertBefore(field, document.querySelector('form:last-child'));
})
</script>
You cannot create this using HTML only, you will need javascript. You could use a frontend framework like react.js to make life easy.
For example in react, you could bind an onclick listener on the button and maintain an array of values as state. Use this array to map value to your input. Whenever user clicks the button, you can then simply push a defaultValue to the array and react will handle the rest.
Import React, { useState } from 'react';
const Page = ()=>{
const [ arr, setArr ] = useState([""]);
const handleAdd = ()=>{
setArr([...arr, ""]);
};
return <form>
{arr.map((elem, index)=><input
onChange={ //"implement logic to update value stored in array" }
value={elem}
key={index} /> )}
<button onClick={()=>handleAdd()}>Add</button>
</form>
}
Using Bootstrap and jquery
Only in html is not possible, you need some on click event to trigger the functionality that may change the html dom.
You can use vanilla javascript as well, here is example using jquery library.
It will dynamically add and remove the element
index.html
<!DOCTYPE html>
<html>
<head>
<title>YDNJSY</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
</head>
<body>
<!-- <h1>Lets learn javascript</h1> -->
<div class="col-xs-12">
<div class="col-md-12">
<h3> Actions</h3>
<div id="field">
<div id="field0">
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="action_id">Action Id</label>
<div class="col-md-5">
<input id="action_id" name="action_id" type="text" placeholder=""
class="form-control input-md">
</div>
</div>
<br><br>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="action_name">Action Name</label>
<div class="col-md-5">
<input id="action_name" name="action_name" type="text" placeholder=""
class="form-control input-md">
</div>
</div>
<br><br>
</div>
</div>
<!-- Button -->
<div class="form-group">
<div class="col-md-4">
<button id="add-more" name="add-more" class="btn btn-primary">Add More</button>
</div>
</div>
<br><br>
</div>
</div>
</body>
<script src="./index.js"></script>
</html>
index.js
$(document).ready(function () {
var next = 0;
$("#add-more").click(function (e) {
e.preventDefault();
var addto = "#field" + next;
var addRemove = "#field" + (next);
next = next + 1;
var newIn = ' <div id="field' + next + '" name="field' + next + '"><!-- Text input--><div class="form-group"> <label class="col-md-4 control-label" for="action_id">Action Id</label> <div class="col-md-5"> <input id="action_id" name="action_id" type="text" placeholder="" class="form-control input-md"> </div></div><br><br> <!-- Text input--><div class="form-group"> <label class="col-md-4 control-label" for="action_name">Action Name</label> <div class="col-md-5"> <input id="action_name" name="action_name" type="text" placeholder="" class="form-control input-md"> </div></div><br><br></div>';
var newInput = $(newIn);
var removeBtn = '<button id="remove' + (next - 1) + '" class="btn btn-danger remove-me" >Remove</button></div></div><div id="field">';
var removeButton = $(removeBtn);
$(addto).after(newInput);
$(addRemove).after(removeButton);
$("#field" + next).attr('data-source', $(addto).attr('data-source'));
$("#count").val(next);
$('.remove-me').click(function (e) {
e.preventDefault();
var fieldNum = this.id.charAt(this.id.length - 1);
var fieldID = "#field" + fieldNum;
$(this).remove();
$(fieldID).remove();
});
});
});

How to create dynamic form elements using cloneNode

I'm trying to create an interactive resume template using javascript and html and have managed to use cloneNode to duplicate work history blocks (see attached screenshot)
The problem(s) I am having is that clicking on the add list item button in the cloned/duplicated work history block at the bottom, creates a <li> item in the 1st/cloned element.
The objective is to be able to add or delete ````` list elements within a specific work history block and to also be able to add/remove entire work history sections. Currently it deletes from the top down, which is also an issue.
Thanks for any pointers in advance.
CODE
<!DOCTYPE html>
<html>
<body>
<div id="test">
<div id="node">
<div class="work_history">
<div class="row">
<strong>
<input type="text" name="company" value="ACME Company">
</strong>
</div>
<div class="row">
<input type="text" name="position" value="Cheese Taster">
</div>
<input type="text" name="start" value="1/2019">
<input type="text" name="end" value="2/2020">
<ul id="list">
<li>
<textarea id="task" name="task" rows="4" cols="50">Did some things. Tasted cheese.</textarea>
</li>
<button onclick="addTask()">Add List Item</button>
<button onclick="RemoveTask()">Delete List Item</button>
</ul>
<button onclick="addWork()">Add Work</button>
<button onclick="removeWork()">Remove Work</button>
</div>
</div>
</div>
<script>
function addWork() {
var div = document.getElementById("node");
var cln = div.cloneNode(true);
//cln.setAttribute( 'id', 'newId');
document.getElementById("test").appendChild(cln);
}
function removeWork(){
var last = document.getElementById("test");
// want to delete the last added work history not first
last.removeChild(last.childNodes[0]);
}
function addTask(){
var ul = document.getElementById("list");
var task = document.getElementById("task");
var li = document.createElement("li");
li.setAttribute('id',task.value);
li.appendChild(document.createTextNode(task.value));
ul.appendChild(li);
}
function removeTask(){
var ul = document.getElementById("list");
var task = document.getElementById("task");
var item = document.getElementById(task.value);
ul.removeChild(item);
}
</script>
</body>
</html>
You'd have to use e.currentTarget instead of document.getElementById, otherwise you're only referring to the first instance of it:
function addWork(e) {
const div = e.currentTarget.parentElement;
const cln = div.cloneNode(true);
document.getElementById("test").appendChild(cln);
}
function removeWork(e) {
const last = e.currentTarget.parentElement;
last.parentElement.removeChild(last);
}
function addTask(e) {
const ul = e.currentTarget.parentNode;
let task = ul.children[0].childNodes[1].value;
let li = document.createElement("li");
// Replace paragraph breaks
task = task.replace(/\r?\n|\r/g, " ");
li.innerText = task;
ul.appendChild(li);
}
function removeTask(e) {
const ul = e.currentTarget.parentNode;
ul.removeChild(ul.lastChild);
}
<!DOCTYPE html>
<html>
<body>
<div id="test">
<div id="node">
<div class="work_history">
<div class="row">
<strong>
<input type="text" name="company" value="ACME Company">
</strong>
</div>
<div class="row">
<input type="text" name="position" value="Cheese Taster">
</div>
<input type="text" name="start" value="1/2019">
<input type="text" name="end" value="2/2020">
<ul id="list">
<li>
<textarea name="task" rows="4" cols="50">Did some things. Tasted cheese.</textarea>
</li>
<button onclick="addTask(event)">Add List Item</button>
<button onclick="removeTask(event)">Delete List Item</button>
</ul>
<button onclick="addWork(event)">Add Work</button>
<button onclick="removeWork(event)">Remove Work</button>
</div>
</div>
</div>
</body>
</html>
This allows you to refer to the specific element where the click event occurred and add/remove any elements that are relative within the DOM.
As a side note, it's best practice to have unique id attributes, adding the same id to multiple elements goes against that.
var add_button = $(".add_form_field");
var wrapper = $(".container1");
var max_fields = 9;
var x = 1;
$(add_button).click(function (e) {
e.preventDefault();
if (x < max_fields) {
x++;
$(wrapper).append(
` <div class="email">
<label for="">Year</label>
<input type="text" name="eduYear${x}">
<label for="">Title Name</label>
<input type="text" name="eduTitle${x}">
<label for="">Institution/School Name</label>
<input type="text" name="eduPlace${x}">
<label for="">Details</label>
<input type="text" name="eduNotes${x}"> <br>Delete<hr></div>`
); //add input box
}
});
$(wrapper).on("click", ".delete", function (e) {
e.preventDefault();
$(this).parent("div").remove();
x--;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container1">
<h2>Educations</h2>
<button type="button" class="add_form_field">Add Education
<span style="font-size:16px; font-weight:bold;">+ </span>
</button>
<div class="email">
<label for="">Year</label>
<input type="number" name="eduYear1">
<label for="">Title Name</label>
<input type="text" name="eduTitle1">
<label for="">Institution/School Name</label>
<input type="text" name="eduPlace1">
<label for="">Details</label>
<input type="text" name="eduNotes1">
</div>
you can try this to create dynamic form

Jquery event handling when a checkbox is clicked

edit Updated full code :
I'm working on my first Javascript case i'm stuck here :
I have the following :
$(document).ready(function()
{
$('input, select').on('focus' ,swapPersonClass);
//Blur = Bind an event handler to the “blur” JavaScript event, or trigger that event on an element.
$('input, select').on("change", updateCart);
}
);
// Functions
var swapPersonClass = function()
{
var expression = $(this).attr('id');
switch(expression)
{
case "fullname":
break;
case "email":
$("#arm").removeClass().addClass("pointemail");
break;
case "countpizzas":
$("#arm").removeClass().addClass("pointamount");
break;
default:
$("#arm").removeClass().addClass("pointothers");
}
};
var updateCart = function () {
var change = $(this).attr('id');
console.log(change);
$('input, select').each(function ()
{
switch (change)
{
case "fullname":
$("#displayname").text($('#fullname').val() + ',');
break;
case "countpizzas":
aantalpizzas = $("#countpizzas").val();
if (aantalpizzas > 1) {
$('.plural').show();
} else {
$('.plural').hide();
};
$("#displayamount").text(aantalpizzas);
console.log(aantalpizzas);
break;
case "pizzatype":
PrijsPizza = $("#pizzatype option:selected").data("price");
console.log(PrijsPizza);
break;
case "YesOption":
$("#toppings").show();
break;
case "NoOption":
$("#toppings").hide();
break;
case "toppings":
updateTopping();
break;
};
$("#currenttotal").text(aantalpizzas * PrijsPizza );
});
};
var updateTopping = function ()
{
$(".chk_topping").change(function()
{
var selected_topping = $(this).attr('data-value');
switch(selected_topping)
{
case "salami":
$("#currenttotal").text(aantalpizzas * PrijsPizza );
PrijsTopping += 0.30;
break
}
});
};
var PrijsTopping = 0.30;
var aantalpizzas = 0;
var PrijsPizza = 0;
<!DOCTYPE html>
<html>
<head>
<title>Forms</title>
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Lobster">
<link href='http://fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="assets/css/reset.css"/>
<link rel="stylesheet" href="assets/css/screen.css" type="text/css"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div id="container">
<header>
<h1>Pizza Palace</h1>
</header>
<aside>
<h2><span>Order details</span></h2>
<div id="total">
<p>Your current order total: € <strong id="currenttotal">0</strong></p>
</div>
<p><strong id="displayname"></strong> you are ordering <strong id="displayamount"></strong> pizza<span
class="plural">s</span></p>
<h3>Chosen toppings:</h3>
<div id="toppingmessage">
<p>No toppings selected</p>
<ul>
<li class="hide">Salami</li>
<li class="hide">Olives</li>
<li class="hide">Ansjovis</li>
</ul>
</div>
<h3>Your discount: </h3>
<p id="displaydiscount"></p>
</aside>
<form action="#" method="post">
<figure id="arm"></figure>
<figure id="face"></figure>
<fieldset class="personbody">
<form>
<div>
<label for="fullname">Full Name
<input id="fullname" name="fullnames" type="text" required autofocus>
</label>
</div>
<div>
<label for="email">Email
<input id="email" name="email" type="email" placeholder="Enter Your email" required>
</label>
</div>
<div>
<label for="howmany">How many pizzas would you like?<br><br>
<input id="countpizzas" name="countpizzas" type="number" min="1" max="3" step="1" value="0" required>
</label>
</div>
<div>
<label for="pizzatype">Which type of pizza would you like ? <br>
<select id="pizzatype"name="pizzatype">
<option data-price="4" value="S">Small</option>
<option data-price="5.5" value="M">Medium</option>
<option data-price="7" value="L">Large</option>
</select>
</label>
</div>
<div>
<label for="extratopping">Would you like extra topping? <br>
<input id="YesOption" name="ExtraTopping" type="radio"> Yes
<input id="NoOption" name="ExtraTopping" type="radio"> No
</label>
</div>
<div class="hide" id="toppings">
<label for="toppings">Which toppings would you like?</label>
<input type="checkbox" class="chk_topping" data-value="salami"> Salami
<input type="checkbox" class="chk_topping" data-value="olives"> Olives
<input type="checkbox" class="chk_topping" data-value="ansjovis"> Ansjovis
</div>
<div>
<label for="deliverydate">When do you want the pizza<span class="plural">s</span> to be delivered?
<input id="delivery" name="delivery" type="date" required > </label>
<label for="deliverytime">
<input id="Time" name="Time" type="time" required> </label>
</div>
<label for="discountcode">Do you have a discount code?
<input id="DiscountCode" name="DiscountCode" type="text" pattern="[1-9]{1}-[A-Z]{3}" title="The discount code should be a digit followed by a dash and then 3 uppercase letters" required>
</label>
</div>
</form>
<input type="submit" value="Place your order" name="placeorder"/>
</fieldset>
</form>
<footer><p>Graphics courtesy of © Basecamp </p></footer>
</div>
<script type='text/javascript' src='assets/js/jquery.js'></script>
<script type='text/javascript' src='assets/js/script.js'></script>
</body>
</html>
Why my checkboxes keep telling me it's undefined when selecting them ?
I'm realy not good at javascript so my code will probably be sh*t
Try this
var selected_topping = $(this).data('value');
http://jsfiddle.net/f4Lghy6p/
Found it.
i'm searching for a specefic ID in my select en input fields :
$('input, select').on("change", updateCart);
My checkboxes are located in a DIV with an input fields which don't have an ID.

Categories