Remove all tr elements unless tr>td>input has a class 'DontRemoveMe' - css

Sorry for the very specific title, couldn't think of how to say it in more general terms.
Assume you have a table and each row contains a cell that has an input, but some input fields have a class of 'DontRemoveMe'. How do you target every row except the 'DontRemoveMe' rows?

Manipulation of DOM Elements requires JavaScript. One way to achieve this is with jQuery:
function remove() {
$('tr:not(.dontRemoveMe)').remove();
}
.dontRemoveMe td {
background-color: green;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr class="dontRemoveMe">
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Jon</td>
<td>Jones</td>
<td>33</td>
</tr>
</table>
<button onclick="remove()">Remove rows</button>

CSS (Not Yet Implemented):
Using CSS level 4 selectors, I believe it would be
tr:has(td>input:not(>>.DontRemoveMe))
However, those aren't implemented in any browser. So you would want to use javascript.
Javascript:
// Select all rows that don't contain a input.DontRemoveMe
let rows = Array.from(document.querySelectorAll("tr")).filter(x => !(x.querySelector("input.DontRemoveMe")));
// Add a special class to these rows so we can target them with CSS
rows.forEach(x => x.classList.add("selected"));
td {
padding: 8px; /* Padding for all rows to make background visible */
}
.selected {
background: red;
}
<table>
<tr>
<td><input type="text" value="selected" />
</td>
</tr>
<tr>
<td><input class="DontRemoveMe" type="text" value="not selected" />
</td>
</tr>
<tr>
<td>
<input type="text" value="selected" />
</td>
</tr>
</table>

Here is an old school javascript way.
Find all the tr tags then find any children with class DontRemoveMe, if it doesn't find any add a .hide class to the current row.
But, honestly I'd question the reason you want to do it like this, chances are there is a more sensible way.
var tr = document.getElementsByTagName('tr');
var i = 0;
var length = tr.length
for (; i < length; i++) {
var dontRemove = tr[i].getElementsByClassName('DontRemoveMe')
if (!dontRemove.length) {
tr[i].classList.add('hide')
}
}
td {
color: #ededed;
}
.red {
background-color: #ff3030;
}
.blue {
background-color: #6495ED;
}
.hide {
display: none;
}
<table>
<tr class="red">
<td>Normal</td>
<td>Normal</td>
<td class="DontRemoveMe">Don't Remove Me</td>
</tr>
<tr class="blue">
<td>Can't see me</td>
<td>Can't see me</td>
<td>Can't see me</td>
</tr>
<tr class="red">
<td class="DontRemoveMe">Don't Remove Me</td>
<td>Normal</td>
<td class="DontRemoveMe">Don't Remove Me</td>
</tr>
</table>

Related

Checking table cell for an and coloring it

I asked a question about coloring an empty cell for accessibility purposes and I got a great answer that worked perfectly. Now I have found some of the empty cells actually contain the . I would like to be able to check for that and colorized as well. I did this and it did not work, is it possible?
table td[ ]:before {
background-color: gold;
content: "Cell only contains a ";
}
Any thoughts? Thanks in advance!!
You need js to achieve that. Something like:
const highlightBg = (selector, seed, color) => {
const elements = Object.values(document.querySelectorAll(selector));
const elementsToHighlight = elements.filter(
(element) => element.innerHTML.includes(seed),
);
elementsToHighlight.forEach((element) => element.style.backgroundColor = color);
}
document.querySelector('#highlightButton').addEventListener(
'click',
() => highlightBg('td', '&nbsp', 'gold'),
);
<table>
<thead>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cel A1</td>
<td>Cel A2</td>
<td>Cel A3</td>
</tr>
<tr>
<td>Cel B1</td>
<td>Cel B2</td>
<td>Cel B3</td>
</tr>
<tr>
<td>Cel C1</td>
<td>Cel C2</td>
<td>Cel C3</td>
</tr>
</tbody>
</table>
<hr>
<button id="highlightButton">Highlight</button>
CSS cannot check the content of a tag, javascript can
here is a test example that might not cover all situation you have:
// edit : best is to do it once the page is loaded
window.onload = function() {
let tdEmpty = document.querySelectorAll('td');
for (i = 0; i < tdEmpty.length; i++) {
if (tdEmpty[i].innerHTML == ' ') {
tdEmpty[i].classList.add('empty')
}
}
}
table,
td {
border: solid 1px;
}
td {
height: 1em;
width: 1em;
background: gray;
}
:empty {
background: hotpink;
}
.empty {
background: gold;
}
<table>
<tr>
<td></td>
<td> </td>
<td></td>
<td>text</td>
<td> </td>
<td></td>
<td><i> </i></td>
<td> </td>
<td></td>
<td> </td>
<td> </td>
</tr>

Change table column header and table cell element position #media in CSS

I need to make a table responsive using CSS. When the screen size is small I must make the table headers and table cell data appear side by side. How can I do that using only CSS?
<table class="hobbies_table">
<tr>
<th>Name</th>
<th>Age</th>
<th class="hobbies">Hobby1</th>
<th class="hobbies">Hobby2</th>
<th>Contact</th>
</tr>
<tr>
<td>John</td>
<td>21</td>
<td class="hobbies_values">Football</td>
<td class="hobbies_values">Snooker</td>
<td>1234567890</td>
</tr>
<tr>
<td>Jack</td>
<td>30</td>
<td class="hobbies_values">Reading</td>
<td class="hobbies_values">Swimming</td>
<td>1234567890</td>
</tr>
<tr>
<td>Jenna</td>
<td>40</td>
<td class="hobbies_values">Travelling</td>
<td class="hobbies_values">Singing</td>
<td>1234567890</td>
</tr>
</table>
.hobbies {
width: 50%;
display: flex;
}
.hobbies_values {
width: 50%;
display: flex;
}
#hobbies_table td:nth-of-type(3):before { content: attr(hobbies) }
#hobbies_table td:nth-last-of-type(2):before { content: attr(hobbies) }
I know only basic CSS. So this is what I have tried. But I came to know this is the wrong way. So how can I correct the code?
Here in #media, I want the hobbies and hobbies_values to be displayed like this:
Hobby1: Football
Hobby2: Snooker
Hobby1: Reading
Hobby2: Swimming
Hobby1: Travelling
Hobby2: Singing
May it helps :)
.hobbies_table {
width: 100%;
}
th {
display: flex;
}
tr {
width: 20%;
display: inline-grid;
}
<table class="hobbies_table">
<tr>
<th>Name</th>
<th>Age</th>
<th class="hobbies">Hobby1</th>
<th class="hobbies">Hobby2</th>
<th>Contact</th>
</tr>
<tr>
<td>John</td>
<td>21</td>
<td class="hobbies_values">Football</td>
<td class="hobbies_values">Snooker</td>
<td>1234567890</td>
</tr>
<tr>
<td>Jack</td>
<td>30</td>
<td class="hobbies_values">Reading</td>
<td class="hobbies_values">Swimming</td>
<td>1234567890</td>
</tr>
<tr>
<td>Jenna</td>
<td>40</td>
<td class="hobbies_values">Travelling</td>
<td class="hobbies_values">Singing</td>
<td>1234567890</td>
</tr>
</table>
There are two popular approaches to your problem:
Solution A (Bootstrap's classic "table responsiveness")
Simply wrap the table inside a scrollable div and allow it to have its full width. Note this becomes confusing on mobile devices, especially when the user starts scrolling in both directions. A better mobile user experience is often times opening the table in a modal and allowing the user to scroll it in full screen).
Solution B (Separate markup for each case)
Have separate markup for each case, hiding the unwanted contents using #media queries. The base principle is that you duplicate content and hide the clone you don't want displayed on each responsiveness interval.
As with almost anything, no solution is clearly better than the other. It largely varies from case to case.
Here's a solution catered for your particular case (based on clarifications in comments):
.mobile_content {
display: none;
}
#media (max-width: 700px) {
.desktop_content {
display: none;
}
.mobile_content {
display: block;
}
.hobbies_values + .hobbies_values {
display: none;
}
}
<table class="hobbies_table">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th class="hobbies_values">
<div class="desktop_content">Hobby1</div>
<div class="mobile_content">Hobbies</div>
</th>
<th class="hobbies_values">Hobby2</th>
<th>Contact</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>21</td>
<td class="hobbies_values">Football<div class="mobile_content">Snooker</div></td>
<td class="hobbies_values">Snooker</td>
<td>1234567890</td>
</tr>
<tr>
<td>Jack</td>
<td>30</td>
<td class="hobbies_values">Reading<div class="mobile_content">Swimming</div></td>
<td class="hobbies_values">Swimming</td>
<td>1234567890</td>
</tr>
<tr>
<td>Jenna</td>
<td>40</td>
<td class="hobbies_values">Travelling<div class="mobile_content">Singing</div></td>
<td class="hobbies_values">Singing</td>
<td>1234567890</td>
</tr>
</table>
It's actually a separate case of solution B (where, rather than completely replace the table markup - you reuse part of it and only duplicate the part that is displayed under other column's content).

