I am trying to create a dynamic aggregation based on fields. The only difference is that it's not a table but a div block.
What I am trying to accomplish
On button click add field, the content from the template is cloned ( it's like a table row ), this part is fully working.
The code is supposed to count the values, for each row add some fields. I used keyup function to keep it updated all time.
Why is it not working?
Well I was not able to get it working like such .each of i_row or template contains fields p_cnetto[] p_pvat[] p_ilosc[] ( quantitiy )
Because I can't read row wise - I tried many things but apparently did something bad it only counts curr_net value and it's still not the way it should be.
Decimal values should be acceptable : example 2222.00
How it should work?
Add a row
Summing row part [ not really need to display row aggregation ]:
curr_netto = get this row p_cnetto[] value multiply by p_ilosc[]
curr_brutto = get this row (p_cnetto[] * p_pvat[]) / 100 * p_ilosc[]
At the end it should calculate a grand total of all rows for as total_netto,total_brutto - could be in console.log
Thanks for any tips.
JsFiddle Example
<!-- statistic block --->
<div id="curr_netto"></div>
<div id="curr_brutto"></div>
<button class="btn btn-primary btn-add-panel mt-5" type="button"> <i class="glyphicon glyphicon-plus"></i> Add field</button>
<div class="row">
<div class="col-sm-12" id="extra_group">
<!-- s -->
<div class="widget widget2 card template mb-2 bg-light-blue-50" style="display: none;">
<div class="col-lg-5">
<div class="row i_row">
<div class="form-group col-md-2">
<div class="form-group pmd-textfield pmd-textfield-floating-label">
<label>Name</label>
<input type="text" name="p_nazwa[]" class="form-control"></input>
</div>
</div>
<div class="form-group col-md-2">
<div class="form-group pmd-textfield pmd-textfield-floating-label">
<label>Qty</label>
<input type="text" name="p_ilosc[]" class="form-control p_ilosc"></input>
</div>
</div>
<div class="form-group col-md-2">
<div class="form-group pmd-textfield pmd-textfield-floating-label">
<label>Unit</label>
<select class="form-control" name="p_unit[]">
<option value="Kg">Kilogram</option>
</select>
</div>
</div>
<div class="form-group col-md-2">
<div class="form-group pmd-textfield pmd-textfield-floating-label">
<label>Net</label>
<input type="text" name="p_cnetto[]" class="form-control p_cnetto"></input>
</div>
</div>
<div class="form-group col-md-2">
<div class="form-group pmd-textfield pmd-textfield-floating-label">
<label>VAT</label>
<input type="text" name="p_pvat[]" class="form-control p_pvat"></input>
</div>
</div>
<div class="form-group col-md-2">
<div class="subtot"></div>
</div>
<div class="form-group col-md-2">
<button class="btn btn-danger btn-add-panel rh mt-5 ml-3"> <i class="glyphicon glyphicon-minus"></i> Del</button>
</div>
</div>
</div>
</div>
<!-- s -->
</div>
</div>
below code will loop through individual block and get the values.
$(document).keyup(function() {
// desired calculation : for curr_netto is [name='p_cnetto[]']" * [name="p_pvat[]"]
// curr_brutto = ([name='p_cnetto[]']" * [name="p_pvat[]"]) / 100 * name="p_ilosc[]"
var cnetto = 0;
var pnetto = 0;
jQuery('#extra_group .template').each(function(){
var resetVar = (Number(jQuery(this).find('.p_cnetto').val()) * Number(jQuery(this).find('.p_pvat').val()));
cnetto = cnetto + resetVar;
pnetto = pnetto + ((resetVar / 100) * Number(jQuery(this).find('.p_cnetto').val()));
});
$("#curr_netto").html("Netto : " + cnetto + " -- " + pnetto)
console.log(cnetto);
});
#Kavvson Empcraft also updated your jsfiddle - you can check the output
Based on the answer, this works for me
$(document).bind("keyup change", function (e) {
var pbrutto = 0;
var wartosc_vat = 0;
var cnetto = 0;
jQuery('#extra_group .template').each(function () {
var qty_field_current = (Number(jQuery(this).find('.p_ilosc').val()));
var vatfield_current = (Number(jQuery(this).find('.p_pvat').val()));
var nettofield_current = (Number(jQuery(this).find('.p_cnetto').val().replace("Zł ", "").replace(",", "")));
cnetto = cnetto + (nettofield_current * qty_field_current);
wartosc_vat = wartosc_vat + (nettofield_current * vatfield_current) / 100;
wartosc_vat = wartosc_vat * qty_field_current;
});
pbrutto = cnetto + wartosc_vat;
$("#curr_brutto").html("Brutto : " + pbrutto + " zł");
$("#curr_netto").html("Netto : " + cnetto + " zł");
$("#curr_vat").html("Vat : " + wartosc_vat + " zł");
});
Related
I have just finished creating a localStorage booking website for a university project, as an additional feature, I was thinking of including a hidden span which would be shown when the users appointment is starting soon. The examples I have looked at for countdowns etc look really complex and my knowledge is limited so I don't know what parts I would need to construct such a thing..
I am just really looking for some advice on how I would go about it. I have a datepicker and a select box with times (populated from an array) and I want to use the data that is stored from the appointment booking to show a span that says 'Your appointment is about to begin', for example.
Here is my function that displays my bookings in the browser (from localStorage)
function showBooking() {
var bookingResult = document.getElementById("result");
var ul = document.createElement("ul");
bookingResult.innerHTML = `<h3 class="text-center">Your Bookings</h3>`;
for (let i = 0; i < bookings.length; i++) {
bookingResult.innerHTML += `
<div class="card resultcard card-body bg-light m-4">
<div class="row">
<p>Owner name:${bookings[i].fname + " " + bookings[i].lname}</p>
<p>Dog Name: ${bookings[i].dogname + " " + bookings[i].lname} (${bookings[i].breed})</p>
<p>Collecting from ${bookings[i].address + ", " + bookings[i].postcode + " at " + bookings[i].stime + " for a " + bookings[i].duration} dog walk.</p>
<p>Additional Info: ${bookings[i].info}</p>
</div>
<span id="apptNotify" class="label label-success" style="display: none;">Your appointment is about to begin.</span>
<div class="row">
<div class="d-grid gap-2 d-md-block">
<button onclick="editBooking(${i})" class="col-md-4 btn btn-outline-danger ">Edit</button>
<button onclick="deleteBooking(${i})" class="col-md-4 btn btn-danger text-light ">Delete</button>
</div>
</div>
</div>`;
}
}
My array of times:
function showTimes() {
let startTime = document.getElementById('stime');
let times = ['9:00', '9:30', '10:00', '10:30', '11:00', '11:30','12:00','12:30', '13:00', '13:30', '14:00', '14:30', '15:00'];
let options = times.map(time => `<option value="${time}">${time}</option>`).join('');
startTime.innerHTML += options;
}
And my form elements which contribute to these functions (not the entire form):
<form id="regForm" name="regForm" action="" class="col-md-6">
<div class="row">
<div class="col-md-6">
<input type="date" id="sdate" class="input datepicker form-control required" name="sdate" onchange="checkStartDate()" required>
<span id="dError" style="display: none;">Start date must be in the future.</span>
</div>
<div class="col-md-6">
<select name="stime" class="select form-control required" id="stime" required>
<option value="" selected disabled hidden>Choose a time</option>
</select>
</div>
</div>
</form>
<div id="result" class="result row"></div>
I've got a dropdown box which is populated with ajax according to what option i choose from another dropdown. I need to duplicate the dropdown box keeping the same options loaded via ajax, this is what i've done o far. Many thanks for your help
This is the code to get tha value from the first dropbox and then use it for ajax
$('#flatGroup').on('change',function(){
var countryID = $(this).val();
console.log(countryID);
if(countryID){
$.ajax({
type:'POST',
url:'../controllers/ctrl_admin_group_table_app/ctrl_admin_get_building_table.php',
data: {
group_id: countryID
},
success:function(html){
$('#flatTable-1').html(html);
$(".bs-select").selectpicker('refresh');
}
});
}
});
This is the code i'm using to close the second dropbox that receive the option from ajax
// start repeating form tabelle
//Start repeating form group add limit
var maxGroup1 = 5;
//add more fields group
var fieldGroup1= $(".fieldGroup1").clone();
$(".addMore1").click(function() {
var fgc1 = $('body').find('.fieldGroup1').length;
if (fgc1 < maxGroup1) {
var fieldHTML1 = '<div class="form-group fieldGroup1">' + fieldGroup1.html() + '<div class="col-md-1"><label class="control-label"> </label><i class="fa fa-close"></i></div></div>';
fieldHTML1 = fieldHTML1.replace('flatTable-1', 'flatTable-' + (fgc1 + 1));
fieldHTML1 = fieldHTML1.replace('flatMillesimi-1', 'flatMillesimi-' + (fgc1 + 1));
$('body').find('.fieldGroup1:last').after(fieldHTML1);
$('.bs-select').selectpicker({
iconBase: 'fa',
tickIcon: 'fa-check'
});
} else {
swal("Operazione Annullata", "Hai raggiunto il massimo numero di proprietari registrabili", "error");
}
});
//remove fields group
$("body").on("click", ".remove", function() {
$(this).parents(".fieldGroup1").remove();
});
// end repeating form
This is the HTML code
<div class="row">
<div class="col-md-9">
<div class="portlet-body form">
<div class="col-md-9">
<div class="mt-repeater">
<div data-repeater-list="group-b">
<div data-repeater-item class="row">
<div class="form-group fieldGroup1">
<div class="col-md-4">
<div class="form-group">
<label class="control-label">Tabella</label>
<select class="form-control bs-select" id="flatTable-1" name="flatTable[]" title="Seleziona tabella millesimale"></select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="control-label">
<i class="fa fa-info-circle red tooltips" data-placement="top" data-original-title="Quota del titolare dell'immobile" ></i>Millessimi<span class="required"> * </span>
</label>
<input type="text" id="flatMillesimi-1" name="flatMillesimi[]" class="form-control" placeholder="Millessimi dell'immobile" >
</div>
</div>
</div> <!-- Fine field group -->
</div>
</div>
<!-- <hr> -->
<a href="javascript:;" data-repeater-create class="btn btn-info mt-repeater-add addMore1">
<i class="fa fa-plus"></i> Aggiungi tabella</a>
<br>
<br>
</div>
</div>
</div>
</div>
</div>
Have a form to create a contract, where that contract can have one or more users associated.
The area to input the users info, starts with only one field of one user, and one button to add more fields if needed.
<div id="utilizadores" class="row">
<div id="utilizador1" class="container-fluid">
<div class="row">
<div class="col-lg-5">
<input type="text" class="form-control" id="nomeUtilizador1" placeholder="Nome Utilizador">
</div>
<div class="col-lg-6">
<input type="text" class="form-control" id="funcaoUtilizador1" placeholder="Função">
</div>
</div>
</div>
</div>
This is the starting div
Clicking on Add User button it adds a new div under the "utilizador1"
<div id="utilizadores" class="row">
<div id="utilizador1" class="container-fluid">
<div class="row">
<div class="col-lg-5">
<input type="text" class="form-control" id="nomeUtilizador1" placeholder="Nome Utilizador">
</div>
<div class="col-lg-6">
<input type="text" class="form-control" id="funcaoUtilizador1" placeholder="Função">
</div>
</div>
</div>
<div id="utilizador2" class="container-fluid">
<div class="row">
<div class="col-lg-5">
<input type="text" class="form-control" id="nomeUtilizador2" placeholder="Nome Utilizador">
</div>
<div class="col-lg-6">
<input type="text" class="form-control" id="funcaoUtilizador2" placeholder="Função">
</div>
</div>
</div>
My question is, how can I get the number of users created, and insert them into a list using Javascript. The list will be a attribute of a Object (Contract).
What i have til now:
function test_saveItem() {
var contract = new Object();
contract.Dono = <% =uID %>;
contract.BoostMes = $("#boostMes").val();
contract.BoostAno = $("#boostAno").val();
var ListaUtilizadores = [];
var divs = document.getElementsByName("utilizador");
for (var i = 0; i < divs.length; i++){
var user = new Object();
user.Nome = $('#nomeUtilizador' + i).val();
ListaUtilizadores.push(user);
}
var test = JSON.stringify({ "contract": contract });
}
Any help appreciated
Edit: Got to a solution thanks to Shilly
List = [];
Array.prototype.slice.call(document.querySelectorAll('.user')).forEach(function (node, index) {
List.push({
"name" : document.getElementById('nameUser' + (index + 1)).value,
"job" : document.getElementById('jobUser' + (index + 1)).value
});
});
Something like this? But adding it into the addUser function as Super Hirnet says, will be more performant.
var divs = document.querySelector('#utilizadores').childNodes,
users = [];
Array.slice.call(divs).forEach(function (node, index) {
users.push({
"name" : divs[index].getElementById('nomeUtilizador' + (index + 1)).value
});
});
You can have an empty array and on every click of addUser put a new object into the array. The object can have information related to the added user.
I have the following HTML and JS Code and the problem, that I'm not quite sure how to get the values from the input-boxes with the classes bti, bi, bp and bb when I click on the savebtn Button. I really hope someone can help me and give me a hint! best regards
$(document).ready(function() {
$('.savebtn').click(function() {
//how to i get the values?
});
});
<div class="modal-body">
<?php
for ($i=0; $i<count($barkeeperarr); $i++) {
?>
<div class="panel panel-primary" value="<?php echo $barkeeperarr[$i]->getID(); ?>" >
<div class="panel-heading clickablePanel">
<div class="panel-title"><?php echo $barkeeperarr[$i]->getFirstname().' '.$barkeeperarr[$i]->getLastname(); ?></div>
</div>
<div class="panel-body" style="display: none">
<div class="container-fluid">
<div class="row" value="row" style="margin-bottom: 3px">
<div class="col-xs-5">
<input type="text" class="form-control bti" placeholder="Gesamtumsatz">
</div>
<div class="col-xs-5">
<input type="text" class="form-control bi" placeholder="Einladung">
</div>
<div class="col-xs-2">
<button type="button" class="btn btn-primary btn-sm savebtn">Hinzufügen</button>
</div>
</div>
<div class="row" style="margin-bottom: 3px">
<div class="col-xs-5">
<input type="text" class="form-control bp" placeholder="Personal">
</div>
<div class="col-xs-5">
<input type="text" class="form-control bb" placeholder="Bruch">
</div>
</div>
</div>
</div>
</div>
<?php } ?>
</div>
It will something like this,
$('.savebtn').click(function() {
$.each($('input:text.form-control'), function(){
if ($(this).prop('class') === 'bti'){
alert('form-control bti value = ' + $(this).val()));
} else if ($(this).prop('class') === 'bp'){
alert('form-control bp value = ' + $(this).val()));
} else if ($(this).prop('class') === 'bb'){
alert('form-control bb value = ' + $(this).val()));
} else if ($(this).prop('class') === 'bi'){
alert('form-control bi value = ' + $(this).val()));
});
});
You could store the values in an array and then process that array to add the values to your database.
For instance, let's create an array called values :
var values = [];
Then add an object to that array with the values of the respective classes bti, bi, bp and bb like :
jQuery(document).ready(function ($) {
var formControl = $(".form-control");
$('.savebtn').on("click", function () {
//how to i get the values?
for (var i = 0; i < formControl.length; i++) {
values[i] = {
name: formControl[i].className.split(" ")[1],
val: formControl[i].value
}
}
});
}); // ready
Notice we targeted the selector .form-control, which is a common class to all input fields.
I have a list of and fields where users enter the name of an item and the quantity. The PHP function
generateMaterialsTable();
is responsible for generating one text field and one number field if there are no existing records in the database. If there are multiples, the function shows all items and their corresponding quantities. Here is the PHP code:
function generateMaterialsTable($month_id, $table, $item, $addOrEdit){
global $mysqli;
$item_singular = substr($item, 0, strlen($item)-1);
$item_singular_title = $item_singular.'_title';
if($addOrEdit == 'Edit'){
$materials_query = "SELECT * FROM archivestats.".$table."_".$item." WHERE month_id = '$month_id'";
$materials_result = $mysqli->query($materials_query);
if($materials_result->num_rows > 0){
$counter = 1;
while($materials_match = $materials_result->fetch_assoc()){
$output .= '
<div class="form-group '.$item_singular.'-row row">
<div class="col-sm-8">
<input type="text" name="'.$item_singular.'[]" class="form-control item-field" value="'.htmlentities($materials_match[$item_singular_title]).'">
</div>
<div class="col-sm-4">
<input type="number" name="'.$item_singular.'qty[]" class="form-control align-right '.$item_singular.'qty" value="'.$materials_match['quantity'].'">
</div>
</div>
';
$counter++;
}
} else {
$output .= '
<div class="form-group '.$item_singular.'-row row">
<div class="col-sm-8">
<input type="text" name="'.$item_singular.'[]" class="form-control item-field" value="">
</div>
<div class="col-sm-4">
<input type="number" name="'.$item_singular.'qty[]" class="form-control align-right '.$item_singular.'qty" value="">
</div>
</div>
';
}
}
return $output;
}
The user also has the option to add a new text and quantity field. This is done via the following JQuery:
//WHEN USER CLICKS '+Add Another Field'
$('.new-field').click(function(){
var newFieldId = $(this).attr('id'); //find id of the '+Add Another Field' paragraph
var newField = newFieldId.substr(0, newFieldId.lastIndexOf('-')); //find the name of the field before the last - (eg. 'book' from 'book-new')
var fields = $(this).parents().siblings().closest('.'+newField+'-row').find('input[type="text"]');
var count = 0;
$(fields).each(function(){
//we only need to get information for the last text box in the bunch
if(count == fields.length-1){
var last_field = $(this).attr('name'); //the name attribute of the last text box
var field_name = last_field.substr(0, last_field.indexOf('[')); //find the name of the field before a _ (eg. 'book' from 'book_1')
var regEx = /\d+/; //find the number of the field contained in the name (eg. '1' from 'book_1')
var field_number = parseInt(last_field.match(regEx));
$(this).parent().parent().after('<div class="form-group '+ field_name +'-row row"> <div class="col-sm-8"><input type="text" name="'+ field_name +'[]" class="form-control item-field"></div><div class="col-sm-4 add-field"><input type="number" name="'+ field_name +'qty[]" class="form-control align-right ' + field_name + 'qty"></div></div>');
}
count++; //iterate our counter
});
}); //end .new-feild.click()
For whatever reason, when I go to submit the form, the array as defined in
name="'.$item_singular.'[]"
only works properly with one group of text fields - that is, it properly records all array items. For example, let's say I have the following:
<div class="form-group book-row row">
<div class="col-sm-8">
<input type="text" name="book[]" class="form-control item-field">
</div>
<div class="col-sm-4">
<input type="number" name="bookqty[]" class="form-control align-right bookqty">
</div>
</div>
</div>
<div class="form-group book-row row">
<div class="col-sm-8">
<input type="text" name="book[]" class="form-control item-field">
</div>
<div class="col-sm-4">
<input type="number" name="bookqty[]" class="form-control align-right bookqty">
</div>
</div>
For this, I will input values of EXAMPLE 1 / 4 and EXAMPLE 2 / 15. When I submit and do:
print_r($_POST['book'])
I get the proper value of
Array([0] => "Example 1", [1] => "Example 2")
But then in another section of that EXACT SAME FORM I do this:
<div class="form-group book-row row">
<div class="col-sm-8">
<input type="text" name="digbook[]" class="form-control item-field">
</div>
<div class="col-sm-4">
<input type="number" name="digbookqty[]" class="form-control align-right digbookqty">
</div>
</div>
</div>
<div class="form-group book-row row">
<div class="col-sm-8">
<input type="text" name="digbook[]" class="form-control item-field">
</div>
<div class="col-sm-4">
<input type="number" name="digbookqty[]" class="form-control align-right digbookqty">
</div>
</div>
</div>
For this, I will input values of EXAMPLE 3 / 1 and EXAMPLE 4 / 20. Now I'll get ONLY the first item in the array:
Array([0] => "Example 3")
This makes absolutely no sense and it is driving me crazy. It is the exact same function spitting out the exact same code with two completely different results. Unreal...