I have a table where the sum of the rows are updated with javascript when a user changes the quantity within a popup modal. I want to be able to update the grand total of all my rows every time the total of a row change.
I have tried to add an event listener onchange and oninput on the total of each of my row but it doesn't work. I have tried to find a workaround by adding an event listener on the quantity the user is changing but to no effect. I have tried the code in the console and it is working but the event-listener doesn't seem to trigger.
document.getElementById("work_quantity_<%= #work_detail.id %>").addEventListener("change", grandTotal)
var work_detail_quantity = document.getElementById("work_quantity_<%= #work_detail.id %>").value;
var work_detail_block = document.getElementById("work-<%= #work_detail.id %>");
var quant = work_detail_block.getElementsByTagName('td')[1];
quant.innerHTML = work_detail_quantity+" <%= #work_detail.work_resource.unit_measure%>";
function grandTotal() {
var sub_total = document.getElementById("subtotal_lign").innerHTML
var table = document.getElementById("invoice_summary"), sumVal = 0;
for(var i = 1; i < table.rows.length; i++)
{
sumVal = sumVal+ parseFloat(table.rows[i].cells[4].innerText.replace(/[^0-9-.]/g, ''));
}
document.getElementById("subtotal_lign").innerHTML = sumVal.toFixed(2) + ' €' ;
};
If someone could give me a hint it would be more than appreciated, I am a rookie in javascript. Thank you
It's not a good idea to parse the DOM like that to get the values.
Solution 1
You get the object that contains the values of your table form Ruby. Something like that:
var works = <%= #works.to_json %>;
Then, when a user updates his order, you first update the object and then you update the table based on the updated object.
Solution 2
When a user update his order, you send the update to your server and you update the table in the server side.
Solution 3 (Not recommended)
If you still want to do it by parsing the DOM, have a look at MutationObserver to listen the changes in your table.
I confess, I haven't tried this per say; but I did try in jQuery a similar thing, mainly because your example lacks the detail of the table;
but you need to trigger the event when a change occurs, I assume here your not using standard input fields, so are you using like <td contenteditable></td>, they can't be monitored for change, but keyup and blur can be monitored, so if you want to trigger the calc on blur, when that event occurs, trigger your table sum event...
I'd actually use jQuery for this but here goes ...
document.getElementById("work_quantity_<%= #work_detail.id %>").addEventListener("change", grandTotal)
...
function grandTotal() {
var sub_total = document.getElementById("subtotal_lign").innerHTML
var table = document.getElementById("invoice_summary"), sumVal = 0;
for(var i = 1; i < table.rows.length; i++) {
sumVal = sumVal+ parseFloat(table.rows[i].cells[4].innerText.replace(/[^0-9-.]/g, ''));
}
document.getElementById("subtotal_lign").innerHTML = sumVal.toFixed(2) + ' €' ;
};
// something like this
(function() {
// i assume it's cell[4] that is being edited, and it's like contenteditable
var table = document.getElementById("invoice_summary");
for(var i = 1; i < table.rows.length; i++) {
/* assign listener on the cell,
when it blurs, trigger the update,
you could also monitor keyup
*/
table.rows[i].cells[4].addEventListener("blur", function(e) {
document.getElementById("work_quantity_<%= #work_detail.id %>").dispatchEvent("change", grandTotal);
});
}
})();
Updated
I thought that what I wrote below was working but actually the grand total is always one computation behind as it is doing the sum of the rows before the total of the modified row has been updated after a change of quantity.
Ok it is working with a workaround, but I still believe MutationObservers could be a good way to resolve this kind of problem in the future
Good tutorial: for MutationObservers
To make my event listener work I add to define it before the change in the quantity is made by the user (stupid isn't it)
1) Add the event listener to the object you are tracking
document.getElementById("work_quantity_<%= #work_detail.id %>").addEventListener("input", grandTotal)
2) This is where my object is changed with javascript
var work_detail_block = document.getElementById("work-<%= #work_detail.id %>");
var quant = work_detail_block.getElementsByTagName('td')[1];
quant.innerHTML = work_detail_quantity+" <%= #work_detail.work_resource.unit_measure%>";
3) I define the function which is called in the step 1
function grandTotal() {
var sub_total = document.getElementById("subtotal_lign").innerHTML
var table = document.getElementById("invoice_summary"), sumVal = 0;
for(var i = 1; i < table.rows.length; i++)
{
sumVal = sumVal+ parseFloat(table.rows[i].cells[4].innerText.replace(/[^0-9-.]/g, ''));
}
document.getElementById("subtotal_lign").innerHTML = sumVal.toFixed(2) + ' €' ;
};
I have looked all over but can't find a good answer.
So what I'm wanting to do is highlight multiple rows on a table
Then if you click on a highlighted row it gets un-highlighted.
All of this works for me. The problem I'm having is when I un-highlight a row for some reason it won't highlight again.
function highlight_row() {
var table = document.getElementById("display-table");
var cells = table.getElementsByTagName('td');
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
cell.onclick = function () {
var rowId = this.parentNode.rowIndex;
var rowSelected = table.getElementsByTagName('tr')[rowId];
rowSelected.className += "selected";
$(cell).toggleClass('selected');
}
}
}
I have changed out $(cell) with $(this) and that works but only re highlighting the cell I click on and not the whole row.
I'm at a lose here.
Thanks
If you want to highlight the whole row, you need to get parent tr
cell.onclick = function () {
$(this).parent('tr').toggleClass('selected');
}
I am having a groupable kendo grid.
Please help me out with setting some custom text whenever the grid is empty.
If grid is not groupable i could acheive it using databound funtion.
Here's a version I adapted from KendoGridBinderEx as I wanted a function on databound that could handle not only empty but error cases too. I've modified it back to mostly suit what you're struggling with. When my datasource has errors I'll read them out of the event that I pass into the function itself, thus why you see 'e' referenced as a parameter but not used.
function DisplayNoResultsFound(evt) {
var grid = evt.sender.element;
//Only do this if you can properly find the grid
if (grid.data("kendoGrid") == undefined) {
return;
}
// Get the number of Columns in the grid
var dataSource = grid.data("kendoGrid").dataSource;
var colCount = grid.find('.k-grid-header colgroup > col').length;
//Check for an empty datasource
if (dataSource._view.length == 0) {
//Clear the grid
//you may or may not need this depending on how your datasource returns
grid.find('.k-grid-content tbody').empty();
//Add the no result row
grid.find('.k-grid-content tbody')
.append('<tr class="kendo-data-row"><td colspan="' + colCount + '" style="text-align:center" class="k-state-error"><b>No Results Found</b></td></tr>');
}
// Get visible row count
var rowCount = grid.find('.k-grid-content tbody tr').length;
// If the row count is less that the page size add in the number of missing rows
if (rowCount < dataSource._take) {
var addRows = dataSource._take - rowCount;
for (var i = 0; i < addRows; i++) {
grid.find('.k-grid-content tbody').append('<tr class="kendo-data-row"><td> </td></tr>');
}
}
}
EDIT: Here's a JSFiddle example
I am trying to get a value of a cell in a html table within JavaScript. I can do this when the row is clicked twice or when I click on a row and then another row but I need to get the cell value on first click
This is my code so far
var table = document.getElementById('ContentPlaceHolder1_htmltable');
if (table != null) {
for (var i = 0; i < table.rows.length; i++) {
for (var j = 0; j < table.rows[i].cells.length; j++)
table.rows[i].cells[j].onclick = function () {
cellvalue = this.innerHTML;
};
}
}
This runs on an onclick event on the ASPxListBox object from devexpress I am using.
Note: I can't use third party libraries like jQuery for this.
Thanks
The jsfiddle code posted by arcade Gandalf above does work, however, to fix my problem of getting the cell value on first click, the code needs to run when the page load is complete
window.onload = getCellValueOfTable;
function getCellValueOfTable {
jsFiddle code or my code posted above...
}
Then in the onclick event for the listbox or a table as I described in the question, just call the above function and that is all.
I apologize in advance, English is not my native language.
I am working on a project that was delegated to me. I am working on a webpage, that is being generated by an XSLT file. I only have access to the source code of the generated page.
What does it do: The page shows a synopsis in form of a table. The left most column (lets call that one A) and the top most row (lets call it B) are the Header (?) segments (like in this table i found on google)
There are also Buttons in the top most row to sort the table.
Now the problem: There is a button to invert the table which activates the following code. This is where the problem is
I have this java code
// FAULTY FUNCTION BEGINNING
function swap_table_horizontally_vertically() {
//This is the code I already have
// Deletes all sort buttons
for (i = 0; i <= 1000; i++) {
try {
var sort_buttons = document.getElementById('sort_buttons');
}
catch(err) {
alert(err.message);
continue;
} finally {
sort_buttons.parentNode.removeChild(sort_buttons);
}
}
//End of the Code I made
//This code was already in the file
var old_table = document.getElementById('synopsis_table'),
old_table_rows = old_table.getElementsByTagName('tr'),
cols = old_table_rows.length, rows = old_table_rows[0].getElementsByTagName('td').length,
cell, next, temp_row, i = 0, new_table = document.createElement('table');
while(i < rows) {
cell = 0;
temp_row = document.createElement('tr');
if (i == 0) {
while(cell < cols) {
next = old_table_rows[cell++].getElementsByTagName('td')[0];
temp_row.appendChild(next);
}
new_table.appendChild(temp_row);
++i;
}
else {
while(cell < cols) {
next = old_table_rows[cell++].getElementsByTagName('td')[0];
temp_row.appendChild(next);
}
new_table.appendChild(temp_row);
++i;
}
}
old_table.parentNode.replaceChild(new_table, old_table);
new_table.setAttribute("id", "synopsis_table");
}
// FAULTY FUNCTION END
Now what I need is a way to add the buttons again into the new table head (top most row) with a class and id attribute.
To summarize: I need to delete the buttons from the previous top most row (because the left column shouldn't have them) and add them again to the new top most row (the previous left column).