Mobile responsive tables

I’ve built a web application and am in the process of making the pages mobile responsive. Specifically, I’m dealing with tables. I found a write up that explains how to make the table switch from horizontal to vertical for tablets and phones which have smaller screens. This works great, but the page has 3 tables and I’m not sure how to adapt the CSS for the 3 different tables.
The write up: https://www.liquidlight.co.uk/blog/article/tables-in-responsive-design/
Code Demo: https://codepen.io/team/css-tricks/pen/wXgJww?editors=1100
The portions I’m having trouble with is the labels of the cells. The CSS uses:
td:before {
/* Now like a table header */
position: absolute;
/* Top/left values mimic padding */
top: 0;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
}
/*
Label the data
You could also use a data-* attribute and content for this. That way "bloats" the HTML, this way means you need to keep HTML and CSS in sync. */
td:nth-of-type(1):before { content: "No Longer with Parish"; }
td:nth-of-type(2):before { content: "Position"; }
td:nth-of-type(3):before { content: "Name, City"; }
td:nth-of-type(4):before { content: ""; }
td:nth-of-type(5):before { content: "Religious Affiliation"; }
td:nth-of-type(6):before { content: "Virtus"; }
td:nth-of-type(7):before { content: "Background Check"; }
td:nth-of-type(8):before { content: "Standard Code of Conduct"; }
td:nth-of-type(9):before { content: "Technology / Social Media"; }
td:nth-of-type(10):before { content: "Youth (under 18) Code of Conduct"; }
}
The CSS adds a cell before each cell in the row which contains a label for the item. This would be fine if all the tables showed the same data and could use the same labels. The problem is that they don’t. The 3 tables all have different numbers of columns as well.
How do I tweak the CSS to differentiate between the 3 tables? Should I use an ID in each of the td cells such as id=”One”; id=“Two”; id=”Three” and then target the td id?
I've tried adding id="one" to the first cell and using the following CSS to add the label, but can't get the label to show:
td#one:before { content: "label"; }
td#one:nth-of-type(1):before { content: "label"; }
#one:before { content: "label"; }
#one:nth-of-type(1):before { content: "label"; }
In the design window of visual studio, the cell is referenced as td#one so I thought that one of the first 2 lines of CSS would work. No label shows. Can someone explain how to reference the cell in order to get the label to show? Once I get that to work, table one will have cells one to nine, table two will have cells ten through nineteen and table three will have cells twenty through twenty-eight.
Maybe instead, I could add the label to the main td cell inside a div that displays none or inline using media queries.
Use nth-child instead of nth-of-type.
th:nth-child(1):before{content:'First Name'}
th:nth-child(2):before{content:'Last Name'}
th:nth-child(3):before{content:'Job Title'}
th:nth-child(4):before{content:'Favorite Color'}
th:nth-child(5):before{content:'Wars or Trek?'}
th:nth-child(6):before{content:'Secret Alias'}
th:nth-child(7):before{content:'Date of Birth'}
th:nth-child(8):before{content:'Dream Vacation City'}
th:nth-child(9):before{content:'GPA'}
th:nth-child(10):before{content:'Arbitrary Data'}
<table border="1">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody role="rowgroup">
<tr role="row">
<td role="cell">James</td>
<td role="cell">Matman</td>
<td role="cell">Chief Sandwich Eater</td>
<td role="cell">Lettuce Green</td>
<td role="cell">Trek</td>
<td role="cell">Digby Green</td>
<td role="cell">January 13, 1979</td>
<td role="cell">Gotham City</td>
<td role="cell">3.1</td>
<td role="cell">RBX-12</td>
</tr>
<tr role="row">
<td role="cell">The</td>
<td role="cell">Tick</td>
<td role="cell">Crimefighter Sorta</td>
<td role="cell">Blue</td>
<td role="cell">Wars</td>
<td role="cell">John Smith</td>
<td role="cell">July 19, 1968</td>
<td role="cell">Athens</td>
<td role="cell">N/A</td>
<td role="cell">Edlund, Ben (July 1996).</td>
</tr>
<tr role="row">
<td role="cell">Jokey</td>
<td role="cell">Smurf</td>
<td role="cell">Giving Exploding Presents</td>
<td role="cell">Smurflow</td>
<td role="cell">Smurf</td>
<td role="cell">Smurflane Smurfmutt</td>
<td role="cell">Smurfuary Smurfteenth, 1945</td>
<td role="cell">New Smurf City</td>
<td role="cell">4.Smurf</td>
<td role="cell">One</td>
</tr>
<tr role="row">
<td role="cell">Cindy</td>
<td role="cell">Beyler</td>
<td role="cell">Sales Representative</td>
<td role="cell">Red</td>
<td role="cell">Wars</td>
<td role="cell">Lori Quivey</td>
<td role="cell">July 5, 1956</td>
<td role="cell">Paris</td>
<td role="cell">3.4</td>
<td role="cell">3451</td>
</tr>
<tr role="row">
<td role="cell">Captain</td>
<td role="cell">Cool</td>
<td role="cell">Tree Crusher</td>
<td role="cell">Blue</td>
<td role="cell">Wars</td>
<td role="cell">Steve 42nd</td>
<td role="cell">December 13, 1982</td>
<td role="cell">Las Vegas</td>
<td role="cell">1.9</td>
<td role="cell">Under the couch</td>
</tr>
</tbody>
</table>

