I am trying to show/hide rows in a HTML table by javascript. Checking the check box shall show the additional rows, unchecking it shall hide them.
<html><body><form><table>
<tr>
<td> This row is always visible. </td>
</tr>
<tr>
<td>
<input id="cbox" type="checkbox" onchange="for(e in document.getElementsByClassName('switchMe')) e.style.display = document.getElementById('cbox').checked ? 'block' : 'none';"/>
<label for="cbox">Show more …</label>
</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td> This row will be shown after the user clicks the check box. </td>
</tr>
<tr class="switchMe" style="display: none; ">
<td> This row too. </td>
</tr>
<tr>
<td> This row is always visible. </td>
</tr>
</table></form></body></html>
However, nothing happens, and I get an e.style is undefined error in the console. How do I access the style attribute of the <tr> element correctly?
(I first tried putting the rows in question in a <div>. That doesn’t give any error, but the rows are always visible, and the <div> is absent in Firebug, so it is probably not allowed there.)
First, for..in is ideal for iterating over objects but not on NodeList.
Second, its a bad practice to have change event listener in html. Anyone can change markup using dev tools and manipulate behaviour of your system. You should use .addEventListener
Third, defining a variable without var will make it global.
Output of for..in
var el_list = document.querySelectorAll('.switchMe');
for(var el in el_list){
console.log(el)
}
<form>
<table>
<tr>
<td>This row is always visible.</td>
</tr>
<tr>
<td>
<input id="cbox" type="checkbox" />
<label for="cbox">Show more …</label>
</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row will be shown after the user clicks the check box.</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row too.</td>
</tr>
<tr>
<td>This row is always visible.</td>
</tr>
</table>
</form>
Sample
JSFiddle
document.querySelector('#cbox').addEventListener('click', function(e) {
var switchEl = document.querySelectorAll('.switchMe');
for (var i = 0; i < switchEl.length; i++)
switchEl[i].style.display = this.checked ? 'block' : 'none';
});
<form>
<table>
<tr>
<td>This row is always visible.</td>
</tr>
<tr>
<td>
<input id="cbox" type="checkbox" />
<label for="cbox">Show more …</label>
</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row will be shown after the user clicks the check box.</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row too.</td>
</tr>
<tr>
<td>This row is always visible.</td>
</tr>
</table>
</form>
You are having an issue with the use of the for...in loop. This isn't really the loop that you should choose for an Array or an (Array like) object, they should only be used for iterating through object keys and properties as they are very slow on array's where there are much faster methods available.
for...in also modifies state so you should have that available eg.
const thing = { one: 1, two: 2 }
for (key in thing) {
console.log(thing[key])
}
You are referencing the thing from the outer scope inside the loop
I Think this is a better way as you are not dealing with any external state when you do your iteration.
const rows = Array.from(document.getElementsByClassName('switchMe'))
const cbox = document.getElementById('cbox')
function changeHandler() {
rows.forEach(row => {
row.style.display = cbox.checked ? 'block' : 'none'
})
}
<html>
<body>
<form>
<table>
<tr>
<td>This row is always visible.</td>
</tr>
<tr>
<td>
<input id="cbox" type="checkbox" onchange="changeHandler()" />
<label for="cbox">Show more …</label>
</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row will be shown after the user clicks the check box.</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row too.</td>
</tr>
<tr>
<td>This row is always visible.</td>
</tr>
</table>
</form>
</body>
</html>
One way to implement what you were trying to do without creating a function as the other answers did would be to do it as shown below.
However this doesn't mean you should do it this way. In practice definitely use the other answers shown.
<html>
<body>
<form>
<table>
<tr>
<td>This row is always visible.</td>
</tr>
<tr>
<td>
<input id="cbox" type="checkbox" onchange="var arr = document.getElementsByClassName('switchMe'); for(var i = 0; i < arr.length; i++) arr[i].style.display = document.getElementById('cbox').checked ? 'block' : 'none';" />
<label for="cbox">Show more …</label>
</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row will be shown after the user clicks the check box.</td>
</tr>
<tr class="switchMe" style="display: none; ">
<td>This row too.</td>
</tr>
<tr>
<td>This row is always visible.</td>
</tr>
</table>
</form>
</body>
</html>
Related
I have a table. This is the sample code for it.
<table>
<thead>
<tr>
<td>filename</td>
<td>file size</td>
<td>date</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox">
file 1
</td>
<td>
1MB
</td>
<td>
13-01-12
</td>
</tr>
<tr>
<td>
<input type="checkbox">
file 2
</td>
<td>
2MB
</td>
<td>
23-12-17
</td>
</tr>
</tbody>
</table>
I have a check box input at each row to select multiple tr in tables. I also need to get redirected to the detail view of the file onclick. so, this is my JS code
$(document).on("click", "table tbody tr", function() {
window.location = $(this).data('href');
});
Now whenever I am trying to click the check box the tr is getting clicked. So, the page is getting redirected to another page. But select is not working. How to prevent page redirection on clicking on select.
Thanks in advance
UPDATE::
I want to implement functionality like Inbox mails in gmail. Whenever I click on any of the mail, it gets opened. If I check the checkbox the corresponding mail will be selected.
When an element is clicked, it bubbles up to the highest point in the DOM which has a click event attached. To prevent your checkboxes from triggering the click event on your <tr>'s, you need to stop the 'bubbling'.
Add this to your code:
$('input:checkbox').on("click", function(e){
e.stopPropagation();
});
Source: How do I prevent a parent's onclick event from firing when a child anchor is clicked?
Since the checkbox is a child of the table row, when you click the checkbox the click event is propagated up the DOM. This means it bubbles up to all its parent elements as well, and any click events defined on those parents are also triggered.
Therefore, the click event you placed on the table row is also executed when you click on the checkbox.
Fortunately, you can prevent this by handling the checkbox's click event and running the stopPropagation method, which turns off this "bubbling" behaviour.
Demo:
$(document).on("click", "table tbody tr", function() {
alert("click"); //just for testing
//window.location = $(this).data('href');
});
$(document).on("click", 'input[type="checkbox"]', function(event) {
event.stopPropagation();
});
table {
border-collapse: collapse;
}
th,
td {
border: 1px solid #cccccc;
padding 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td>filename</td>
<td>file size</td>
<td>date</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox"> file 1
</td>
<td>
1MB
</td>
<td>
13-01-12
</td>
</tr>
<tr>
<td>
<input type="checkbox"> file 2
</td>
<td>
2MB
</td>
<td>
23-12-17
</td>
</tr>
</tbody>
</table>
use Event.Target
document.querySelector("table")
.addEventListener("click" , event=>{
if(( event.target ).tagName == "TD" || ( event.target ).tagName == "TR" ){
alert("redirect")
}
if(( event.target ).tagName == "INPUT" ){
alert("select")
}
})
<table>
<thead>
<tr>
<td>filename</td>
<td>file size</td>
<td>date</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox">
file 1
</td>
<td>
1MB
</td>
<td>
13-01-12
</td>
</tr>
<tr>
<td>
<input type="checkbox">
file 2
</td>
<td>
2MB
</td>
<td>
23-12-17
</td>
</tr>
</tbody>
</table>
Try following code:
<table>
<thead>
<tr>
<td>filename</td>
<td>file size</td>
<td>date</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox">
file 1
</td>
<td>
1MB
</td>
<td>
13-01-12
</td>
</tr>
<tr>
<td>
<input type="checkbox">
file 2
</td>
<td>
2MB
</td>
<td>
23-12-17
</td>
</tr>
</tbody>
</table>
I want to select all first td values using JQuery.
Here is my code:
<tr id="#ASPxGridView1_DXHeadersRow0">
<td id="ASPxGridView1_col0" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;">
<table style="width:100%;">
<tbody>
<tr>
<td>Status</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
<td id="ASPxGridView1_col1" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;">
<table style="width:100%;">
<tbody>
<tr>
<td>Worksheet ID</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
</tr>
I want to get only 2 td (Status.Worksheet ID) elements from my above code using JQuery
You can pass any valid CSS selector to JQuery, so all you need is:
$("td:first-child");
// This will find and group together all the `<td>` elements that are the first ones
// within their parent (<tr>).
var $results = $("td:first-child");
// You can loop over the set and work with the individual DOM elements...
$results.each(function(index, result){
// result is the DOM element we're looping over
console.log(result.textContent);
});
// Or, you can access a specific element by index:
console.log($results[0].textContent + ", " + $results[1].textContent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<tr id="#ASPxGridView1_DXHeadersRow0">
<td id="ASPxGridView1_col0" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;"><table style="width:100%;">
<tbody>
<tr>
<td>Status</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
<td id="ASPxGridView1_col1" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;">
<table style="width:100%;">
<tbody>
<tr>
<td>Worksheet ID</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
</tr>
I have a code which gets one of input's to show/hide some information when it's chosen.
$("input[name$='payment']").click(function() {
Everything works as it should, however, my website let's user to click whole table element to tick the input.
How can I tell jQuery to choose whole element, not only the small input ticker if my code looks like this:
<table cellspacing="0">
<tbody><tr class="moduleRowSelected" onmouseover="rowOverEffect(this)"">
<td width="10"><img src="cat/pixel_trans.gif" width="10"></td>
<td class="main"><b>Name of payment</b></td>
<td class="main"><input name="payment" value="importantpaymentwithexternalinformation" type="radio"> </td>
You can target the tables containing those elements using .closest("table"):
$("input[name$='payment']").closest("table").click(function() {
// ------------------------^^^^^^^^^^^^^^^^^
Within the click handler, this will refer to the table. Since a user clicking the table may not click the radio button, you'll want to include code to do that for them:
$(this).find("input[name$='payment']").prop("checked", true);
Example:
$("input[name$='payment']").closest("table").click(function() {
$(this).find("input[name$='payment']").prop("checked", true);
});
<table cellspacing="0">
<tbody>
<tr class="moduleRowSelected">
<td width="10"><img src="cat/pixel_trans.gif" width="10"></td>
<td class="main"><b>Name of payment</b></td>
<td class="main"><input name="payment" value="type1" type="radio"> Type 1</td>
</tr>
</tbody>
</table>
<table cellspacing="0">
<tbody>
<tr class="moduleRowSelected">
<td width="10"><img src="cat/pixel_trans.gif" width="10"></td>
<td class="main"><b>Name of payment</b></td>
<td class="main"><input name="payment" value="type2" type="radio"> Type 2</td>
</tr>
</tbody>
</table>
<table cellspacing="0">
<tbody>
<tr class="moduleRowSelected">
<td width="10"><img src="cat/pixel_trans.gif" width="10"></td>
<td class="main"><b>Name of payment</b></td>
<td class="main"><input name="payment" value="type3" type="radio"> Type 3</td>
</tr>
</tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This is my FIDDLE
<table>
<tr>
<td>
<div style="background:blue;color:white">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:pink;color:white">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:blue;color:white">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:green;color:white">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:pink;color:white">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:green;color:white">hello</div>
</td>
</tr>
</table>
How do i rearrange the html table rows based on color? I want to group html table rows based on the background color of the rows.
Use sort() to sorting array of tr elements. You can get backgroud-color of element in function of sort and set arrangement of every element.
$("table tr").sort(function (a, b){
return $("div", b).css("background") < $("div", a).css("background") ? 1 : -1;
}).appendTo('table');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<div style="background:blue">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:pink">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:blue">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:green">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:pink">hello</div>
</td>
</tr>
<tr>
<td>
<div style="background:green">hello</div>
</td>
</tr>
</table>
I reviewed your question, I think you want to differentiate each tr by there color, adding html, style and script for you here.
Here is the Html
<table>
</tbody>
<tr><td>123</td></tr>
<tr><td>123</td></tr>
<tr><td>123</td></tr>
<tr><td>123</td></tr>
<tr><td>123</td></tr>
</table>
Do add this script, by this function all your tr will have unique classes. you can add there background colors etc style on the base of class
<script>
// please do add jQuery file to prevent error
function adddClass() {
for(i=1; i<=6; i++) {
alert("");
jQuery('table tr:nth-child('+ i +')').addClass("color"+i);
}
}
adddClass();
</script>
Here is the style for background color of each table row tr
<style>
.color1{background-color:orange;}
.color2{background-color:teal;}
.color3{background-color:red;}
.color4{background-color:#717171;}
.color5{background-color:khaki;}
.color6{background-color:lightgray;}
tr, table, body{width:100%;}
</style>
Hope this will help, Thanks.!
You can easily do it in javascript.
Initiate an empty js object like this var colorRowmap = {}
Loop through all elements(tr elements) of table and get colorName from each tr. And if that color does not exist as a key of colorRowMap object do colorRowMap[colorName] = [currentTableRow] else do colorRowMap[colorName] = colorRowMap[colorName].push(currentTableRow)
Empty the table.
Loop through all keys of colorRowMap and push the tr roows to table.
Done. :)
I have an html table with cells that span multiple rows:
<table border="1" style=""><tbody id="x">
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td rowspan="3">**</td>
<td>AAAA</td>
<td> </td>
</tr>
<tr id="row2">
<td>BBBB</td>
<td> </td>
</tr>
<tr>
<td>CCCC</td>
<td> </td>
</tr>
<tr>
<td style=""> </td>
<td id="ee">EEEE</td>
<td> </td>
</tr>
<tr>
<td style=""> </td>
<td id="dd">DDDD</td>
<td> </td>
</tr>
</tbody></table>
<script type="text/javascript">
alert ("index of dd before delete =" + document.getElementById("dd").cellIndex);
document.getElementById("row2").style.display="none";
alert ("index of dd after delete =" + document.getElementById("dd").cellIndex);
</script>
I am trying to manipulate it in Javascript, eg hide row2.
When I do that, the multi-row cell containing "**" moves down, shifting all the cells in row 3 by 1 to the right. Evidently I have to reduce its rowSpan.
But it seems when I am looking at row 1, I have no way of knowing that there is a multi-row cell intersecting this row - it seems I have to scan all the rows above row2 for multi-row cells.
Is there a better/quicker way to find out what multi-row cells affect the hiding (or deleting) operation?
Try this using javascript... It is working properly.
Change the value of currRowToDelete for Range [1 to 6].
Refer for working code: http://jsfiddle.net/arunkumrsingh/cdS2D/1/
<table id="tbl" border="1" runat="server" >
<tr id="row1">
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr id="row2">
<td rowspan="3">**</td>
<td>AAAA</td>
<td> </td>
</tr>
<tr id="row3">
<td>BBBB</td>
<td> </td>
</tr>
<tr id="row4">
<td>CCCC</td>
<td> </td>
</tr>
<tr id="row5">
<td style=""> </td>
<td id="ee">EEEE</td>
<td> </td>
</tr>
<tr id="row6">
<td style=""> </td>
<td id="dd">DDDD</td>
<td> </td>
</tr>
</table>
<script type="text/javascript">
var trs = document.getElementById("tbl").getElementsByTagName("tr");
var tds;
var bDeleted = false;
var currRowToDelete = 3;
for(var i=0;i<currRowToDelete;i++)
{
tds = trs[i].getElementsByTagName('td');
for(var j=0;j<tds.length;j++)
{
var currRowSpan = tds[j].rowSpan;
if(currRowSpan > 1)
{
if(eval(i + 1) == currRowToDelete)
{
var cell = document.createElement("td");
cell.innerHTML = tds[j].innerHTML;
trs[i + 1].insertBefore(cell, trs[i + 1].getElementsByTagName('td')[0]);
document.getElementById("tbl").deleteRow(i);
bDeleted = true;
document.getElementById("tbl").rows[i].cells[0].rowSpan = eval(currRowSpan -1);
}
else
{
if(eval(currRowSpan + i) >= currRowToDelete)
document.getElementById("tbl").rows[i].cells[0].rowSpan = eval(currRowSpan -1);
}
}
}
}
if(bDeleted == false)
document.getElementById("tbl").deleteRow(currRowToDelete -1);
</script>
I have a solution, in which you don't have to calculate the Rowspan and Colspan.
Step 1: Get the content of HTML (As mentioned above) and save as EXCEL file.
Step 2: Delete the particular Row (ie Row 2).
Step 3: Save as HTML file and Read the HTML content.
You will get the HTML in correct format.