Dynamically remove tableDatas from table - javascript

Update Code working Here
I have a table populated with teacher's disciplines that has: day of the week and it's time period, of course it also have the disciplines.
Now I need to remove those items.
Table:
<table id="prof-table">
<tbody><tr>
<th>HORÁRIO</th>
<th data-dia="mon">Monday</th>
<th data-dia="tue">Tuesday</th>
<th data-dia="wed">Wednesday</th>
<th data-dia="thu">Thursday</th>
<th data-dia="fri">Friday</th>
</tr>
<tr>
<td>08:30 ~ 10:30</td>
<td><ol><li data-id="6" data-prof="4">Calculo A</li></ol></td>
</tr>
<tr>
<td>10:30 ~ 12:30</td>
td></td><td><ol><li data-id="2" data-prof="4">Lab II</li></ol></td>
</tr>
<tr>
<td>14:30 ~ 16:30</td>
</tr>
<tr>
<td>16:30 ~ 18:30</td>
</tr>
<tr>
<td>18:30 ~ 20:30</td>
<td></td><td></td><td></td><td></td><td><ol><li data-id="5" data-prof="4">Estatistica</li></ol></td>
</tr>
<tr>
<td>20:30 ~ 21:30</td>
</tr>
<tr>
<td>21:30 ~ 23:30</td>
</tr>
</tbody></table>
What I did so far is to get the <td> from the rows but I don't know how to work with it, tried to use .each() from JQuery but I just cant do it.
Javascript:
var myRow = document.getElementById("prof-table").rows[range.index + 1];
var test = $(myRow.getElementsByTagName('td')).not(':first-child');//Skip the first td because its the time period of the discipline.
console.log(teste);
Now if you check the console.log() this is what is shown:
As you can see, there are three lines. Each line/obj has the exactly number of <td>s from the row.
What I need to do is loop through each of these lines. Also I need to reset the index for each loop.
EX: While interacting with the first line of the image, my Index goes from 0 ~ 1. Then when start the second line I need to start my index from 0 again untill 4 (because it has 5 elements td)
Tried something like:
$.each(teste, function(index, obj){
if($(obj).text() == "")
myRow.deleteCells(index);
});
But as the index doesnt "reset" for each of those lines in the picture, I get error about overflowing the row index limite. Because while the first row has only one <td> member, the last has 5, as the index is always growing ++ I get that error. And I have no idea how to work around it.

Because I don't understand you situation well, I create two function
To delete data based on "data-prof" attribute of "li" inside the "td"
To delete all data of the table.
In my oppinion, if you assign "data-prof" value to the "td" instead of "li", it'll boost performance.
Hope it's help.
Function to delete data based on "data-prof" attribute:
function resetTableData(dataProf) {
// Get cell list by data-prof
var $cellList = $("#prof-table").find("li[data-prof = " + dataProf + "]").closest("td");
$cellList.each(function(){
$(this).html(""); //Remove inner HTML of cells.
});
}
Function to delete data of all cells:
function resetTableData() {
// Get row list
var $rowList = $("#prof-table").find("tr").not(":first"); // First row is the header, don't need to select.
// Loop row list and get cell list of each
$rowList.each(function(){
// Cell list
var $cellList = $(this).find("td").not(":first"); // First column is time period, don't delete it.
// Loop cell list and delete content
$cellList.each( function() {
$(this).html(""); //Remove inner HTML of cells.
});
});
}

Related

Sort main rows while keeping sub order - jquery

