Javascript - hiding table rows based on enclosed TD content - javascript

I'm writing a python app which is displaying an HTML table of pupil capabilities. I want to add the ability to filter the view depending on those capabilities - including multiple filters at the same time, hence wanting to do this in javascript (managing this via database lookups was becoming unwieldy).
I have a table which has a grid of capabilities (true/false), and to each 'false' I have added a class, such as 'pupil_web', and I have written a javascript function which will hide the on that row, triggered by a button at the top of each column.
But what I want is for the function to hide the entire row if it contains a td of that class, and I can't work out how to do it. I'm a fairly basic Python programmer, and this is my first project of any reasonable size; so far it's going well, but having spent a couple of hours trying to get this working (and getting as far as hiding the TD, not the enclosing row), I'd appreciate some help or a pointer in the right direction - I can't work out how to make the function look inside the row's content, only to look at each individual TD.
Here's the Javascript (note that at the moment I'm using Jinja2 to create multiple functions, each one for each capability, where the name of the function and the capability DIV content are linked - again I'm sure I'm not doing that in the best manner (creating a function for each column), but at the moment I'd rather get it working in the present form and then hopefully optimise in the future).
function toggle_{{ capability }}() {
var table, td, i;
table = document.getElementById("myTable");
td = table.getElementsByClassName("div_{{ capability }}");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < td.length; i++) {
if (td[i].style.display === "none") {
td[i].style.display = "";
} else {
td[i].style.display = "none";
}
}
}
Here's a simple version of the HTML table (the real one has about 20 columns, with a class tag present for the column entry that would lead to a row being hidden).
<tr>
<td>
Pupil 1
</td>
<td>
<img class="pupil_web" src="static/cross.png" width="25">
</td>
<td>
<img src="static/tick.png" width="25">
</td>
</tr>
<tr>
<td>
Pupil 2
</td>
<td>
<img src="/static/tick.png" width="25">
</td>
<td>
<img class="pupil_email" src="static/cross.png" width="25">
</td>
</tr>
Any pointers in the right direction would be greatly appreciated - I've not been at this long (I'm about 4 months in to a 2-year self-study plan), but I'm trying to learn rather than just give up and/or paste code in without understanding it.

Try this:
function toggle_{{ capability }}() {
var table, td, i;
table = document.getElementById("myTable");
td = table.getElementsByClassName("div_{{ capability }}");
// Loop through all table rows, and hide those who don't match the search query
if (td.parent().style.display === "none") {
td.parent().style.display = "";
} else {
td.parent().style.display = "none";
}
}
}

Related

How to hide a row of a table which does not contains a specific icon

