How can I make the left column in a table disappear using plain JS?
This is my approach:
<table id="tab" border="1">
<tr>
<td>abc</td>
<td>def</td>
</tr>
<tr>
<td>ghi</td>
<td>jkl</td>
</tr>
<tr>
<td>mno</td>
<td>pqr</td>
</tr>
</table>
<button onclick="inv()">invisible</button>
<button onclick="vis()">visible</button>
<script>
var tab, td;
window.onload = function() {
tab = document.getElementById("tab");
td = tab.getElementsByTagName("td");
}
function inv() {
for (i = 0; i < td.length; i++) {
td[i].style.display = "none";
i++;
}
}
function vis() {
for (i = 0; i < td.length; i++) {
td[i].style.display = "block";
i++;
}
}
</script>
It works, but I have to use "ugly" loops.
Maybe there is a more efficient way by just saying column[0].display = "none".
Here is the fiddle.
Take advantage of CSS hierarchy and nth-child selectors.
Use selector tr td:nth-child(1) to select all the first column td elements.
JSfiddle
var tab;
// Use DOMContentLoaded instead of load event
document.addEventListener('DOMContentLoaded', function() {
tab = document.getElementById('tab');
});
function inv() {
tab.classList.add('hide');
}
function vis() {
tab.classList.remove('hide');
}
.hide tr td:nth-child(1) {
display: none;
}
<table id="tab" border="1">
<tr>
<td>abc</td>
<td>def</td>
</tr>
<tr>
<td>ghi</td>
<td>jkl</td>
</tr>
<tr>
<td>mno</td>
<td>pqr</td>
</tr>
</table>
<button onclick="inv()">invisible</button>
<button onclick="vis()">visible</button>
Demo using toggle with single button.
function toggle() {
document.getElementById('tab').classList.toggle('hide');
}
.hide tr td:nth-child(1) {
display: none;
}
<table id="tab" border="1">
<tr>
<td>abc</td>
<td>def</td>
</tr>
<tr>
<td>ghi</td>
<td>jkl</td>
</tr>
<tr>
<td>mno</td>
<td>pqr</td>
</tr>
</table>
<button onclick="toggle()">Toggle</button>
By the use of some empty css classes and jQuery, you are able to achieve that in a one-liner:
<table id="tab" border="1">
<tr>
<td class="col1">abc</td>
<td class="col2">def</td>
</tr>
<tr>
<td class="col1">ghi</td>
<td class="col2">jkl</td>
</tr>
<tr >
<td class="col1">mno</td>
<td class="col2">pqr</td>
</tr>
</table>
now you can just do:
jQuery(".col1").hide();
(mind the selector with a dot before the class name)
The most efficient solution would be to inject and remove a stylesheet and let the browser do the work.
Fiddle: https://jsfiddle.net/4L4h7ea1/2/
var tab, td;
var hideFirstColumnCss = document.createElement('style');
hideFirstColumnCss.setAttribute('id', 'hideCssStyle');
hideFirstColumnCss.innerHTML = '#tab td:first-child { display: none; }';
window.onload = function () {
tab = document.getElementById("tab");
td = tab.getElementsByTagName("td");
}
function inv() {
document.head.appendChild(hideFirstColumnCss);
}
function vis() {
var style = document.getElementById('hideCssStyle');
style.parentNode.removeChild(style);
}
Use the row tags to get to your cells to hide/show them. That way you can specify an index for the row as all cells are direct children of their row.
var tab, td;
window.onload = function () {
tab = document.getElementById("tab");
tr = tab.getElementsByTagName("tr");
}
function inv() {
for (i = 0; i < td.length; i++) {
tr[i].children[0].style.display = "none";
}
}
function vis() {
for (i = 0; i < td.length; i++) {
tr[i].children[0].style.display = "block";
}
}
Related
description cells will starts as hide. The row that I click, will show the description and if i click another row will the current row description and hide the other description
var getTable = document.querySelector("tbody");
var cells = getTable.getElementsByTagName("td");
for (let item of document.getElementsByClassName("desc")) {
item.style.display = "none";
}
for (var i = 0; i < cells.length; i++) {
cells[i].addEventListener("click", function () {
var selectedRow =
getTable.getElementsByTagName("tr")[this.parentNode.rowIndex];
if (!this.parentNode.rowIndex) {
$(selectedRow).find(".desc").css("display", "none");
} else {
$(selectedRow).find(".desc").css("display", "block");
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tblInventory">
<thead>
<tr>
<th>UPC</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>987456</td>
<td>Product Blanks</td>
<td class="desc">Unfinished template for parts 1000222 to 1000299</td>
</tr>
<tr>
<td>654123</td>
<td>Threaded Rods</td>
<td class="desc">Rods threaded at both ends for Support Brackets</td>
</tr>
</tbody>
</table>
Try this in vanilla:
document.querySelector('#tblInventory').addEventListener('click', (e) =>
{
// Hide other descriptions
document.querySelectorAll('#tblInventory td.desc span').forEach(span => {
span.style.display = 'none';
});
// Show clicked row description
if (e.target.tagName === 'TD') {
e.target.parentNode.querySelector('td.desc span').style.display = 'inline';
}
});
#tblInventory td.desc span {
display: none
}
<table id="tblInventory">
<thead>
<tr>
<th>UPC</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>987456</td>
<td>Product Blanks</td>
<td class="desc"><span>Unfinished template for parts 1000222 to 1000299</span></td>
</tr>
<tr>
<td>654123</td>
<td>Threaded Rods</td>
<td class="desc"><span>Rods threaded at both ends for Support Brackets</span></td>
</tr>
</tbody>
</table>
Or with jQuery:
$('#tblInventory').on('click', 'td', (e) => {
// Hide other descriptions
$('#tblInventory td.desc span').hide();
// Show clicked row description
$(e.target).closest('tr').find('td.desc span').show();
});
#tblInventory td.desc span {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<table id="tblInventory">
<thead>
<tr>
<th>UPC</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>987456</td>
<td>Product Blanks</td>
<td class="desc"><span>Unfinished template for parts 1000222 to 1000299</span></td>
</tr>
<tr>
<td>654123</td>
<td>Threaded Rods</td>
<td class="desc"><span>Rods threaded at both ends for Support Brackets</span></td>
</tr>
</tbody>
</table>
Using span is a suggestion, but you can fix the selectors to show/hide the td elements directly as well;
If you don't want to hide previous clicked descriptions, just remove the related code.
No jQuery.
I want to loop through unknown amount of table rows with the same class and add a click event that will change the class of hidden table row that is right bellow the one i clicked. All i managed to do is open all hidden rows on click..
Here is a fiddle with my current progres: jsfiddle.net
An my js code, that obviously doesn't work...
var x = document.querySelectorAll('.table');
var y = document.querySelectorAll(".content");
for (var i = 0; i < x.length; i++) {
x[i].addEventListener('click', function(event) {
for (var j = 0; j < y.length; j++) {
if (i === j) {
y[j].style.display = "block";
}
}
});
}
EDIT:
Also i saw that it is bad to make functions inside loops. Would appreciate some feedback on that as well...
Try with nextElementSibling function
Demo fiddle
var x = document.querySelectorAll('.table');
for (var i = 0; i < x.length; i++) {
x[i].addEventListener('click', function(event) {
this.nextElementSibling.style.display='block';
});
}
table tr td {
border: 2px solid #000;
}
table {
width: 500px;
height: 40px;
}
.content {
display: none;
width: 100px;
}
.table:hover {
background-color: red;
}
.content.visible {
display: table-cell;
}
<table>
<thead>
<tr>
<th>Tabela</th>
</tr>
</thead>
<tbody>
<tr class="table">
<td>Visible</td>
</tr>
<tr class="content">
<td>Hidden 1</td>
</tr>
<tr class="table">
<td>Visible</td>
</tr>
<tr class="content">
<td>Hidden 2</td>
</tr>
<tr class="table">
<td>Visible</td>
</tr>
<tr class="content">
<td>Hidden 3</td>
</tr>
<tr class="table">
<td>Visible</td>
</tr>
<tr class="content">
<td>Hidden 4</td>
</tr>
</tbody>
</table>
or If you need like toggle effect (reclick to hide) use this js code
var x = document.querySelectorAll('.table');
for (var i = 0; i < x.length; i++) {
x[i].addEventListener('click', function(event) {
var a = this.nextElementSibling.style.display;
this.nextElementSibling.style.display = (a == 'block') ? 'none': 'block';
});
}
Below is a snippet of the HTML. I'm trying to color the background of the tag that contains "Bananas".
<frame src="blah" name="navigation">
<table id="menu">
<tbody>
<tr>
<td>
<table>
<tbody>
<tr>
<td>
Apples
</td>
<td>
<input class="button">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tbody>
<tr>
<td>
Bananas
</td>
<td>
<input class="button">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tbody>
<tr>
<td>
Carrots
</td>
<td>
<input class="button">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</frame>
This is my JavaScript:
var t = navigation.document.getElementById("menu");
var trs = t.getElementsByTagName("tr");
var tds = null;
for (var i=0; i<trs.length; i++)
{
tds = trs[i].getElementsByTagName("td");
for (var n=0; n<trs.length;n++) {
if(tds[n].innerHTML == "Bananas") {
tds[n].bgcolor="#FF0000";
}
}
}
To be honest it's stumbling even on the 2nd line so I'm clearly doing something wrong. Can anyone suggest an efficient way to do this please?
This should do the job:
var table = document.getElementById('menu');
var tds = table.querySelectorAll('td');
for (var i = 0; i < tds.length; i++) {
var td = tds[i];
if (td.innerHTML.trim() === 'Bananas') {
td.style.backgroundColor = 'red';
}
}
This is a jquery-based solution:
//See: http://stackoverflow.com/questions/8779728/getting-element-within-frame-using-jquery
$("td", window.parent.frames[0].document).filter(function() {
return this.innerText.indexOf("Bananas") + 1;
}).css("background-color", "yellow");
This is a plain Javascript solution:
var items = window.frames[0].document.getElementsByTagName("td");
for (var item in items) {
if ((items[item].innerText) && (items[item].innerText.indexOf("Bananas") + 1)) {
items[item].style["background-color"] = "yellow";
}
}
However, it is nice to make things customizable, reusable. In our case, we could do a function. jquery version:
function jQueryBanana(context, test, operation) {
context.filter(function() {
test(this);
}).operation($(this));
}
Usage:
jQueryBanana($("td", window.parent.frames[0].document), function(record) {
return record.innerText + (record.innerText.indexOf("Bananas") + 1);
}, function(record) {
record.css("background-color", "yellow");
});
Plain Javascript function
function vanillaBanana(items, test, operation) {
for (var item in items) {
if (test(items[item])) operation[items[item]];
}
}
Usage:
vanillaBanana(window.frames[0].document.getElementsByTagName("td"), function(record) {
return record.innerText && (record.innerText.indexOf("Bananas") + 1);
}, function(record) {
record.style["background-color"] = "yellow";
});
This way of making your code more generic wll help you a lot in the long run.
You should use tds[n].innerText instead of tds[n].innerHTML
Difference between innerText and innerHTML in javascript
I have something that seems fairly simple but I'm stumped. I want a dropdown within a table that affects how many table rows are shown. By default, only 2 rows are shown. By selecting 4 in the dropdown, 4 rows should be shown. I am only seeing one of the hidden rows show up, and I've tried to wrap the 2 rows in a hidden div as well, no luck. Ideas?
<table border="1">
<tr>
<td class="noBG" colspan="3">
<select id="displayText" onchange="javascript:toggle();">
<option>2</option>
<option>4</option>
</select>Items
</td>
</tr>
<thead>
<tr>
<th>Dates</th>
<th>Time</th>
<th>Person</th>
</tr>
</thead>
<tr>
<td>12/3</td>
<td>12:45</td>
<td>John Doe</td>
</tr>
<tr>
<td>12/4</td>
<td>12:45</td>
<td>James Doe</td>
</tr>
<tr id="toggleText" style="display: none">
<td>12/4</td>
<td>12:45</td>
<td>Janey Doe</td>
</tr>
<tr id="toggleText" style="display: none">
<td>12/4</td>
<td>12:45</td>
<td>Janey Doe</td>
</tr>
</table>
<script language="javascript">
function toggle() {
var ele = document.getElementById("toggleText");
if(ele.style.display == "block") {
ele.style.display = "none";
}
else {
ele.style.display = "block";
}
}
</script>
Using display: block; doesn't work as the table rows will then displayed not in the right way. But you can toggle the visibility by adding and removing a class, which is defined with display: none;. So you must not switch display: none/block;, but the class.
This works (incl. jQuery): http://jsfiddle.net/Yuvvc/1/
You can use following code for JS function:
function toggle() {
$.each($('tr[name=toggleText]'), function() {
$(this).toggleClass("hiddenRow", $(this).attr('class') != "hiddenRow");
});
}
With the second parameter (bool) for .toggleClass you can add and remove the class.
EDIT
Here a non-jQuery version:
function toggle() {
var rows = document.getElementsByName("toggleText");
for(var i=0; i<rows.length; i++)
{
rows[i].className = (rows[i].className == "hiddenRow") ? "" : "hiddenRow";
}
}
Change all <tr id="toggleText" to <tr name="toggleText", and then change the toggle function to the following:
function toggle() {
var ele = document.getElementsByName("toggleText");
for (var i = 0; i < ele.length; i++) {
if (ele[i].style.display == "block") {
ele[i].style.display = "none";
}
else {
ele[i].style.display = "block";
}
}
}
You can toggle the hidden rows by giving each row an id like this:
<table class="table">
#foreach (var item in Model)
{
<tr>
<td onclick="toggle1(#item.ID)" colspan="3">
#Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
<tr class="hidden" id="bluh_#item.ID">
<td>
#Html.DisplayFor(modelItem => item.Code)
</td>
<td>
#Html.DisplayFor(modelItem => item.Position)
</td>
</tr>
}
then use JavaScript to Hide and Show the Children Rows
<script>
function toggle1(something) {
$("#bluh_"+something).toggleClass('hidden');
}
</script>
When I mouseover one TD in a row I want all the TDs to change background color at the same time, then reverse on mouseout.
How do I do this?
In CSS you could do
tr td { background-color: white }
tr:hover td { background-color: black };
or just
tr { background-color: white }
tr:hover { background-color: black };
if the tds don't have their own background color.
Both should make the row black on mouseover, and white otherwise.
You could also do it in Javascript of course, but that isn't necessary (except for IE6, which doesn't understand the :hover pseudo-class on anything but <a> tags)
var tds = document.getElementsByTagName("td");
for(var i = 0; i < tds.length; i++) {
tds[i].onmouseover = function() {
this.parentNode.style.backgroundColor = "#ff0000";
}
tds[i].onmouseout = function() {
this.parentNode.style.backgroundColor = "#fff";
}
}
This actually changes the background colour of the parent tr, not each td, but it could be easily modified to do so. You could also attach the events to the tr elements instead of the td elements, and then you wouldn't have to use parentNode, but I don't know whether you need to do other stuff in the event handler specifically related to the td.
<table border="1" cellpadding="5" cellspacing="0">
<tr>
<th></th>
<th>Water</th>
<th>Air</th>
<th>Fire</th>
<th>Earth</th>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Spring thunderclouds</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Roasting chestnuts</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Winter snowbanks</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Ice cream on a hot summer day</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
</table>
<script type="text/javascript">
// Specify the normal table row background color
// and the background color for when the mouse
// hovers over the table row.
var TableBackgroundNormalColor = "#ffffff";
var TableBackgroundMouseoverColor = "#9999ff";
// These two functions need no customization.
function ChangeBackgroundColor(row) {
row.style.backgroundColor = TableBackgroundMouseoverColor;
}
function RestoreBackgroundColor(row) {
row.style.backgroundColor = TableBackgroundNormalColor;
}
</script>
I don't know what your exact use-case is, but for such tasks I would stick to CSS only:
td {
background: #f00; }
tr:hover td {
background: #fc0; }
http://jsfiddle.net/feeela/53JBV/
<td onmouseover="changeColorTo(this.parentNode, put color here)" onmouseout="changeColorTo(this.parentNode, put color here)">
...
<script>
function changeColorTo(parent, color)
{
var i, tdArray = parent.getElementsByTagName('td');
for(i in tdArray)
{
tdArray[i].style.backgroundColor = color;
}
}
</script>
This is faster than using jQuery, also, not everybody uses jQuery.
This jsFiddle I created shows you how to do it with jQuery.
I am using jQuery's hover event to handle what you are trying to do.
If you want a framework-agnostic solution, you can try this:
function highlightCells(tableRow) {
for (var index = 0; index < tableRow.childNodes.length; index++) {
var row = tableRow.childNodes[index];
if (row.style) {
row.style.backgroundColor = "red";
}
}
}
function unhighlightCells(tableRow) {
for (var index = 0; index < tableRow.childNodes.length; index++) {
var row = tableRow.childNodes[index];
if (row.style) {
row.style.backgroundColor = "white";
}
}
}
Example: http://jsfiddle.net/9nh9a/
Though practically speaking, wouldn't it be simpler to just bind your listener to the <tr> elements instead of the <td> elements? Is there some reason you want to listen only on the <td> elements?
<style type="text/css">
.table1 tr:hover td{
background-color:#ccc;
}
</style>
<table class="table1">
<tr>
<td>cell 1-1</td>
<td>cell 1-2</td>
<td>cell 1-3</td>
<td>cell 1-4</td>
</tr>
<tr>
<td>cell 2-1</td>
<td>cell 2-2</td>
<td>cell 2-3</td>
<td>cell 2-4</td>
</tr>
<tr>
<td>cell 2-1</td>
<td>cell 2-2</td>
<td>cell 2-3</td>
<td>cell 2-4</td>
</tr>
</table>
$(selector).mouseenter(handlerIn).mouseleave(handlerOut);
You can use code like this:
HTML
<table>
<tr>
<td>cell1,1</td>
<td>cell1,2</td>
<td>cell1,3</td>
</tr>
<tr>
<td>cell2,1</td>
<td>cell2,2</td>
<td>cell2,3</td>
</tr>
</table>
Style sheet
.hover {
background-color: silver;
}
JavaScript
$("td").hover(
function () {
$(this).parent("tr").addClass("hover");
},
function () {
$(this).parent("tr").removeClass("hover");
}
);
The .hover class obviously can be styled as you like.
Regards and happy coding!
In jQuery:
$('td').mouseover(function( obj ) {
$(obj).parent().children().css("background-color","green");
});
$('td').mouseout(function( obj ) {
$(obj).parent().children().css("background-color","red");
});
Or in Javascript:
var tds = document.getElementsByTagName( "td" );
for( var i = 0; i < tds.length; i++ ) {
tds[i].addEventListener("mouseover",function(){
var children = this.parentNode.getElementsByTagName("td");
for( var j = 0; j < children.length; j++ )
children[j].style.background-color = "green";
});
tds[i].addEventListener("mouseout",function(){
var children = this.parentNode.getElementsByTagName("td");
for( var j = 0; j < children.length; j++ )
children[j].style.background-color = "red";
});
}
When I did it in all java script I did it like this
<!DOCTYPE html>
<html>
<head>
<title>Chapter 11 Problem 1</title>
<script>
function blueText()
{
var paragraphObject = document.
getElementById("Paragraph");
paragraphObject.style.color = 'blue',
paragraphObject.style.background= 'white';
}
function whiteText()
{
var paragraphObject = document.
getElementById("Paragraph");
paragraphObject.style.color = 'white',
paragraphObject.style.background = 'blue';
}
</script>
</head>
<body>
<p id="Paragraph" style = "color:white; background-color:blue";
onmouseover="blueText()" onmouseout="whiteText()">
Paragraph Text
</p>
</body>
</html>
I really hope this doesn't garble it all up