Fixed search box and table header, scrolling body

I have the following code for an address book. I'd like to have the search box and table header fixed allowing the table body to scroll up (or behind). I've tried several different CSS coding techniques without success. Can anyone point me to a CSS-only solution? The HTML/CSS code follows.
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#myInput").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
th {
border: 1px solid #dddddd;
font-size: x-large;
text-align: left;
padding: 8px;
}
td {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #ccffff;
}
</style>
</head>
<body>
<h1>Directory</h1>
<!-- <p>Search</p> -->
<input id="myInput" type="text" placeholder="Search..">
<br><br>
<table>
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Number</th>
<th>Street</th>
<th>Phone</th>
<th>Mobile</th>
<th>Email</th>
</tr>
</thead>
<tbody id="myTable">
<tr>
<td>James</td>
<td>Smith</td>
<td>163</td>
<td>Canal Lane</td>
<td>N/A</td>
<td>916-806-9999</td>
<td>jim#gmail.com</td>
</tr>
<tr>
<td>Jacquelyn</td>
<td>Abel</td>
<td>4551</td>
<td>Paso Lane</td>
<td>999-999-9208</td>
<td>999-999-3835</td>
<td>he51#comcast.net</td>
</tr>
<tr>
<td>Deborah Kay</td>
<td>Affal</td>
<td>335</td>
<td>Suez Lane</td>
<td>555-555-4897</td>
<td>555-555-3773</td>
<td>debb#hotmail.com</td>
</tr>
<tr>
<td>Emily</td>
<td>Aguate</td>
<td>3943</td>
<td>River Lane</td>
<td>444-444-2951</td>
<td>444-444-0514</td>
<td>erag#hotmail.com</td>
</tr>
<tr>
<td>Anthony (Tony)</td>
<td>Alba</td>
<td>4449</td>
<td>Red Lane</td>
<td>N/A</td>
<td>777-777-7778</td>
<td>tony35#yahoo.com</td>
</tr>
<tr>
<td>Amador</td>
<td>Alcan</td>
<td>14</td>
<td>Izmal Place</td>
<td>222-222-2002</td>
<td>333-333-3418</td>
<td>abab#7lakes.com</td>
</tr>
<tr>
<td>Ofelia</td>
<td>Alcan</td>
<td>14</td>
<td>Izmal Place</td>
<td>234-234-2002</td>
<td>234-234-7151</td>
<td>ofof#7lakes.com</td>
</tr>
<tr>
<td>Sherry</td>
<td>Allala</td>
<td>3910</td>
<td>Euboea Lane</td>
<td>5657-567-9331</td>
<td>567-567-9427</td>
<td>sherr11#att.net</td>
</tr>
<tr>
<td>Lori</td>
<td>Anders</td>
<td>3905</td>
<td>ADel Paso Lane</td>
<td>N/A</td>
<td>789-789-4784</td>
<td>mags3#yahoo.com</td>
</tr>
<tr>
<td>Peggy</td>
<td>Angert</td>
<td>3924</td>
<td>Pozzlo Lane</td>
<td>N/A</td>
<td>321-321-3494</td>
<td>peggy00#yahoo.com</td>
</tr>
<tr>
<td>Peter</td>
<td>Angty</td>
<td>3924</td>
<td>Pozzaler Lane</td>
<td>N/A</td>
<td>678-678-3003</td>
<td>peter5657#hotmail.com</td>
</tr>
<tr>
<td>Caryne</td>
<td>Angler</td>
<td>4436</td>
<td>Sea Lane</td>
<td>N/A</td>
<td>987-987-6605</td>
<td>N/A</td>
</tr>
<tr>
<td>Neata</td>
<td>Anton</td>
<td>3973</td>
<td>Don Lane</td>
<td>456-456-8711</td>
<td>456-456-4744</td>
<td>nea456t#sbcglobal.net</td>
</tr>
</tbody>
</table>
Put the table's head and the search box in a separate div and set it's position attribute to fixed.
// I'm assuming that you've assigned the div a class called
// .th_div
.th_div { position: fixed; }
An element with position: fixed; is positioned relative to the viewport, which means it always stays in the same place even if the page is scrolled.