I'm trying to figure out a good way to have a table which has sub data where we can sort on the main table without altering the sub data. Here's a MWE.
<table id="my-table">
<tr>
<th>Name</th>
<th class="selectable">Num</th>
</tr>
<tr id="main-1" class="main">
<td>Main 1</td>
<td>1</td>
</tr>
<tr class="main-1 sub">
<td>Sub 1</td>
<td>3</td>
</tr>
<tr id="main-2" class="main">
<td>Main 2</td>
<td>2</td>
</tr>
<tr class="main-2 sub">
<td>Sub 2</td>
<td>4</td>
</tr>
</table>
So you can kind of see I have 4 rows altogether, 2 rows that are "main" rows and 2 that are "sub" rows which are associated to certain "main" rows as can be seen through their classes.
What I'm looking to do is sort the table in such a way that only the main rows get sorted and the sub rows travel with the main rows. So if I sort by the second column I would have Main 1 - Sub 1 - Main 2 - Sub 2 and if I reverse the sort I would have the order Main 2 - Sub 2 - Main 1 - Sub 1.
I tried using https://github.com/padolsey-archive/jquery.fn/tree/master/sortElements but this seems to do the entire table and I can't figure out how to make it move "groups" of rows together.
Any ideas?
(Note: the reason I'm doing the HTML structure as is, is because normally all ".sub" are hidden and when you click on ".main" it grabs the id and shows everything that has a class with that id. I'm open to changing the HTML structure if needed, and I don't mind either way if the sub elements get sorted too, I just prefer that they move with the main row)
This is the code I was using, but since it only does every line in the table, it's not really relevant:
$('.sub').toggle();
$('.main').on('click', function(e) {
e.preventDefault();
$('.' + $(this).attr('id')).toggle();
});
var table = $('#my-table');
$('th.selectable')
.wrapInner('<span title="sort this column"/>')
.each(function(){
var th = $(this),
thIndex = th.index(),
inverse = true;
th.click(function(){
table.find('td').filter(function(){
return $(this).index() === thIndex;
}).sortElements(function(a,b){
a_num = parseInt($.text([a]))
b_num = parseInt($.text([b]))
if (a_num == b_num)
return 0;
return a_num > b_num ?
inverse ? -1 : 1
: inverse ? 1 : -1;
}, function() {
// parentNode is the element we want to move
return this.parentNode;
});
inverse = !inverse;
});
});

Replace old value with new value excluding the children

The initial text of A, B, C, D, and the number need to be removed in the frontend because I require it in the backend.
The HTML structure of table row is like this:
<tr ng-repeat="(key, field) in nbd_fields" ng-show="field.enable && field.published" class="ng-scope">
<td class="ng-binding">A,B,C,D: 1 - Auswahl Wunschkarte : <b class="ng-binding">Wähle eine Option</b>
</td>
<td ng-bind-html="field.price | to_trusted" class="ng-binding"></td>
</tr>
Before Input:
Current Output:
If you notice that the selected option is also not visible. Is it because of the $(window).load() ?
Required Output:
Code that I am using:
jQuery(".ng-scope td.ng-binding:first-child").text(function(i, oldVal) {
return oldVal.replace(/^[^-]+ - /,"");
});
});
How can I make it so that it does not affect the <b> tag inside?
I used the above code for the steps heading with a different selector on the same page* and it worked because it did not have any children to alter.
I had to wrap it around $(window).load() so that the changes are applied after the table is loaded. $(document).ready() did not work with it. Not sure why?
(Edit: Modified to accommodate restated requirement in comment below.)
To strip "everything up to and including the '-'" from the text of first column table cells while leaving the rest untouched:
// strip "everything up to and including the '-'"
// from table cell contents
function stripPrefix(tblCell) {
// only evaluate first td in tr
if (tblCell.previousElementSibling) {
return;
}
const tNode = tblCell.firstChild;
// ignore if table cell is empty
if (!tNode) {
return;
}
const chars = tNode.nodeValue.split('');
const iFirstDash = chars.indexOf('-');
if (iFirstDash === -1) { return; }
tNode.nodeValue = chars.slice(iFirstDash+1).join('');
}
function stripAllPrefixes() {
const tds = document.getElementsByTagName('td');
for (const td of tds) {
stripPrefix(td);
}
}
td {
border: 1px solid gray;
}
<h4>Strip "everything up to and including the '-'" from Table Cells</h4>
<table>
<tr>
<td>A,B,C,D: 1 - Auswahl Wunschkarte : <b>Wähle eine Option</b></td>
<td></td>
</tr>
<tr>
<td>B,C,D,E: 20 - A different leader : <b>should also be stripped</b></td>
<td></td>
</tr>
<tr>
<td>Oops no dash here <b>Just checking</b></td>
<td></td>
</tr>
</table>
<button onclick="stripAllPrefixes();">Strip All</button>
It does not effect the b tag, your code is working, you just need to use the right method and do the replacement to the HTML code and not the text nodes:
jQuery(".nbd-field-header label, .nbo-summary-table .ng-binding").html(function(i, oldVal) {
return oldVal.replace(/^[^-]+ - /,"");
});

Protractor - How to get all cells from one column and sum them when the Grid has id="0-0" for rows-Columns

