I have a table and I need to group columns. How is it possible with HTML to tell if columns belong together? I've been looking at colgroup, but I don't know if that's what I need.
I need to create a function with jquery which works somehow like Microsoft Excel's group function, so I can hide unused columns and only show the relevant columns, but also the option to show the other columns.
Take a look at the jqGrid demos. It has functionality for grouping columns and, I believe (at least for older versions) also hiding them.
You could try something like this...
HTML
<table>
<tr>
<td>
First Name
</td>
<td>
Middle Initial
</td>
<td>
Last Name
</td>
</tr>
<tr>
<td>
John
</td>
<td>
C
</td>
<td>
Doe
</td>
</tr>
<tr>
<td>
Jim
</td>
<td>
D
</td>
<td>
Doe
</td>
</tr>
<tr>
<td>
Jane
</td>
<td>
E
</td>
<td>
Doe
</td>
</tr>
</table>
<a onclick="javascript:hideColumn('first')">Hide First Name</a>
<a onclick="javascript:hideColumn('middle')">Hide Middle Initial</a>
<a onclick="javascript:hideColumn('last')">Hide Last Name</a>
JavaScript
<script type="text/javascript">
function hideColumn(column) {
var row = [];
var dataCell = [];
switch (column) {
case 'first': {
var a = document.getElementsByTagName('a');
if(a[0].innerHTML == "Hide First Name")
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[0].style.visibility = "hidden";
}
a[0].innerHTML = "Show First Name";
}
else
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[0].style.visibility = "visible";
}
a[0].innerHTML = "Hide First Name";
}
break;
}
case 'middle': {
var a = document.getElementsByTagName('a');
if(a[1].innerHTML == "Hide Middle Initial")
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[1].style.visibility = "hidden";
}
a[1].innerHTML = "Show Middle Initial";
}
else
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[1].style.visibility = "visible";
}
a[1].innerHTML = "Hide Middle Initial";
}
break;
}
case 'last': {
var a = document.getElementsByTagName('a');
if(a[2].innerHTML == "Hide Last Name")
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[2].style.visibility = "hidden";
}
a[2].innerHTML = "Show Last Name";
}
else
{
row = document.getElementsByTagName('tr');
for(var i = 0; i < row.length; i++){
dataCell = row[i].getElementsByTagName('td');
dataCell[2].style.visibility = "visible";
}
a[2].innerHTML = "Hide Last Name";
}
break;
}
}
}
</script>
Since you want to group items by the columns they are in, they will always be in the same spot in the row. There is probably a better/less hardcoded way to do this. But hopefully this example will help.
Related
This question already has answers here:
Why does firstChild not return the first element?
(5 answers)
Closed 5 years ago.
I am trying to deleted selected or all rows using pure javascript. I am unable to delete selected rows. what was the issue in my fiddle
Edit: First row is header so not considering that.
document.getElementById("delete").addEventListener("click", function() {
var tableRef = document.getElementById('links-list');
var tableRows = document.getElementById("links-list").rows;
var checkedIndexes = [];
for (var i = 1; i < tableRows.length; i++) {
var checkboxSelected = tableRows[i] && tableRows[i].cells[0].firstChild.checked;
if (checkboxSelected) {
checkedIndexes.push(i);
}
}
for (var k = 0; k < checkedIndexes.length; k++) {
tableRef.deleteRow(checkedIndexes[k]);
}
});
This sould be something like the one below, with tableRows[i].querySelector('input').checked, as .firstChild is a textnode. Also, index of tableRows starts with 0.
document.getElementById('delete').addEventListener('click', function() {
var tableRef = document.getElementById('links-list');
var tableRows = document.getElementById('links-list').rows;
var checkedRows = [];
for (var i = 0; i < tableRows.length; i++) {
if (tableRows[i].querySelector('input').checked) {
checkedRows.push(tableRows[i]);
}
}
for (var k = 0; k < checkedRows.length; k++) {
checkedRows[k].parentNode.removeChild(checkedRows[k]);
}
});
As the last loop alters the dom, deleting based on indexes is not reliable when multiple rows are deleted in the same time. So instead of the pure indexes, it should iterate through the actual nodes.
You can use the document.querySelectorAll method with the proper css selector to get all the checkboxes that are checked. Then from the table you can remove those rows with checked checkboxes.
let tableRef = document.getElementById('links-list');
let tbody = tableRef.querySelector("tbody");
let checkedInputs = document.querySelectorAll("input[type='checkbox']:checked");
Array.prototype.slice.call(checkedInputs)
.forEach( input => tbody.removeChild(input.parentNode.parentNode))
Can also be writen with es7 syntax like this
[...checkedInputs].forEach( input => tbody.removeChild(input.parentNode.parentNode))
Use the children property instead of the firstChild one. Also you can enhance your code by avoiding element recalculation. For example, you already found the table, so get the row from it.
Also when you're removing rows, start from the end and go up.
document.getElementById("delete").addEventListener("click", function() {
var tableRef = document.getElementById('links-list');
var tableRows = tableRef.rows;
var checkedIndexes = [];
for (var i = 0; i < tableRows.length; i++) {
var checkboxSelected = tableRows[i].cells[0].children[0].checked;
if (checkboxSelected) {
checkedIndexes.push(i);
}
}
for (var k = checkedIndexes.length - 1; k >= 0; k--) {
tableRef.deleteRow(checkedIndexes[k]);
}
});
<table id="links-list">
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test1
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test2
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test3
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test4
</td>
</tr>
<tr>
<td>
<input type=checkbox>
</td>
<td>
Test5
</td>
</tr>
</table>
<input type=button value="delete" id="delete">
You have 2 errors, first you are not getting the value correctly; secondly, you are deleting in the list that you are iterating, so you need to fix that. Try this:
document.getElementById("delete").addEventListener("click", function() {
var tableRef = document.getElementById('links-list');
var tableRows = document.getElementById("links-list").rows;
var checkedIndexes = [];
for (var i = 1; i < tableRows.length; i++) {
var checkboxSelected = tableRows[i] && tableRows[i].cells[0].firstElementChild.checked;
if (checkboxSelected) {
checkedIndexes.push(i);
}
}
for (var k = 0; k < checkedIndexes.length; k++) {
tableRef.deleteRow(checkedIndexes[k]-k);
}
});
fiddle
i am developer for android web App.
i using javascript interface on Android Webview.
so that, i have some problem.
how to convert html table with only javascript?
<table>
<tr>
<td> <input type=button value='test'> </input>
</td>
<td> <form> <h1> test heading </h1> </form>
</td>
<tr>
<h1> heading 2 </h1>
</tr>
<tr>
<div>
<table>
<tr>
<td> td1 </td>
<td> td2 </td>
<td> td3 </td>
</tr>
</table>
</div>
</tr>
and Javascript Code
var table_index = 0;
function node_init() {
var nodes = document.body.children;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
if (node.tagName == 'TABLE') {
node_init_table_name(node, ++table_index);
}
}
}
function node_init_table_name(table, index) {
table.setAttribute('node_tableName', 'table ' + index);
var cellIndex = 0;
for (var row = 0; row < table.rows.length; row++) {
for (var column = 0; column < table.rows[row].cells.length; column++) {
var cell = table.rows[row].cells[column];
cell.setAttribute('cellName', cellIndex++);
if (cell.childElementCount > 0) {
var nodes = cell.children;
var inner_table_index = 0;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
if (node.hasChildNodes()) {
han_initChildNodes(node);
var pNode = node.parentNode;
if (pNode) {
var hasChild = node.getAttribute('child');
var focusChild = node.getAttribute('current_child');
pNode.setAttribute('child', hasChild);
pNode.setAttribute('current_child', focusChild);
}
}
if (node.tagName == 'TABLE') {++inner_table_index;
var inner_index = index + "-" + inner_table_index;
han_init_table_name(node, inner_index);
}
}
}
}
}/* end for*/
table.setAttribute('cellCount', cellIndex);
}
I have a DataTable that stores names only. I want to have a button that will add all the names in the DataTable to an text input field.
<div id="myTabDiv">
<table name="mytab" id="mytab1">
<thead>
<tr>
<th>name</th>
</tr>
</thead>
<tbody>
<tr>
<td>chris</td>
</tr>
<tr>
<td>mike</td>
</tr>
</tbody>
</table>
<button id="add" >ADD</button>
<input type="text" id="text">
</div>
After click the "add" button, I want the names to appear in the text field separated by a comma.
And if possible, If the button is clicked again, remove the names?
I created the whole solution on codepen. This is the function used:
var clicks = 0;
function csv() {
var box = document.getElementsByName('text')[0];
if(clicks === 0){
var newcsv = "";
var tds = document.getElementsByTagName("TD");
for(var i = 0; i < tds.length; i++)
{
newcsv += tds[i].innerHTML;
if(i != tds.length-1) newcsv += ",";
}
box.value = newcsv;
clicks++;
}
else{
clicks = 0;
box.value = "";
}
}
This is bound to onclick event of a button.
Assign id to input
<input type=text id="textbox"/>
Just loop though table
var table = document.getElementById("mytab1");
var textbox=document.getElementById("textbox")
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
if(textbox.value=="")
{
textbox.value=row.cells[j].innerText;
}
else
{
textbox.value+= textbox.value+','+row.cells[j].innerText;
}
}
}
I am writing up an webpage to display a table with 2 columns and two rows(header and body).
I would like to control the show and hide of any of this 2 columns with Javacript.
The hide and display should be determined by the value of "input1" and"input2" from server.
If "input1"="empty"(string), hide colomn1(col1). Otherwise, display it.
Similar logic applying to "input2" and "col2"
I printed the value "input1" in the webpage and confirmed it is equal to "empty". However, the "col1" is still in the table displayed.
Can anyone point out the problem? If my approach is incorrect, please advise what is the best alternative.
<table>
<tr>
<th class="col1">Genus</th>
<th class="col2">Species</th>
</tr>
<tr>
<td class="col1">column1</td>
<td class="col2">column2</td>
</tr>
</table>
<script type="text/javascript">
function check()
{
if({{input1}}=="empty")
document.getElementByID("col1").style.display = "none";
else
document.getElementByID("col1").style.display = "block";
if({{input2}}=="empty")
document.getElementByID("col2").style.display = "none";
else
document.getElementByID("col2").style.display = "block";
}
</script>
I can see two big mistakes over there:
The method "getElementById" will not work since you're not selecting an element by its id, you're selecting it by its class. How to do that? I'll suggest you to download the jQuery library ( http://jquery.com/ ) and then search how to select elements by its class name. jQuery is, in some way, a javascript wrapper that will make your life much easier :)
Setting the "display" property to "none" should hide it, but setting if to "block" will probably screw the table up. You should either set it to "table-cell" or "table-header-group" depending on if it's td or th. I suggest you look at the documentation of the display property: http://www.w3schools.com/cssref/pr_class_display.asp
I hope it helped :)
EDIT: if you don't want to use jquery, check at this post: How to Get Element By Class in JavaScript?
Yes, it can be done. Here's a quick example: http://jsfiddle.net/vZB5k/
<body>
<table>
<tr>
<th class="col1">Genus</th>
<th class="col2">Species</th>
</tr>
<tr>
<td class="col1">
column1
</td>
<td class="col2">
column2
</td>
</tr>
</table>
<input type="button" id="hideCol1" value="Hide Column 1" />
<input type="button" id="hideCol2" value="Hide Column 2" />
<input type="button" id="hideBoth" value="Hide Both" />
<input type="button" id="showAll" value="ShowAll" />
<script>
var hideCol1 = function () {
var e = document.getElementsByClassName("col1");
for (var i = 0; i < e.length; i++) {
e[i].style.display = "none";
}
};
var hideCol2 = function () {
var e = document.getElementsByClassName("col2");
for (var i = 0; i < e.length; i++) {
e[i].style.display = "none";
}
};
var hideBoth = function () {
hideCol1();
hideCol2();
};
var showAll = function () {
var e = document.getElementsByClassName("col1");
for (var i = 0; i < e.length; i++) {
e[i].style.display = "table-cell";
};
e = document.getElementsByClassName("col2");
for (var i = 0; i < e.length; i++) {
e[i].style.display = "table-cell";
};
};
(function () {
document.getElementById("hideCol1").addEventListener("click", hideCol1);
document.getElementById("hideCol2").addEventListener("click", hideCol2);
document.getElementById("hideBoth").addEventListener("click", hideBoth);
document.getElementById("showAll").addEventListener("click", showAll);
})();
</script>
</body>
Updated - using "input" variables:
var hideCol1 = function () {
var e = document.getElementsByClassName("col1");
for (var i = 0; i < e.length; i++) {
e[i].style.display = "none";
}
};
var hideCol2 = function () {
var e = document.getElementsByClassName("col2");
for (var i = 0; i < e.length; i++) {
e[i].style.display = "none";
}
};
(function () {
if (input1 !== "on") {
hideCol1();
}
if (input2 !== "on") {
hideCol2();
}
})();
This should do the trick
<script>
function hideCol() {
if (document.getElementById("txt1").value != "") {
var elements = document.getElementsByClassName('col1')
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = 'none';
}
}
if (document.getElementById("txt2").value != "") {
var elements = document.getElementsByClassName('col2')
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = 'none';
}
}
}
</script>
check out this fiddle
update the code as per your requirement .. but it has code to select the elements to be hidden.
Edit 1
Here is the new fiddle
have made to work according to checkboxes
function hidecol() {
if (document.getElementById("txt1").checked) {
var elements = document.getElementsByClassName('col1')
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = 'none';
}
}
if (document.getElementById("txt2").checked) {
var elements = document.getElementsByClassName('col2')
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = 'none';
}
}
}
please let me know if this was helpful
I am trying on following code;
Why doesn't deleteRow() alert "hi" when we click on delete button for first time (nor it delete row)?
Surprisingly it will work perfectly second time.
HTML
<div style="height: 190px;overflow: auto;left:220px;width:710px;" id="filterTable">
<table id="filterTableBody" style="border-collapse: collapse; border: 1px solid black;width:690px;" border="1">
<tbody><tr bgcolor="#FF6600">
<td><strong>
and/or
</strong></td>
<td><strong>
Column Name
</strong></td>
<td><strong>
operator
</strong></td>
<td><strong>
Filter
</strong></td>
<td><strong>
Delete
</strong></td>
</tr>
<tr><td> </td><td>WORKGROUP_NAME</td><td>!=</td><td>ABDEL HAMEID</td><td><img src="/images/delete.gif"></td></tr></tbody></table>
</div>
Javascript
function deleteRow(){
var table = document.getElementById('filterTableBody');
var rows1 = table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
for (var i = 0; i < rows1.length; i++) {
rows1[i].onclick = (function() {
alert("hi");
table.deleteRow(this.rowIndex);
var oTable = document.getElementById('filterTableBody');
//gets rows of table
var rowLength = oTable.rows.length;
for (i = 1; i < rowLength; i++){
var oCells = oTable.rows.item(i).cells;
//gets cells of current row
var cellLength = oCells.length-1;
for(var j = 0; j < cellLength; j++){
oCells.item(j).innerHTML = "";
break;
}
break;
}
});
}
}
Why doesn't the code run in first click and why it runs in the second?
The reason is because the onclick event handler for the rows are getting attached only when the Delete button is clicked for the first time.
They have to be attached onload itself. You can do it like below:
window.onload = deleteRow;
Demo Fiddle
This code works for me. Thank you #harry for pin pointing the problem.
function deleteRowUI(btndel) {
var table=document.getElementById('filterTableBody');
if (typeof(btndel) == "object") {
p=btndel.parentNode.parentNode;
p.parentNode.removeChild(p);
var oTable = document.getElementById('filterTableBody');
//gets rows of table
var rowLength = oTable.rows.length;
for (var i = 1; i < rowLength; i++){
var oCells = oTable.rows.item(i).cells;
//gets cells of current row
var cellLength = oCells.length-1;
for(var j = 0; j < cellLength; j++){
oCells.item(j).innerHTML = "";
break;
}
break;
}
} else {
return false;
}
}