This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 7 years ago.
Each time the user clicks the 'add pizza' button, I would like the page to produce another pizza form and add any costs of the additional pizza. I have been able to add a pizza form, but none of the adding up rules are being applied to the cloned element. Any ideas?
HTML:
<div id="pizzaForm">
<fieldset>
<form class="pure-form">
<legend>Pizza</legend>
<label><b>Pizza Type: </b></label>
<select id="pizza">
<option name="margarita">Margarita</option>
<option name="deep-pan">Deep Pan</option>
<option name="stuffed-crust">Stuffed Crust</option>
</select>
<span style="float:right">
<label><b>Pizza Size: </b></label>
<select id="pizzaSize">
<option name="e-small" id="4.99">Extra Small - £4.99</option>
<option name="small" id="5.99">Small - £5.99</option>
<option name="medium" id="6.99">Medium - £6.99</option>
<option name="large" id="8.99">Large - £8.99</option>
<option name="e-large" id="9.99">Extra Large - £9.99</option>
<option name="f-size" id="10.99">Family Size - £10.99</option>
</select>
</span>
</form>
</fieldset>
<fieldset style = "border-top:0px">
<form class="pure-form">
<legend><b>Toppings (99p Each): </b></legend>
<input type="checkbox" name="onions" id="0.99">Onions</input>
<input type="checkbox" name="mushrooms" id="0.99">Mushrooms</input>
<input type="checkbox" name="peppers" id="0.99">Peppers</input>
<input type="checkbox" name="olives" id="0.99">Olives</input>
<input type="checkbox" name="garlic" id="0.99">Garlic</input>
<input type="checkbox" name="peperoni" id="0.99">Peperoni</input>
<input type="checkbox" name="cheese" id="0.99">Pesto</input>
</form>
</fieldset>
<br>
</div>
<div id="extraPizza"></div>
<center><button id="addPizza"> Add Pizza </button></center>
JavaScript:
var pizzaCost = 0.00;
var toppingCost = 0.00;
var sideCost = 0.00;
var drinkCost= 0.00;
var desertCost = 0.00;
var desertSizeCost = 0.00;
var drinkSizeCost = 0.00;
var sideSizeCost = 0.00;
$("#pizzaSize").prop('disabled', true);
$("#pizza").change(function() {
$("#pizzaSize").prop('disabled', false);
})
$( "#pizzaSize" ).change(function() {
$("input[type='checkbox']").prop('disabled', false);
var selectionPrice = $('option:selected', this).attr('id');
var selectionInt = parseFloat(selectionPrice, 10);
pizzaCost = selectionInt;
calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost, drinkSizeCost, sideSizeCost);
});
$('input[type=checkbox]').change(function(){
var checked = $(":checkbox:checked").length;
toppingCost = 0.99 * checked;
calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost, drinkSizeCost, sideSizeCost);
});
function calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost, drinkSizeCost, sideSizeCost) {
var total = pizzaCost + toppingCost + sideCost + drinkCost + desertCost + desertSizeCost + drinkSizeCost + sideSizeCost;
$("#totalPrice").text(total.toFixed(2));
}
$( "#addPizza" ).click(function() {
$("#pizzaForm").clone().appendTo("#extraPizza");
});
You should use jQuery on delegation when registering your events so that it will work for the dynamically created and injected form elements.
$(document).on("change","#pizzaSize", function() {
$("input[type='checkbox']").prop('disabled', false);
var selectionPrice = $('option:selected', this).attr('id');
var selectionInt = parseFloat(selectionPrice, 10);
pizzaCost = selectionInt;
calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost,
drinkSizeCost, sideSizeCost);
});
Also, I see a few issues with your code. First of you should not keep Id's on your form elements because you are making a clone. Also you should not bind your events by using jQuery selection using Id. No more than one element should have the same Id. Keep some css class on the element which you can use to register your click event code. Also do not keep the price in the id property values. What if 2 items has same price ? Same Id ? That is not correct. You should keep the price in HTML 5 data attribute.
You can use closest() method to get to the parent container and then use find to get a reference to the relative size dropdown.
$(document).on("change", ".pizza", function () {
var _this = $(this);
_this.closest("fieldset").find(".size").prop('disabled', false);
});
Here is a working sample with the changes i mentioned.
Related
I was following the sample code provided by another post (source: How to display multiple list of checkboxes dynamically on dropdown list), as it has the function that was exactly what I was trying to do for my webpage. However, I am having trouble retrieving the value of the checkbox that the user has selected, as the checkbox was dynamically created from the javascript. I tried debugging by inserting an alert function, and I was return with a "[Object NodeList]".
How can I retrieve the individual value(s) base on the checkbox that the user has selected?
For example, if user has selected "apple", I want to retrieve the value "apple". But if the user has selected "apple" and "Orange", I want to retrieve the value "apple" and "orange".
UPDATE
Thank you everyone for your comments and sample codes. I have edited the code below to retrieve the user-selected checkbox.
HTML:
<form id="product_form">
<div class="row" id="row1">
<div class="col-8">
<label><strong>FoodCategory:</strong></label>
<select id="model" name="model" onchange="populate(this.id, 'food')">
<option value="select">--Select Category--</option>
<option value="Fruit">Fruit</option>
<option value="vegetable">Vegetable</option>
</select>
</div>
<div class="col-8">
<label><strong>Outcome:</strong></label>
<div id="food"></div>
</div>
</div>
</form>
<button onclick="getResult()">Get Result</button>
Javascript:
var mappingData = {
"fruit": {
"destination": ["Apple", "Orage"]
},
"vegetable": {
"destination": ["Cabbage", "Carrot"]
}
};
function populate(model, food) {
var mod = document.getElementById('model');
var scenario = document.getElementById('food');
scenario.innerHTML = "";
mappingData[mod.value].destination.forEach(function(item) {
createCheckBox(item, scenario)
});
}
function createCheckBox(value, parent) {
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.name = "food";
checkbox.value = value;
var label = document.createElement('label')
label.htmlFor = value;
label.appendChild(document.createTextNode(value));
parent.appendChild(checkbox)
parent.appendChild(label)
parent.appendChild(document.createElement("br"))
}
function getResult() {
let checkboxes = document.querySelectorAll('input[name="food"]:checked');
let values = [];
checkboxes.forEach((checkbox) => {
values.push(checkbox.value)
});
alert(values);
}
Write this code when all javascript code done...
<script>
if (document.getElementById('youid').checked) {
alert(document.getElementById('youid').value);
}</script>
Assuming you have an attribute to select those checkboxes, this code would work:
function do_submit(form) {
var result = [];
var checkboxes = form.querySelectorAll(".my-checkbox").forEach(function(elem) {
if (elem.checked) {
result.push(elem.value);
}
});
form.querySelector("[name=chekboxes]").value = result.join(",");
// to cancel:
return false
// to submit:
// form.submit();
}
<form onsubmit="return do_submit(this); ">
<label><input type="checkbox" class="my-checkbox" value="apple"> apple </label><br>
<label><input type="checkbox" class="my-checkbox" value="banana"> banana </label><br>
<label><input type="checkbox" class="my-checkbox" value="cabbage"> cabbage </label><br>
<!-- should be hidden: -->
<input type="text" name="chekboxes" value="">
<input type="submit">
</form>
I have a specific section of a form(a select box and three checkboxes) that needs to be duplicated upon request. I have the clone of the div working as well as the incrementing of that specific div, but I am having issues incrementing the checboxes itself to make it unique.
Here is my HTML:
<div class="orgboxdupe" style="border: 1px solid lightgrey; padding-left:20px;padding-right:20px;padding-bottom:20px;margin-top:10px; width: 600px;">
<h3>Add user to an organization</h3>
<select id="orggroupadd" class="user_groupadd" name="user_orggroupadd[]">
<option value="none">Select an organization</option>
<option value="152">Test4</option>
<option value="156">test9</option>
</select>
<br><br>Organization Admin (can view uploaded files): <input type="checkbox" name="orgadmincheckbox2"><br><br>c3 Access: <input type="checkbox" name="c3checkbox2"> c4 Access: <input type="checkbox" name="c4checkbox2">
</div>
On button click it creates a new orgboxdupe box with an incrementing ID but for some reason it increments the number on the first div checkboxes and not on the subsequent cloned checkboxes:
Here is my JS
//Portalorgs - add Users
//Vars
let $addnewgroupbutton = jQuery( "#addnewgroup" );
let $mainelement = jQuery("#orguserbox");
let $dupebox = jQuery(".orgboxdupe");
let $selectboxid = jQuery("#orggroupadd");
let $checkboxes = jQuery("input[type='checkbox']");
let $cloneindex = 1;
//Duplicating add organizations box for users - po-addusers.php
$addnewgroupbutton.click(function() {
$cloneindex++;
$dupebox.clone().appendTo($mainelement).attr("id","user_orggroupadd" + $cloneindex).find(':checked').attr('checked', false);
$checkboxes.each(function(){
jQuery(this).attr("name",jQuery(this).attr("name") + $cloneindex);
});
console.log($cloneindex);
});
Thanks for any help that can be provided.
As noted by #Taplar $checkboxes references the original checkboxes. So they are the ones being updated each time there's a click.
You need to reference the checkboxes in the just copied clone; you can use chaining like so:
....
.end().find(':checkbox').attr('name', function() {
return this.name + $cloneindex;
});
//Portalorgs - add Users
//Vars
let $addnewgroupbutton = jQuery( "#addnewgroup" );
let $mainelement = jQuery("#orguserbox");
let $dupebox = jQuery(".orgboxdupe");
let $selectboxid = jQuery("#orggroupadd");
let $checkboxes = jQuery("input[type='checkbox']");
let $cloneindex = 1;
//Duplicating add organizations box for users - po-addusers.php
$addnewgroupbutton.click(function() {
$cloneindex++;
$dupebox.clone().appendTo($mainelement).attr("id","user_orggroupadd" + $cloneindex).find(':checked').attr('checked', false)
//operate on the close via method chaining
.end().find(':checkbox').attr('name', function() {
return this.name + $cloneindex;
});
/*$checkboxes.each(function(){
jQuery(this).attr("name",jQuery(this).attr("name") + $cloneindex);
});*/
//console.log($cloneindex);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="addnewgroup">Add New Group</button>
<div id="orguserbox">
<div class="orgboxdupe" style="border: 1px solid lightgrey; padding-left:20px;padding-right:20px;padding-bottom:20px;margin-top:10px; width: 600px;">
<h3>Add user to an organization</h3>
<select id="orggroupadd" class="user_groupadd" name="user_orggroupadd[]">
<option value="none">Select an organization</option>
<option value="152">Test4</option>
<option value="156">test9</option>
</select>
<br><br>Organization Admin (can view uploaded files): <input type="checkbox" name="orgadmincheckbox2"><br><br>c3 Access: <input type="checkbox" name="c3checkbox2">
</div>
</div>
I'm trying to make a form previewer.
The idea is to make a layer that shows user info printed on a div by default, but with the possibility of modifying their data in real time and show it in the box.
My code works, but I don't know how to simplify it.
Here's my code:
function preview() {
$('#previewName').html($('#Name').val());
$('#Name').keyup(function () {
$('#previewName').html($(this).val());
});
$('#previewDirection').html($('#Direction').val());
$('#Direction').keyup(function () {
$('#previewDirection').html($(this).val());
});
$('#previewPostal').html($('#Postal').val());
$('#Postal').keyup(function () {
$('#previewPostal').html($(this).val());
});
$('#previewCountry').html($('#Country option:selected').text());
$('#Country option:selected').change(function () {
$('#previewCountry').text($(this).text());
});
}
<form id="form">
<div>
<div>
<label>Name</label>
<input type="text" id="Name" name="Name" value="">
</div>
<div>
<label>Direction</label>
<input type="text" id="Direction" name="Direction">
</div>
<div>
<label>Postal</label>
<input type="text" id="Postal" name="Postal">
</div>
<div>
<label>Country</label>
<div>
<select name="Country" id="Country">
<option value="">x</option>
<option value="">y</option>
</select>
</div>
</div>
</div>
<div>
<div class="box">
<p class="strong" id="previewName"></p>
<p class="mb0" id="previewDirection"></p>
<p id="previewPostal"></p>
<p id="previewCountry"></p>
</div>
</div>
</form>
Any idea?
You can simplify this by querying the form input elements and using the id and value to update the preview.
// cache form selector
var form = $('#form');
// cache all form input elements
var inputs = form.find('input');
// cache all form select elements
var selects = form.find('select');
inputs.keyup(function(){
var id = this.id,
value = this.value;
$('#preview' + id).html(value);
});
selects.change(function(){
var id = this.id,
option = $(this).find('option:selected'),
value = option.val();
$('#preview' + id).html(value);
});
or a condensed version
$('#form input').keyup(function(){
var id = this.id,
value = this.value;
$('#preview' + id).html(value);
});
$('#form select').change(function(){
var id = this.id,
option = $(this).find('option:selected'),
value = option.val();
$('#preview' + id).html(value);
});
Demo
I'm currently trying to create a form that will extend on click using the method shown from this site. http://www.quirksmode.org/dom/domform.html
I have the Extending of the form more or less working fine, My issue is getting the Date field to correctly step up from the date that the user inputs in the first field.
Right now if I click on Add another Date, it adds a day to 1970-01-01 which i'm assuming is a default start date somewhere.
I'm not familiar enough with javascript to reference the generated date to the date that is initially selected by the User.
Here is a fiddle link of you want to see what I mean. https://jsfiddle.net/2nvz6kqj/9/
Note i'm pretty sure you can only get the date field to show up in Chrome correctly.
And here is my code.
<script type="text/javascript">
var counter = 0;
function moreFields() {
var date = document.getElementById("myDate").value;
counter++;
var newFields = document.getElementById("readroot").cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
var newField = newFields.childNodes;
for (var i=0;i<newField.length;i++) {
var theName = newField[i].name;
if (theName)
newField[i].name = theName + counter;
}
var insertHere = document.getElementById("writeroot");
insertHere.parentNode.insertBefore(newFields,insertHere);
document.getElementById("myDate").stepUp(1);
}
window.onload = moreFields;
</script>
<body>
<div id="readroot" style="display: none">
<input type="button" value="Remove Date"
onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />
<input type="date" id="myDate" value="">
<select name="rankingsel">
<option>School Day</option>
<option value="day1">Day 1</option>
<option value="day2">Day 2</option>
<option value="day3">Day 3</option>
<option value="day4">Day 4</option>
<option value="day5">Day 5</option>
<option value="closed">School Closed</option>
</select><br /><br />
</div>
<form method="post" action="/cgi-bin/show_params.cgi">
<span id="writeroot"></span>
<input type="button" onclick="moreFields()" value="Add Another Date" />
<input type="submit" value="Send form" />
</form>
</body>
Ultimately once i get this working correctly, I'll submit it to a DB with PHP.
Ok, I changed a few things, but this should work for you.
NOTE: In order to keep the code and markup close to what you had, I didn't "fix" some of the JavaScript and HTML that I consider to be bad practice.
I also took some liberties with the readroot element IDs and writeroot is now a DIV not a SPAN as you had it.
<html>
<head>
<script type="text/javascript">
var counter = 0;
var date = new Date();
// this function adds a day to the date variable
function addDay (dateObj) {
var ticks = dateObj.getTime();
var newTicks = ticks + (24 * 60 * 60 * 1000);
dateObj.setTime(newTicks);
}
function moreFields() {
//var dateVal = document.getElementById("myDate").value;
counter++;
// querySelector is nicer way to get your elements
var newFields = document.querySelector("#readroot").cloneNode(true);
newFields.id = newFields.id + counter;
newFields.style = null;
// nifty way to convert node list into an array
var fields = Array.prototype.slice.call(newFields.childNodes);
// now use forEach instead of old-style for loop
fields.forEach(function (f,i,nodes) {
var theName = f.name;
if (theName) {
f.id = theName + counter;
}
});
// convert "writeroot" to div and just append the newFields container
var form = document.querySelector('#writeroot');
form.appendChild(newFields);
// to set the date, you need to use an ISO-format date string
var dateFields = form.querySelectorAll('[name="myDate"]');
var len = dateFields.length;
var dateField = dateFields[len - 1];
if (dateField) {
var dateISO = date.toISOString().substr(0,10);
dateField.value = dateISO;
addDay(date);
}
}
window.onload = moreFields;
</script>
</head>
<body>
<div id="readroot" style="display: none">
<input type="button" value="Remove Date"
onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />
<input type="date" name="myDate">
<select name="rankingsel">
<option>School Day</option>
<option value="day1">Day 1</option>
<option value="day2">Day 2</option>
<option value="day3">Day 3</option>
<option value="day4">Day 4</option>
<option value="day5">Day 5</option>
<option value="closed">School Closed</option>
</select><br /><br />
</div>
<form method="post" action="/cgi-bin/show_params.cgi">
<div id="writeroot"></div>
<input type="button" onclick="moreFields()" value="Add Another Date" />
<input type="submit" value="Send form" />
</form>
</body>
</html>
I posted this earlier, but deleted the post due to formatting errors. I have a seen a few similar responses but they have been given negative scores so I thought I would post one up.
I have checkboxes that pull names from an SQL list using Ajax (which are echoed as checkboxes) and I want to when they are checked be posted in the textarea below when 'Add Selected Names' is clicked on
Here is my code, it functions for all and selects the figures ok (as the alerts test them). But doesn't pass the values to the textarea.
Jsfiddle:
http://jsfiddle.net/B4PvJ/1/
HTML:
<form name="promoForm4" method=post enctype=multipart/form-data action=cp007.php onSubmit="return validateForm();">
<ul class=mainForm id="mainForm_1">
<select name="nameoflist" onchange="changeFunc(this);">
<option value="" disabled="disabled" selected="selected">Select Recipients</option>
<option value="All Recipients">All Recipients</option>
<option value="Tech_List">Tech List</option>
</select>
<p>
<input type="checkbox" class="checkall">Check All
<br>
<br>
<div id="list_output" style="width:500px;height:500px;overflow:auto;"></div>
<p>Add Selected Names
<p>
<textarea readonly rows="10" cols="100" name="name_list_box"></textarea>
<p class="mainForm">
<input id="saveForm" class="mainForm" type="submit" value="Enter Track Details" />
</li>
</form>
JavaScript:
$(function () {
$(".add_names").click(function () {
alert("clicked");
var allVals = [];
$(".cb:checked").each(function () {
allVals.push($(this).val());
});
alert(allVals);
});
});
function changeFunc(obj) {
$('.checkall').prop('checked', false);
$("#list_output").empty();
var selectedValue = obj.options[obj.selectedIndex].value;
var url = "getnames.php?list_name=" + selectedValue;
$.get(url, function (data, status) {
var recep_list = data.split("^");
var r_len = recep_list.length;
for (var i = 0; i < r_len; i++) {
recep = recep_list[i].split("~");
$('#list_output').append('<input type="checkbox" class="cb" value="' + recep[1] + '" /> ' + recep[0] + '<br>');
}
});
}
$(".add_names").click(function () {
alert("clicked");
var allVals = [];
$(".cb").each(function () {
allVals.push($(this).val());
alert("somethingchecked");
});
var stringvals = allVals.join(" ");
$("#name_list_box").val($("#name_list_box").val() + stringvals);
alert(allVals);
});
$(".checkall").click(function () {
$('#list_output .cb').prop('checked', this.checked);
});
Many thanks
CP