I am validating a drill down process in the portal i am testing, for this my script is doing:
Read the value from the first row of a table and click at this value (there is a link for certain cells that perform the drill down to the detail page)
To click at this particular cell I am using it's ID:
<table id="transHistTable" class="table table-hover table-bordered table-striped dataTable no-footer" style="width: 100%" role="grid" aria-describedby="transHistTable_info">
<thead>
<tbody>
<tr role="row" class="odd">
<td id="0-0" class="ng-scope">31 Jul 2018</td>
<td id="0-1" class="ng-scope">RandomText0</td>
<td id="0-2" class="ng-scope">RandomText1</td>
<td id="0-3" class="ng-scope">EmptyValue</td>
<td id="0-4" class="ng-scope">Value I Click And Save it</td>
So for this table I am clicking directly to the row 0 column 4 since my data and my filters will always bring only one row, but then, comes my problem....
When the drill down is performed I never know how many rows I will have since it depends of user operations.
I need to perform a validation to compare the sum of all the values from the table displayed after the drill down with the value captured from table "transHistTable" row 0 column 4
This is the values I get after performing the Drill Down:
<table id="transHistDetailTable" class="table table-hover table-bordered table-striped dataTable no-footer" style="width: 100%" role="grid" aria-describedby="transHistDetailTable_info">
<thead>
</thead>
<tbody><tr role="row" class="odd">
<td id="0-0" class="ng-scope">Site</td>
<td id="0-1" class="ng-scope">Date</td>
<td id="0-2" class="ng-scope">Time</td>
<td id="0-3" class="ng-scope">I</td>
<td id="0-4" class="ng-scope">value 1</td>
<td id="0-5" class="ng-scope">value 2</td>
<td id="0-6" class="ng-scope">value 3</td>
<td id="0-7" class="ng-scope">12</td>
</tr></tbody>
</table>
So what I would like to do is reading all the rows (could be 0,1,2,3,4,5...) saving the value that is stored in Column 7 then after this is done, perform a sum and then comparing with the value I have saved from the first table.
My code is this one:
var rowstransHistDetail = element(by.id('transHistDetailTable')).all(by.tagName("tr"));
rowstransHistDetail.count().then(function(rcount){
//In case only 1 row is displayed
if (rcount < 3)
{
element(by.id('0-7')).getText().then(function(valueQty){
expect(valueQty).toEqual(600)
})
}
else
{
var tempValue
for (i=0; i < rcount; i++)
{
element(by.id(i+'-7')).getText().then(function(valueQty){
tempValue = Number(tempValue) + Number(valueQty)
})
}
expect(tempValue).toEqual(600);
}
});
But when I execute this, gives me a undefined value
Any ideas how to solve this please?
Thank you!!!!
It seems that you are incrementing a value in a loop before execution.
See here: https://stackoverflow.com/a/6867907/6331748
Should bee i++ instead of ++i in a loop.
Drop me a line if I'm wrong.
===========================
Edited:
Here's some code from my side:
var expectedCells = element.all(by.css('#transHistDetailTable tr td:nth-of-type(5)'));
var currentSum = 0;
expectedCells.each((eachCell) => {
eachCell.getText().then((cellText) => {
currentSum += Number(cellText);
});
}).then(() => {
expect(currentSum).toEqual(600);
});
Sorry, but wasn't able to test it. I only want to share a main idea and elaborate it.
expectedCells are all id=n-4 cells. We go through all elements and get text from them, change to the number type and add to current value. Aftermath we do an assertion.
It also looks that if statement is not necessarily.
Let me know how it works.
Two options for your issue:
1) using element.all().reduce()
let total = element
.all(by.css('#transHistDetailTable > tbody > tr > td:nth-child(8)'))
.reduce(function(acc, item){
return item.getText().then(function(txt) {
return acc + txt.trim() * 1;
});
}, 0);
expect(total).toEqual(600);
2) using element.all().getText() and Array.reduce
let total = element
.all(by.css('#transHistDetailTable > tbody > tr > td:nth-child(8)'))
.getText(function(txts){ //txts is a string Array
return txts.reduce(function(acc, cur){
return acc + cur * 1;
}, 0);
});
expect(total).toEqual(600);

How do I get specific values from checked rows in MVC razor view?