I have a table with some items and those items can be selected by adding a tick. Check the image attached:
What I need to achieve is to hide the row which does not contain any ticks to be not visible. This is because in my app I have to generate lists of the items contains only ticks in another view. So when I will press the generate button that row will be hidden.
I just want to say if that row does not contain any 'glyphicon-ok' need to be deleted/hidden when I will generate the view with the list of those items.
I tried something like this:
SveCrf.prototype.hideRowWhereNoTicksForm = function () {
var tr = document.getElementsByTagName('tr');
for (var i = 0; i < tr.length; i++) {
switch (tr.item(i).getElementsByTagName('td').item(0).className) {
case "glyphicon-ok":
tr.item(i).style.display = "none";
break;
}
}
}
This doesn't do anything.
I would like to see an example of being able to resolve this issue.
Correct me if I'm wrong but you don't seem to have provided HTML you want to act upon but just a screenshot and a link to some RoR code in the comments that generates the HTML. Also you don't show how you try to execute SveCrf.prototype.hideRowWhereNoTicksForm, and furthermore I'm not really sure at all what you are trying to do with switch/case (I also don't understand what item is supposed to be; this is where providing us with actual HTML might have helped).
In addition, as I've alluded to in some comments of mine, you are really trying to do two things. I don't know if you've seen this Stackoverflow page yet about creating "a Minimal, Complete, and Verifiable example" but I think reviewing that will help improve your StackOverflow experience moving forward (and also for me it validated my suggestion of "divide and conquer").
All of which I think made it hard for you to get the help you desired. In any case below I'm providing some sample HTML with a table containing four rows total, two with a cell that contains the class foo, and two that don't. Beneath that is my non-jQuery code selecting the rows with no cells containing the class foo, and then hiding them; furthermore there is a demo of the same functionality using jQuery at https://repl.it/#dexygen/HideRowsWithNoCellsWithClass
<table border="1">
<tr><td class='foo'>foo</td><td></td><td></td></tr>
<tr><td></td><td>bar</td><td></td></tr>
<tr><td></td><td></td><td>baz</td></tr>
<tr><td class="foo">foo</td><td>bar</td><td>baz</td></tr>
</table>
/*
We cannot call `filter` directly on an HTMLCollection such as returned by
"document.getElementsByTagName('tr')" as it is not a bona fide array, so we use
"[].filter.call()", and we return only those rows that *fail* the test
"row.querySelector('td.foo')", then we loop over these with `forEach` and hide them
*/
[].filter.call(document.getElementsByTagName('tr'), function(row) {
return !row.querySelector('td.foo');
}).forEach(function(row) {row.style.display = 'none'});

How to hide multiple (thousands) rows in the html table

I have html page with many rows (is about 40000)
<html><body>
<table id="t1">
<tr id="r1" name="1"><td>row 1</td></tr>
<tr id="r2" name="1"><td>row 2</td></tr>
....
<tr id="r50000" name="3"><td>row 30000</td></tr>
</table></body></html>
I need a fast way to hide/show set of rows (10 000 or 20 000) with the specified name. Platform requirements: IE8-9 and Mozila Firefox. I tray many methods: using tbody, block tags, hiding rows, and stop at one: loop trow the rows and hide/show it:
curLevel=root.getAttribute("Name");
var nextElement=curElement.nextElementSibling;
while(nextElement!=null)
{
curElement=nextElement;
nextElement=curElement.nextElementSibling;
if(curElement.tagName=="TR")
{
i++;
childLevel=curElement.getAttribute("Name");
if(childLevel<=curLevel)
break;
curElement.style.display = blockStyle;
}
}
But this method is very slow!! Takes is about 2 minutes...
Loop goes fast, the slowest part is curElement.style.display = blockStyle; it repaints document every time.
Could I change display style for selection rows and then show changes?
P.S. without jQuery
Probably the fastest way is to use a CSS rule, either by adding and removing a rule, or modifying one. Since the rows you wish to hide have a common name, you can use the equivalent of the following to hide the rows with a name of "1":
tr[name="1"]{
display: none;
}
and remove the rule to show them. The following shows how to do that.
// Object to hold functions for adding and removeing style rules
var myStyles = (function() {
// Use the first style sheet for convenience
var sheet = document.styleSheets[0];
// Delete a rule from sheet based on the selector
function deleteRule(selector) {
// Get rules
var rules = sheet.rules || sheet.cssRules; // Cover W3C and IE models
// Search for rule and delete if found
for (var i=0, iLen=rules.length; i<iLen; i++) {
if (selector == rules[i].selectorText) {
sheet.deleteRule(i);
}
}
}
// Add a rule to sheet given a selector and CSS text
function addRule(selector, text) {
// First delete the rule if it exists
deleteRule(selector);
// Then add it
sheet.insertRule(selector + text);
}
// Return object with methods
return {
'addRule': addRule,
'deleteRule': deleteRule
};
}());
// Convenience functions to hide and show rows
function hideRows(){
myStyles.addRule('tr[name="1"]','{display: none}');
}
function showRows(){
myStyles.deleteRule('tr[name="1"]');
}
Alternative behaviours for the addRule function if a rule with the selector already exists are:
do nothing, or
add the new CSS text to the existing rule
Some play HTML:
<table>
<tr name="1"><td>name is 1
<tr name="1"><td>name is 1
<tr name="1"><td>name is 1
<tr name="1"><td>name is 1
<tr name="2"><td>name is 2
<tr name="2"><td>name is 2
<tr name="2"><td>name is 2
<tr name="2"><td>name is 2
</table>
<button onclick="hideRows()">Hide rows named 1</button>
<button onclick="showRows()">Show rows named 1</button>
Clicking on the first button hides all rows with a name of "1" by adding a CSS rule, clicking the other button shows them by removing the rule.
Of course you can make it much more sophisticated, the above just shows the method.
a table with 40000 rows is not the best for a webpage....
like pradipgarala say you should do it from server side.
or at list use "divs" to separate multiple tables with less rows..
<div id="table_1_1000">
<table>
...rows from 1 to 1000
</table>
</div>
like this you can show-hide only the divs you need... and the loop would be faster...
but still not the best solution....
My first idea would be to do something like this:
var start = 20000; // hide 10k rows
var end = 30001; // rows from 20k to 30k
while(end!=start) {
end--;
var x = 'r' + end;
document.getElementById(x).style.display = "none";
}
Basically, I would use IDs instead going trough DOM Nodes, if possible. It's "cheaper".
Since performance is an issue, you should note that is faster to decrement than to increment.
Note: Since I don't have enough rep, I can't comment on pradipgaralas answer so I'll note it here... Can you do something like IF "request is to hide/show over 10k(or whatever number your benchmark show you) rows" SEND REQUEST TO SERVER ELSE DO YOUR THING ON CLIENT SIDE?

Copy HTML Table to Text Box Using JQuery/JS

My problem has left me trying many solutions and stumped for a while now. My problem is exactly this:
There's a HTML table and a button on a page. Upon pressing the button, a script will run, copying the contents of the cells in the table into a text box. Here is the code for the table:
<table>
<tr><th></th><th>Category1</th></tr>
<tr><td>1.</td><td class="rule">Rule1</td></tr>
<tr><td>2.</td><td class="rule">Rule2</td></tr>
<tr><th></th><th>Category2</th></tr>
<tr><td>3.</td><td class="rule">Rule3</td></tr>
<tr><td>4.</td><td class="rule">Rule4</td></tr>
<tr><th></th><th>Category3</th></tr>
<tr><td>5.</td><td class="rule">Rule5 </td></tr>
<tr><td>6.</td><td class="rule">Rule6</td></tr>
<tr><td>7.</td><td class="rule">Rule7</td></tr>
<tr><th></th><th>Category4</th></tr>
<tr><td>8.</td><td class="rule">Rule8</td></tr>
</table>
My first thoughts were to write a script that iterated through the table and copied the contents of each cell (and creating a new line after every 2 cells). I realized very quickly, that I had no idea how to do that. After some searching I was able to come up with a script that clones the table, and it actually works quite well. This code is here:
$("button").click(function () {
$("table").clone().appendTo(".copy");
});
There are two problems that arise from using this method, however. I want plaintext, not a carbon copy of the table. The other problem is that this method only works when I clone the table into a div, it will not work when I try to clone it to a text box.
I've searched for a while for something similar to this and can only find solutions to copying single rows or cells. I had originally started there but couldn't figure out a way to write a loop that started at the beginning of the table and iterated through the entire thing, copying the contents as it iterated row by row (and creating a new line with each new row that it encountered). The loop would obviously end when there were no more rows to iterate through... This all sounds so simple to do, I know there must be a way.
Please Note: This script will be applied to a Site.Master Page so the script must be able to run for a plethora of tables. All of the tables follow the same structure shown above, but some will have more rows than others.
Any ideas? Any help is greatly appreciated.
You could use the .each() JQuery Method:
JS
function cloneTableContents()
{
$("table tr").each(function()
{
$(this).children().each(function()
{
$(".copy").append($(this).text());
});
});
}
JS For All Tables On Page In Order
function cloneTableContents()
{
$("table").each(function()
{
$(this).find("tr").each(function()
{
$(this).children().each(function()
{
$(".copy").append($(this).text()+" ");
});
});
});
}
HTML
<table id="mine">
<tr><th></th>
<th>Category1</th>
</tr>
<tr><td>1.</td><td class="rule">Rule1</td></tr>
<tr><td>2.</td><td class="rule">Rule2</td></tr>
<tr>
<th></th>
<th>Category2</th>
</tr>
<tr><td>3.</td><td class="rule">Rule3</td></tr>
<tr><td>4.</td><td class="rule">Rule4</td></tr>
<tr>
<th></th><th>Category3</th>
</tr>
<tr><td>5.</td><td class="rule">Rule5 </td></tr>
<tr><td>6.</td><td class="rule">Rule6</td></tr>
<tr><td>7.</td><td class="rule">Rule7</td></tr>
<tr>
<th></th><th>Category4</th>
</tr>
<tr><td>8.</td><td class="rule">Rule8</td></tr>
</table>
<textarea class="copy"></textarea>
<button onclick="cloneTableContents('mine','.copy');">Copy</button>
Working Example:
http://casewarecomputers.com:8088/soHelp.html

Getting Table Element

I want to get an element for a specific row in my HTML table.
Here is my table.
<tr class="inner2-top">
</tr>
I fill this table using Javascript for the following class:
<td class="ddu-orl">
So far I have around 9 rows. I was wondering how I would get the data for a specific row.
So far I have the following code but it seems to log all of the data for that class. What about for a specific row?
function removeRoute() {
var objectId = $(".inner2-top").find(".ddu-orl").text();
console.log(objectId);
}
I run the following code using the following HTML:
<td class="status1"><img src="images/cross.png" href="#" onclick="removeRoute()" width="12" height="12" alt="cross">
Within an onclick function if you pass this as argument it makes it easy to isolate instance.
<img onclick="removeRoute(this)">
Now you can traverse the DOM from the image. One path is first look up to the closest row, then looking within that row for the element wanted
function removeRoute(elem) {
var objectId = $(elem).closest('tr').find(".ddu-orl").text();
console.log(objectId);
}

Inserting new <TD> elements into a table row

I have created a small application written in XHTML, JavaScript/JQuery and PHP.
The PHP reads and writes to a small SQLite database.
How would I go about inserting <td> cells into a pre-scripted table. The cells would need to be configured using some information from my database. For example, below are two cells with their data retrieved from my database:
Cell One
Starts: 120px;
Finishes: 180px;
Background: Blue;
Cell Two
Starts: 240px;
Finishes: 300px;
Background: Green;
On my table row, it is 500px in width. How would I insert the cells above into the row. In this example, the first cell would start 120px into the row and have a width of 180px. The second cell would start 240px into the row and have a width of 300px.
I just can't seem to work out a way of doing this, any ideas would be very helpful.
Thank you for any input, all is appreciated.
Hunter.
forgive me if this answer is too simplistic but it sounds like you just need to loop through a variable that stores the cells that need to be inserted into a table that already exists.
Then you can dynamically generate the styles of whatever tag you need to edit such as style="<?= background-color:green; ?>"
I'm not exactly sure what you mean by starts and finishes. If your trying do placements then it will be a lot more complicated and you need some sort of position element in your db that can be referenced. But if you just mean height and width then you can also add these elements to the dynamically generate style
Not entirely sure what you're asking, but I'll give it a shot.
var c1 = 'stuff, stuff stuff.' // Your data for cell1
, c2 = 'more stuff.' // Data for cell2
$('table tr:first').append(
// Ugly multiline string
'<td width=120></td>
<td width=60 style="background-color: blue">' + c + '</td>
<td width=60></td>
<td width=60 style="background-color: green">' + c2 + '</td>
<td width=200></td>' // Filler
);
When building the tables, Put html comment tags with parameters so you can scan pre created output and insert where and how you like.
<table>
<!--|str1|2|60|100|--><tr>
<!--|str1td1|--><td width='60'>content row 1</td><!--|etr1td1|-->
<!--|str1td2|--><td width='100'>content row 2</td><!--|etr1td2|-->
</tr><!--|etr1|-->
<!--|str2|2|60|100|--><tr>
<!--|str2td1|--><td width='60'>content row 1</td><!--|etr2td1|-->
<!--|str2td2|--><td width='100'>content row 2</td><!--|etr2td2|-->
</tr><!--|etr2|-->
</table>
Then if you want to go back into your output and insert stuff, just strrpos (php) to the tr you want to edit and gather between comment tags, pharse the pipe seperated fields, you know the first is the id tag, the second is how many td's and the next two can be added to figure the width so far. Then find the tag for the end of the td you want to insert into after. Do your insert (include new tags!). Then go back and re comment the tr info you just read and include new row and information.
After all done and ready to output, go back and remove and the comment tag stuff from output. Or leave it in if you are lazy, it is just html comment stuff that will not be seen but kinda heavy on the text size side.
Sounds more complicated than it is, kind hard to explain but you should know exactly what i mean and the process can be more elaborate or simple to meet your needs.
If this is close to what you need, then hope this helps or ask me more, if not then i am sleepy so please excuse me.

Categories