Hide item using CSS

What's wrong with my CSS code? I want to hide the Timestamp column but it's not working? I do not have access to anything in the body, as it is automatically generated, hence i'm trying to use css.
http://snipt.org/Asge0
Code:
<html><head>
<meta http-EQUIV="refresh" content="5">
<style TYPE="text/css">
th, td {
padding-RIGHT: 50px;
text-ALIGN: CENTER;
}
.tb {
CLEAR: both;
}
.tsp {
display: none;
}
</style>
</head>
<body>
<div CLASS="tb"><!-- channeltable schedule="" --><table class="jdt" cellspacing="0">
<colgroup>
<col CLASS="sid"/>
<col CLASS="sun"/>
<col CLASS="chv"/>
<col CLASS="dfu"/>
<col CLASS="tsp"/>
</colgroup>
<thead>
<tr>
<th>Schedule</th>
<th>Name</th>
<th>Value</th>
<th>Units</th>
<th>Timestamp</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>Stream Level</td>
<td>---</td>
<td>metres</td>
<td>2013/06/18 18:10:01.948</td>
</tr>
<tr>
<td>A</td>
<td>Stream Flow</td>
<td>---</td>
<td>cumecs</td>
<td>2013/06/18 18:10:01.989</td>
</tr>
<tr>
<td>A</td>
<td>Tank Pressure</td>
<td>---</td>
<td>PSI</td>
<td>2013/06/18 18:10:02.029</td>
</tr>
<tr>
<td>A</td>
<td>Bubbler Voltage</td>
<td>---</td>
<td>V</td>
<td>2013/06/18 18:10:02.068</td>
</tr>
<tr>
<td>A</td>
<td>Water Temperature</td>
<td>---</td>
<td>Deg</td>
<td>2013/06/18 18:10:03.176</td>
</tr>
<tr>
<td>A</td>
<td>Conductivity</td>
<td>---</td>
<td>uS/cm</td>
<td>2013/06/18 18:10:03.244</td>
</tr>
<tr>
<td>A</td>
<td>Turbidity</td>
<td>---</td>
<td>NTU</td>
<td>2013/06/18 18:10:03.284</td>
</tr>
<tr>
<td>A</td>
<td>pH</td>
<td>OverRange</td>
<td>pH units</td>
<td>2013/06/18 18:10:03.322</td>
</tr>
<tr>
<td>A</td>
<td>Ext. Battery Voltage</td>
<td>18.996444</td>
<td>V</td>
<td>2013/06/18 18:10:03.323</td>
</tr>
</tbody>
EDIT:
Try this javascript hack:
(as it is it just reads first <tbody>, if you have more than one in each page you can add another for loop like in myrows)
var tbody = [];
var tbody = document.getElementsByTagName("tbody");
var myrows = [];
var myrows = tbody[0].getElementsByTagName("tr");
for (var i in myrows) {
var mycells = [];
var mycells = myrows[i].getElementsByTagName("td");
var lastcell = mycells[mycells.length - 1];
lastcell.style.color = "blue";
}
First answer:
Try with :last-child.
Something like
td:last-child {display:none;}
You have to set each <td> tag which you like to hide to <td class="tsp"> colgroup does not support the display attribute.
supported attributes are:
align, char, charoff, valign, width and span
some attributes are not supported in HTML5.
http://www.w3schools.com/tags/tag_colgroup.asp
Edit: as you mentioned you can not access table body try this to hide the 5th column in table:
tr td:nth-child(5), tr th:nth-child(5) {
display: none;
}
tr td + td + td + td + td {display:none } /*IE 8*/
As fallback for older browsers you also can try just to set width: 0px for colgroup
You need to apply the class to all corresponding td's and th's as well
<thead>
<tr>
<th>Schedule</th>
<th>Name</th>
<th>Value</th>
<th>Units</th>
<th CLASS="tsp">Timestamp</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>Stream Level</td>
<td>---</td>
<td>metres</td>
<td CLASS="tsp">2013/06/18 18:10:01.948</td>
</tr>
...etc
You can use the pseudo class :nth-child(n) on your table:
.jdt tr th:nth-child(5), .jdt tr td:nth-child(5) {
display: none;
}
This will hide the 5'th td, th elements in the table.
For more special selectors see this article:
http://net.tutsplus.com/tutorials/html-css-techniques/the-30-css-selectors-you-must-memorize/

Resources