Ok, so I have this partial view (part of an MVC application) which just displays data from a view in the database.
#model IEnumerable<TransportPlanner.Models.TRANSPORT_PLANNER_VIEW>
<table>
<tr>
<th>#Html.CheckBox("HeaderCheck")</th>
<th>#Html.DisplayNameFor(model => model.Status)</th>
....
<th>#Html.DisplayNameFor(model => model.Volume)</th>
<th>#Html.DisplayNameFor(model => model.Weight)</th>
....
</tr>
#foreach (var item in Model) {
<tr>
<th>#Html.CheckBox("RowCheck")</th>
<td>#Html.DisplayFor(modelItem => item.Status)</td>
....
<td>#Html.DisplayFor(modelItem => item.Volume)</td>
<td>#Html.DisplayFor(modelItem => item.Weight)</td>
....
</tr>
}
</table>
I want to be able to find a way in which I can get the values for the Volume and Weight fields of only the checked rows (after checking them), and add them to get the total (which is displayed but not stored).
For example, once I get the results displayed on screen, and I check 3 rows (having the values of 'weight' as 5, 10 and 15), then value displayed should be '30' (sum of the weights). Similarly, if I remove the checkbox for the row having weight as '5', then the value displayed should be '25'.
My front end skills are almost non-existent, and I have scourged over the internet for nearly 12 hours but not found a way to do it. I know that I need to either use JavaScript (or some flavour of it like JQuery) or Ajax (if I need the values updates dynamically as I check/uncheck them).
What is the best way to achieve this, without updating my model? I don't have the luxury of time because I am the only developer at my workplace, and this is the first step of a huge task I need to complete in 3 weeks.
Your #Html.CheckBox("RowCheck") is generating invalid html (duplicate id attributes). Replace it with
<input type="checkbox" class="checkbox" />
Then add class names to the <td> elements for Volume and Weight
<td class="volume">#Html.DisplayFor(modelItem => item.Volume)</td>
<td class="weight">#Html.DisplayFor(modelItem => item.Weight)</td>
And assuming you want to display the totals in the table footer, add the following html to the <table> element (note you should also use the <thead> and <tbody> in your table
<table>
....
<tfoot>
<tr>
<td></td>
....
<td id="totalvolume"><td>
<td id="totalweight"><td>
....
</tr>
</tfoot>
</table>
Then you can use javascript/jquery to handle the change event of the checkboxes, and sum the values in each row. Using jquery:
$('.checkbox').change(function() {
var totalVolume = 0;
var totalWeight = 0;
var selected = $('.checkbox:checked'); // get the selected checkboxes
$.each(selected, function(index, item) { // loop through the selected checkboxes
var row = $(this).closest('tr'); // get the containing tr element
totalVolume += Number(row.find('.volume').text());
totalWeight += Number(row.find('.weight').text());
})
// display the totals
$('#totalvolume').text(totalVolume);
$('#totalweight').text(totalWeight);
});
Note, the above code assumes the values of properties Volume and Weight are numeric (without any formatting)

jquery table selector with condition

i had a table that submitted from my jquery append script, are its possible to find the match value with jquery selectors,
i want to check if the condition >= var $minimumEducation, it will pass to next page when submit, i set the value 0 for High School, 1 for Diploma and so on as it use selectbox, the var $minimumEducation variable come from my php admin, anyone knows how to pass this condition ? thanks
<thead>
<tr>
<th>Name</th>
<th>Relation</th>
<th>DOB</td>
<th>Education</th>
<th>Job</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Uncle</td>
<td>02/19/1955</td>
<td>Bachelor</td>
<td>Carpenter</td>
</tr>
<tr>
<td>Amy</td>
<td>Aunty</td>
<td>02/19/1950</td>
<td>Master</td>
<td>Housewife</td></tr>
<tr>
<td>Eddie</td>
<td>Cousin</td>
<td>02/19/1990</td>
<td>Diploma</td>
<td>Editor</td>
</tr>
</tbody>
</table>
You can select each matched element using the :has selector. To match against minimum education you must build the selector string based on the array mapping the education strings to the $minimumEducation value
$( "tr:has(td[value="bachelor"], td[value="master"])" )
This can be generated similar to the following
var query = "";
for (var i = minimumEducation; i < eduarray.length; i++) {
query += ', td[value="'+eduarray[i]+'"]';
}
query = query.substring(1);
Then just put the query string inside the selector
$( "tr:has("+query+")" )

Categories

Resources