I try to change value by default with a calcul : value by default * quantity / 100. In my script something does not work because nothing happened, I can't find what! (jQuery is very new for me...)
$(function () {
$("#calcul").click(function (e) {
e.preventDefault();
var valeur = parseFloat($("#valquantite").text() );
$("#nutrition > tbody > tr").each(function () {
var valeurOrigin = parseFloat($(this).find("td").eq(1).text().replace(",", "."));
var newValeur;
if ($.isNumeric(valeurOrigin) === true) {
newValeur = valeurOrigin*valeur/100;
newValeur = Math.ceil(newValeur*1000)/1000;
} else {
newValeur = $(this).find("td").eq(1).text();
}
$(this).find("td").eq(2).html(newValeur);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="overflow-x:scroll;;" name="formu">
<table class="table table-striped" id="nutrition" >
<thead>
<tr>
<th>Aliments</th>
<th id="qty">Poids</th>
<th class="generaux">Energie kJ</th>
<th class="generaux">Energie kcal</th>
</thead>
<tbody class="text-primary" id="">
<tr><td>Pain au lait, préemballé:</td><td id="valquantite"><strong>35gr</strong></td>
<td class="generaux" name="">1510</td>
<td class="generaux">358</td>
</tr>
<tr><td>Total</td>
<td><strong>50gr</strong></td>
</tr>
</tbody>
</table>
<input class="btn btn-primary" type="button" value="Calculer" id="calcul" />
What i try to do is that the first column after the name retrieves the quantities from a table (different for each row), then I retrieve the values by default columns energie_kj, energie_kcal, proteines, etc .. from a table (there are 60 Columns !! they are already calculated by default, I do not need to do any conversion). Some cells contain text (example: nc, traces, <) that I want to display as text. Then I have to calculate the total of each column (ignoring cells that contain text). That's my problem! I posted another question for the same problem with a code in js that works almost but not completely ... here: Javascript problems with NaN
Thanks in advance for your answers.
Hope this will help you. Replace your code with following : I've just parse your valeur variable and replaced > sign when calling .each function and applied Id=nutrition to table rather than tbody tag.
$(function () {
$("#calcul").click(function (e) {
e.preventDefault();
var valeur = parseInt($("#valquantite").text());
$("#nutrition tbody tr").each(function () {
var valeurOrigin = parseFloat($(this).find("td").eq(2).text().replace(",", "."));
var newValeur;
if ($.isNumeric(valeurOrigin) === true) {
newValeur = valeurOrigin*valeur/100;
newValeur = Math.ceil(newValeur*1000)/1000;
} else {
newValeur = $(this).find("td").eq(1).text();
}
$(this).find("td").eq(2).html(newValeur);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="overflow-x:scroll;;" name="formu">
<table class="table table-striped" id="nutrition">
<thead>
<tr>
<th>Aliments</th>
<th id="qty">Poids</th>
<th class="generaux">Energie kJ</th>
<th class="generaux">Energie kcal</th>
</thead>
<tbody class="text-primary">
<tr><td>Pain au lait, préemballé:</td><td id="valquantite"><strong>35gr</strong></td>
<td class="generaux" name="">1510</td>
<td class="generaux">358</td>
</tr>
<tr><td>Total</td>
<td><strong>50gr</strong></td>
</tr>
</tbody>
</table>
<input class="btn btn-primary" type="button" value="Calculer" id="calcul" />
The issue may be, we don't know exactly what it is you're trying to calculate or where the data comes from. The valQuantite to which you refer, does that change for each row? If so, why is it defined outside of the each function? If not, why does it refer to a value from the first row of the table?
Doing a little research, you seem to want to take the quantity column and use that along with the energie kJ column to calculate... something. I'd suggest using classes for the three columns, valquantite, energie-kj, and energie-kcal, which you can then use to manipulate the individual columns in a meaningful way. Using $(this).find("td").eq(2).text() is only as good as the coder -- what if the column layout changes? Instead, simply use $(this).find(".energie-kj").text() and you're good.
Now, having gotten to displaying the kj as you'd like (by taking the qty and multiplying it by the kj, then rounding), you can calculate the kCal by dividing that number by 4.1868 and rounding as you'd like.
But note, I've modified your code -- the quantity seems to change with each row, so I've moved valQuantite inside the each statement. Also, I can't stress enough, I've commented my code to the point of silliness. Doing so makes it far easier to track what each line of code is SUPPOSED to be doing, as well as what it's actually doing. And use your console, it is your debugging FRIEND! lol
$(function() {
// When the button is clicked, calculate the values.
$("#calcul").click(function(e) {
// First, make sure the button doesn't submit...
e.preventDefault();
// Each row is handled individually, so
$("#nutrition > tbody > tr").each(function() {
// First, get the qty for this row
var valeur = parseFloat($(this).find(".valquantite").text());
/****
* Here is a case. We have hard-wired to use the
* third column of the table for the original val,
* but we could also add a class for this col and
* reference that: $(this).find(".energie-kj");
****/
var valeurOrigin = parseFloat($(this).find("td").eq(2).text().replace(",", "."));
var energyKJ, energyKCal;
// If the energie kJ value is numeric, we do the first
if ($.isNumeric(valeurOrigin) === true) {
// calculate some value from the energie kJ and qty,
energyKJ = valeurOrigin * valeur / 100;
// 1 kCal = 4.1868 kJ, so do the conversion
energyKCal = (energyKJ/4.1868).toFixed(2);
energyKJ = energyKJ.toFixed(2);
} else {
// If the energie kJ value is NOT numeric, we simply
// set the displayed value to this
newValeur = $(this).find("td").eq(2).text();
}
$(this).find(".energie-kj").text(energyKJ);
$(this).find(".energie-kcal").text(energyKCal);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="overflow-x:scroll;;" name="formu">
<table class="table table-striped" id="nutrition">
<thead>
<tr>
<th>Aliments</th>
<th id="qty">Poids</th>
<th class="generaux">Energie kJ</th>
<th class="generaux">Energie kcal</th>
</thead>
<tbody class="text-primary" id="">
<tr>
<td>Pain au lait, préemballé:</td>
<td class="valquantite"><strong>35gr</strong></td>
<td class="generaux energie-kj" name="">1510</td>
<td class="generaux energie-kcal">358</td>
</tr>
<tr>
<td>Some other thing...:</td>
<td class="valquantite"><strong>45gr</strong></td>
<td class="generaux energie-kj" name="">1510</td>
<td class="generaux energie-kcal">358</td>
</tr> <tr>
<td>Total</td>
<td><strong>50gr</strong></td>
</tr>
</tbody>
</table>
<input class="btn btn-primary" type="button" value="Calculer" id="calcul" />
Related
I am creating table, and want to remove row by id using input field. (if input field matches with id then the row must be deleted)
can not figure it out.
Your help is much appreciated
`
<body onload="addRow()">
<table id="myTable" style="display:none">
<tr>
<th class="borderless">ID</th>
<th>Name</th>
<th>Username</th>
<th>Gender</th>
<th>Country</th>
</tr>
<tbody id="myTableBody">
</tbody>
</table>
<button type="button" id="buttonShow" onclick="showTable()">Show Table</button>
<button type="button" id="buttonAdd" onclick="addRow()" disabled>Add a new row</button>
<br>
<label>
<input class="input1" type="text" name="todoTags"/>
<button class="dellbtn" id="buttonDell"onclick="delRow()" disabled>Delete row</button>
</label>
`
`
function showTable(){
document.getElementById("myTable").style.display = "block";
document.getElementById("buttonAdd").disabled = false;
document.getElementById("buttonDell").disabled = false;
}
const btn = document.querySelector('.dellbtn')
const userTags = []
`
Here is my: JSfiddle
What you could do is changing the addRow() method so it adds a data-attribute to each row, in the <tr>. You can achieve this goal by adding this when creating the row :
row.setAttribute("row-id", tr.length - 1);
Then, when you want to delete it, you can simply search the
row that has the data-attribute that you just input. And it will look like this :
function delRow() {
const value = document.getElementById("valueToDelete").value;
document.querySelector('[row-id="' + value + '"]').remove();
}
I created a fork to your JSFiddle that you can check right here.
Hope it helps ! Good luck :)
Not exactly what you're asking, but this method might work better for you. It uses a delete button for each row so you can decide which one to delete. Then it uses a delegate listener to enable the delete buttons
const table = document.querySelector('#theTable tbody');
let c = 1
const addRow = () => {
table.innerHTML += `<tr><td>${c} data</td><td>${c} data</td><td><button class='delete'>delete</button></td></tr>`;
c++
}
// delegate listener for the delete button
table.addEventListener('click', e => {
if (e.target.classList.contains('delete')) {
e.target.closest('tr').remove();
}
})
<table id='theTable'>
<th>
<tr>
<td>Col 1</td>
<td>Col 2</td>
<td></td>
</tr>
</th>
<tbody>
</tbody>
</table>
<button onclick='addRow()'>Add Row</button>
I'm trying to do the following: I have a table populated with data from the DB. Apart from that, I have an input where you can write something and a button that will filter, only showing the lines that have that string. This is working now!
The thing is, the input should only allow you to filter by foo.name/foo.code (two propertys of my entity).
I'm adding the code I have in case anyone can guide me out, I've tried several things but this are my first experiences with JQuery while I have a strict story-delivery time. Thanks everyone!
<tbody>
<c:forEach var="foo" items="${foo}">
<tr id = "fooInformation" class="mtrow">
<th id="fooName" scope="row">${foo.name}</th>
<td id="fooCode" class="left-align-text">${foo.code}</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
</c:forEach>
</tbody>
$("#search").click(function () { -> button id
var value = $("#fooRegionSearch").val(); -> value of the input
var rows = $("#fooRegionTable").find("tr"); -> table id
rows.hide();
rows.filter(":contains('" + value + "')").show();
});
To start with, your HTML is invalid - there cannot be elemenets with duplicate IDs in HTML. Use classes instead of IDs.
Then, you need to identify which TRs pass the test. .filter can accept a callback, so pass it a function which, given a TR, selects its fooName and fooCode children which contain the value using the :contains jQuery selector:
$("#search").click(function() {
var value = $("#fooRegionSearch").val();
var rows = $("#fooRegionTable").find("tr");
rows.hide();
rows.filter(
(_, row) => $(row).find('.fooName, .fooCode').filter(`:contains('${value}')`).length
).show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="fooRegionTable">
<tr id="fooInformation" class="mtrow">
<th class="fooName" scope="row">name1</th>
<td class="fooCode" class="left-align-text">code1</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
<tr id="fooInformation" class="mtrow">
<th class="fooName" scope="row">name2</th>
<td class="fooCode" class="left-align-text">code2</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
</table>
<button id="search">click</button><input id="fooRegionSearch" />
I'm creating a view with two text inputs ('est' being calculated via JS based on 'idd') on top, and then a table with a #foreach loop to display all my data. Some fields will be calculated based on each other, but others must be calculated after the page is loaded, every time the 'est' and/or 'idd' inputs change.
Since razor is calculated server side and this JS client side, how can I set these type of calculated columns like the one in this example:
This should be the myResult var (or 'est' value) + #Content.V2
I though about pulling the #Content.EntityId to set some dynamic var names like:
<input type="text" id="#Content.EntityId-newfield"">
and pulling some <script>get the myResult again, add #Content.V2, set document.getElementById('#Content.EntityId-newfield').value</script> inside the loop but it doesn't work.
How can I achieve this?
Here's the full page:
<h1>My page</h1>
<br>
idd: <input type="text" id="idd" oninput="calculate()"> __ est: <input type="text" id="est">
<br><br>
<table border="1">
<thead>
<tr>
<th></th>
<th>Id</th>
<th>Title</th>
<th>V1</th>
<th>V2</th>
<th>V1 / V2</th>
<th>Field I know not how to calculate</th>
</tr>
</thead>
<tbody>
#foreach(var Content in AsDynamic(Data["Default"])){
<tr>
<td>#Edit.Toolbar(Content, actions: "edit,replace")</td>
<td>#Content.EntityId</td>
<td>#Content.Title</td>
<td>#Content.V1</td>
<td>#Content.V2</td>
<td>#Math.Round(#Content.V1 / #Content.V2, 2)</td>
<td>This should be the myResult var (or 'est' value) + #Content.V2</td>
</tr>
}
</tbody>
</table>
<script>
function calculate() {
var idade = document.getElementById('idd').value;
var myResult = (parseInt(idade) + 4) * 2;
document.getElementById('est').value = myResult;
}
</script>
Figure an array of functions would do the trick.
Before #foreach:
var arrayOfFunctions = [];
<input type="text" id="peso" oninput="callFunctions()">
inside #foreach:
arrayOfFunctions.push(function(setPeso) { document.getElementById('#Content.EntityId').value = setPeso * #Content.fieldToCalculate; });
after: #foreach:
function callFunctions() {
var myPeso = parseInt(document.getElementById('peso').value);
arrayOfFunctions.forEach(f => f(myPeso));
}
Lets say, I have simple datatable
<table datatable="" dt-options="dtOptions" dt-column-defs="dtColumnDefs" class="row-border hover">
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr ng-repeat"reservation in reservations">
<td>{{reservation.ID}}</td><td>{{reservation.name}}</td>
</tr>
</tbody>
</table>
When I put some string into search box datatable is being filtered. Now I want to iterate in Angular over filtered rows and read IDs to array. How to deal with it in Angular? I can use jquery but I do not want make a mess in code.
$scope.addressDTInstance = {};
var j = $scope.addressDTInstance.DataTable.rows();
<table id="addressSelectionTable" class="table table-condensed table-bordered" datatable="ng" dt-options="addressdtOptions" dt-column-defs="addressdtColumnDefs" dt-instance="addressDTInstance">
This is something to get you on your way. Need an instance of dtInstance which you don't have. So add dt-instance='dtInstance' in the html table tag.
Then initiate it at the top of your controller, $scope.dtInstance = {};.
Perform a click or some action in your javascript that you can set a break point on and then examine your $scope.dtInstance to see what all properties and methods you have. As you see in my snippet I'm accessing DataTable.Rows of my dtInstance. If you need better example or help let leave me a comment and I'll revise.
UPDATE
Here is a method I found that works. I am ofcourse using the DTOptionsbuilder. This will get called twice, first when it is created and second when i populated the array variable that is populating my table. I just check to see if rows exist and that the first one isn't 'No results'.
$scope.addressdtOptions = DTOptionsBuilder.newOptions()
.withOption('bFilter', false)
.withOption('bInfo', false)
.withOption('paging', false)
.withOption('processing', true)
.withOption('aaSorting', [1, 'asc'])
.withOption('language', { zeroRecords: 'No results' })
.withOption('initComplete', function () {
var rows = $("#addressSelectionTable > tbody > tr");
if (rows.length > 0 && rows[0].innerText !== "No results") {
var x = 3;
}
});
Here i am setting that variable that is ng-repeat for table. You may not be doing it my way, but you should be able to figure it out for your way.
$.when($OfficerService.GetAddressSelections($scope.officer.EntityID, $scope.officer.EntityTypeID, $scope.officer.MemberID)).then(function (result) {
$scope.addresses = result.data;
$scope.$applyAsync();
});
<table id="addressSelectionTable" class="table table-condensed table-bordered" datatable="ng" dt-options="addressdtOptions" dt-column-defs="addressdtColumnDefs" dt-instance="addressDTInstance">
<thead>
<tr>
<th></th>
<th>Type</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Country</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="a in addresses">
<td class="centerColumn">
<input type="button" class="btn btn-primary" value="Select" ng-click="selectAddress(a.AddressID,a.AddressLocationCode,$event)" />
</td>
<td>
<span ng-if="a.AddressLocationCode == 'E'">Office</span>
<span ng-if="a.AddressLocationCode == 'M'">Member</span>
</td>
<td>
{{a.AddressLine1}}
<span ng-if="a.AddressLine2 != null"><br /> {{a.AddressLine2}}</span>
</td>
<td>{{a.City}}</td>
<td>{{a.StateCode}}</td>
<td>{{a.Zip}}</td>
<td>{{a.CountryCode}}</td>
<td>{{a.AddressID}}</td>
</tr>
</tbody>
</table>
For me it works: $scope.dtInstance.DataTable.rows( { search: 'applied' } ).data()
JSFiddle: https://jsfiddle.net/dxhen3ve/4/
Hey guys,
I've been trying to figure out the issue here for some time.
Essentially, I have a table with rows. You can add new rows (works fine). However, on the deletion of rows, I would like to re-number all of the rows below it (including all of their input names/ids within).
This works fine as I have it on the first time you click "remove" for any row.. say, if you have rows 0-4 and delete row 1, you will now have rows 0-3 and they will be numbered correctly--however, after that if you click remove again on another row, the numbers do not update
The indexes are getting mixed up some how and it almost seems like it's not recognizing that I've removed an element from the DOM.. when I console.log the indexes everything looks fine.
As an example:
- Add 5 rows (0-4)
- Remove row #1 (the rows below get updated as they should).
- Remove the new row #1, and you will see that row #2 takes its place instead of changing to row #1.
- In the function 'renumber_budget_rows', the if statement seems to get skipped for that row #2, even though I feel like it should meet the conditions (and is present if I console.log(item)
What am I missing? https://jsfiddle.net/dxhen3ve/4/
** Update: Just wanted to update that I have a true resolution that works, which is great! However, I am more interested in knowing WHY my solution is failing. At the moment, the best I have, from the correct answer, was that my indexes were misaligned. I'm going to take a new look at them.
HTML
<script type="text/template" id="budget_row-template">
<tr id="budget_row-{{index}}" class="budget-row" data-budget-index="{{index}}">
<td class="budget-line">{{index}}</td>
<td><input type="text" name="budget_description-{{index}}" id="budget_description-{{index}}" class="budget-description" /></td>
<td><input type="text" name="budget_amount-{{index}}" id="budget_amount-{{index}}" class="budget-amount" /></td>
<td>
<select name="budget_costcode-{{index}}" id="budget_costcode-{{index}}" class="budget-costcode">
<option>-- Select Cost Code</option>
</select>
</td>
<td><i class="fa fa-share"></i></td>
<td>remove</td>
</tr>
</script>
<div class="table-scroll-container">
<table class="table table-striped table-bordered table-hover tablesorter" id="budget-display">
<thead>
<tr>
<th>Line #</th>
<th>Description</th>
<th>Amount</th>
<th>Cost Code</th>
<th data-sorter="false"></th>
<th data-sorter="false"></th>
</tr>
</thead>
<tbody id="test">
<tr id="budget_row-0" class="budget-row" data-budget-index="0">
<td class="budget-line">0</td>
<td><input type="text" name="budget_description-0" id="budget_description-0" class="budget-description" /></td>
<td><input type="text" name="budget_amount-0" id="budget_amount-0" class="budget-amount" /></td>
<td>
<select name="budget_costcode-0" id="budget_costcode-0" class="budget-costcode">
<option>-- Select Cost Code</option>
</select>
</td>
<td><i class="fa fa-share"></i></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="text-align-center">
<i class="icon icon-plus icon-white"></i> Add Line Item<br />
</div>
JS
function renumber_budget_rows(removed) {
$('#budget-display tbody .budget-row').each(function(indite, item) {
var ti = $(item).data('budget-index');
if( ti > removed ) {
ti--;
//console.log(item);
$(item).attr('id', 'budget_row-'+ti);
$(item).attr('data-budget-index', ti);
$(item).find('.budget-line').html(ti);
$(item).find('.budget-description').attr({ 'name': 'budget-description-'+ti, 'id': 'budget-description-'+ti });
$(item).find('.budget-amount').attr({ 'name': 'budget-amount-'+ti, 'id': 'budget-amount-'+ti });
$(item).find('.budget-costcode').attr({ 'name': 'budget-costcode-'+ti, 'id': 'budget-costcode-'+ti });
$(item).find('.add-budget-child').attr({ 'id': 'budget_row-addparent-'+ti, 'data-budget-index': ti });
$(item).find('.trash-budget-row').attr({ 'id': 'budget_row-'+ti+'-trash' });
$(item).find('.trash-budget-row').attr('data-budget-index', ti);
}
});
}
var budget_index = 0;
$('.add-budget-row').click(function(e) {
budget_index++;
e.preventDefault();
var budget_html = $('#budget_row-template').html();
budget_html = budget_html.replace(/{{index}}/g, budget_index);
$('#budget-display tbody').append(budget_html);
});
$('#budget-display').on('click', '.trash-budget-row', function(e) {
var removed = $(this).data('budget-index');
$(this).closest('tr').remove();
console.log(removed);
renumber_budget_rows(removed);
budget_index--;
});
While you are deleting the row, after a row deletion, you can iterate through every tr using .each() function and change the attributes based on the index i value.
$('#budget-display').on('click', '.trash-budget-row', function(e) {
var removed = $(this).data('budget-index');
$(this).closest('tr').remove();
$('tbody tr').each(function(i){
$(this).find('td').eq(0).text(i);
$(this).attr("data-budget-index",i);
$(this).attr("id","budget-row-" + i);
});
budget_index--;
});
Working example : https://jsfiddle.net/DinoMyte/dxhen3ve/5/