I have done the component with table like this.
The problem is, when user chooses a range of cell like this, how can i put the border around that groups( the border likes the first one in group of cells) ?
I tried to use different class for each cell's border style, but it seems imposible, because i dont know which cell user will pick, how big the group of cell's size will be
Thank a lot and sorry about my English
Had the same task this week and sadly the question did not hold any answer, except for external libraries. So here is my approach.
In the following example I am using the class Marked to mark the cells as being selected and the dataset to flag which cells define which outer bound(s).
;window.onload = (event) => {
//REM: Assign mousedown event
document.querySelector('table').addEventListener('mousedown',_onMouseDownTable, false)
};
/***
* MouseDown event for the table, handles cells
*/
function _onMouseDownTable(event){
//REM: Checking for 'td'...
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
const tObject = {Down: event.target};
//REM: ...add event for marking cells
this.onmousemove = ((object, event) => {
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
object.Move = event.target
}
else{
delete object.Move
};
_markCells(object.Down, object.Move)
}).bind(null, tObject);
//REM: ...add event for finish marking cells
this.onmouseleave = this.onmouseup = ((object, event) => {
this.onmouseleave = this.onmousemove = this.onmouseup = null;
}).bind(null, tObject)
}
};
/***
* Marks cells between cell a and cell b
*/
function _markCells(a, b){
if(a && b){
//REM: Table of a (thus usually b)
const tTable = a.closest('table');
//REM: Remove existing marks and border data
tTable.querySelectorAll('td.Marked, td[data-bounds-left], td[data-bounds-right], td[data-bounds-top], td[data-bounds-bottom]').forEach((td) => {
td.classList.remove('Marked');
delete td.dataset.boundsLeft;
delete td.dataset.boundsRight;
delete td.dataset.boundsTop;
delete td.dataset.boundsBottom
});
//REM: The lowest (top to bottom / left to right) and the largest coordinate
const
tMaxColumn = Math.max(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMaxRow = Math.max(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex)),
tMinColumn = Math.min(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMinRow = Math.min(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex));
//REM: Mark all cells between Min and Max
for(let row = tMinRow; row <= tMaxRow; row++){
for(let column = tMinColumn; column <= tMaxColumn; column++){
const tCell = tTable.querySelector(`td[data-row-index='${row}'][data-column-index='${column}']`);
if(tCell){
//REM: If outer left bound...
if(column === tMinColumn){
tCell.dataset.boundsLeft = true
};
//REM: If outer right bound...
if(column === tMaxColumn){
tCell.dataset.boundsRight = true
};
//REM: If outer top bound...
if(row === tMinRow){
tCell.dataset.boundsTop = true
};
//REM: If outer bottom bound...
if(row === tMaxRow){
tCell.dataset.boundsBottom = true
};
//REM: Set cell as marked
tCell.classList.add('Marked')
}
}
}
}
};
td{
border: 2px solid #000;
background-color: grey;
height: 25px;
width: 200px;
}
td.Marked{
background-color: #1e90ff
}
td.Marked[data-bounds-left]{
border-left-color: red
}
td.Marked[data-bounds-right]{
border-right-color: red
}
td.Marked[data-bounds-top]{
border-top-color: red
}
td.Marked[data-bounds-bottom]{
border-bottom-color: red
}
<table>
<tbody>
<tr>
<td data-column-index="0" data-row-index="0"></td>
<td data-column-index="1" data-row-index="0"></td>
<td data-column-index="2" data-row-index="0"></td>
<td data-column-index="3" data-row-index="0"></td>
<td data-column-index="4" data-row-index="0"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="1"></td>
<td data-column-index="1" data-row-index="1"></td>
<td data-column-index="2" data-row-index="1"></td>
<td data-column-index="3" data-row-index="1"></td>
<td data-column-index="4" data-row-index="1"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="2"></td>
<td data-column-index="1" data-row-index="2"></td>
<td data-column-index="2" data-row-index="2"></td>
<td data-column-index="3" data-row-index="2"></td>
<td data-column-index="4" data-row-index="2"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="3"></td>
<td data-column-index="1" data-row-index="3"></td>
<td data-column-index="2" data-row-index="3"></td>
<td data-column-index="3" data-row-index="3"></td>
<td data-column-index="4" data-row-index="3"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="4"></td>
<td data-column-index="1" data-row-index="4"></td>
<td data-column-index="2" data-row-index="4"></td>
<td data-column-index="3" data-row-index="4"></td>
<td data-column-index="4" data-row-index="4"></td>
</tr>
</tbody>
</table>
Note that this is just a draft and not a finished solution, since it depends heavily on the already existing implementation and use-case.
Related
I have an HTML table with like 7 columns. When I select a column I want all the other columns to be hidden except the column next to the selected one. To be clear, only 2 columns need to be visible at a time - and those are the one selected and the one next to it. If there is a column to the right of the selected column, this one should be shown along with the selected column, if not (last column selected) the column to the left shall be shown along with the selected one.
I tried using loops but the problem is the user can select any column from the table.
My code:
var I = document.getElementsByTagName("th").length;
if(s=== I-1) { // s - index of selected column- check if its the last column
for (var D = 0; D < I-2; D++) {
var o = datatable.column(D);
o.visible(!o.visible());
}
} else {
for (var D = 0; D < s; D++) {
var o = datatable.column(D);
o.visible(!o.visible());
}
for (var D = s+1; D < I; D++) {
var o = datatable.column(D);
o.visible(!o.visible());
}
}
My HTML:
<table id="DataTables_Table_0" >
<thead>
<tr role="row" style="height: 0px;">
<th>
<div>Pro</div>
</th>
<th>
<div>Pri</div>
</th>
<th>
<div>State</div>
</th>
<th>
<div>phyId</div>
</th>
<th>
<div>Title</div>
</th>
<th>
<div>Origin</div>
</th>
<th>
<div>type</div>
</th>
</tr>
</thead>
<tbody style="">
<tr role="row" class="odd">
<td class="0 sorting_1">Private</td>
<td class="1">High</td>
<td class="2">Create</td>
<td class="3">E210DC29509F</td>
<td class="4">5</td>
<td class="5">8/9/2019, 8:24:00 AM</td>
<td class="6">Issue</td>
</tr>
<tr role="row" class="even">
<td class="0 sorting_1">Public</td>
<td class="1">Low</td>
<td class="2">Assign</td>
<td class="3">E210DC29509F</td>
<td class="4">5</td>
<td class="5">8/9/2019, 9:11:11 AM</td>
<td class="6">Issue</td>
</tr>
<tr role="row" class="odd">
<td class="0 sorting_1">Private</td>
<td class="1">Medium</td>
<td class="2">Assign</td>
<td class="3">E210DC29509F</td>
<td class="4">5</td>
<td class="5">8/9/2019, 9:17:26 AM</td>
<td class="6">Issue</td>
</tr>
<tr role="row" class="even">
<td class="0 sorting_1">Public</td>
<td class="1">Urgent</td>
<td class="2">Active</td>
<td class="3">E210DC29509F</td>
<td class="4">5</td>
<td class="5">8/8/2019, 4:14:59 PM</td>
<td class="6">Issue</td>
</tr>
</tbody>
</table>
An update to the question: I can select the 1st column always alonwith the column selected by the user. So that means I dont have to manually select the adjacent column from the table. I just modified the code:
for (var D = 1; D < I/2 ; D++) {
if (D !== s ) {
var o = f.datatable.column(D);
o.visible(!o.visible());
}
}
Now it works as expected. Actually this was for generating a line chart for the table data. Now i get a line chart, but i am just confused as to if the line chart does look as expected. I mean I have attached a screenshot of my line chart, but it looks like ther is something more to do. Sorry for not mentioning about the line chart as i thought it would make the question more complicated and confusing.linechart tabledata for the line chart
How exactly should a line chart look with my table.
I would make those td class names more explicit, so they're clearly labeling columns (like col-0), and then query the DOM based on those.
On selection change:
Hide all the columns.
Get the index being selected.
Calculate the two column class names to show.
Query for those class names and show those DOM nodes.
Here's some (untested) example js:
$('th, td').hide();
// for the OP: make sure colIndex isn't the rightmost col
const selectedCol = 'col-' + colIndex;
const nextCol = 'col-' + (colIndex + 1);
$('.' + selectedCol).show();
$('.' + nextCol).show();
Get the count of all columns.
then hide all the columns.
and then only show the selected and next or previous column
var I = document.getElementsByTagName("th").length;
function hideCol(s){
datatable.columns( 'th' ).visible( false );
if(s == I-1){
datatable.column(s).visible(true);
datatable.column(s-1).visible(true);
}else if(s < I){
datatable.column(s).visible(true);
datatable.column(s+1).visible(true);
}
}
hideCol(2);
I have created table cells in html that have ids that increment by 1 for example: cell1, cell2, cell3, ......, cell100.
What I would like to do is loop through and get reference to each of these cells using a for loop because referencing them one by one won't be good pratice and will require alot of codes of line, instead of this;
var cell1 = document.getElementById('cell1');
var cell2 = document.getElementById('cell2');
var cell3 = document.getElementById('cell3');
......
var cell100 = document.getElementById('cell100');
Is it possible to do something like this?
for (i = 0; i<=100; i++) {
var cell+i = document.getElementById("cell"+i);
// then I can call individual cells and assign tasks to them something along the lines of;
cell1.addEventListener('input',function(){}
cell5.background = '#f5f5f5'
cell55.innerHTML = 'I am cell 55'
etc..
}
EDITED:
Incase it might be useful, I have 1 table that contains many cells of which some have ids and some don't. I would only like to reference the ones that do have ids.
you can use document.querySelectorAll with a wildcard
var slice = Array.prorotype.slice;
var selection = document.querySelectorAll("[id^=cell]");
slice.call(selection).forEach(function(item, index){
// here item is the table row and index is the iteration number of forEach
// to get the id
var id = item.id;
//to get the numerical value in id
var number_in_id = item.id.match(/\d+/g)[0];
})
document.querySelectorAll("[id^=cell]") selectects all elements that their id starts with the string cell if you want to make it specific for table td's you add document.querySelectorAll("td[id^=cell]")
may be you are looking for this
var grid = document.getElementById("grid");//grid is the id of the table
for (var i = 1, row; row = grid.rows[i]; i++)
row.cells[0].textContent = "";//content of the starts with row 1..2..3 and so one than cell[0] or cell[1] and so on.
It'd be good pratice to use classes, though;
In base of your loop, you can do it so to get the current element, but if you have an loop more longer than the amount of the elements id numbers sequence, then it will be returning errors.
var Cell=document.getElementById("cell"+i)
//you've your DOM element in the variable called Cell now
//the one error you did is in the variable name
//you used the + operator in the variable name;
That's equivalent to element with id "cell0" when it's the first execution time of the loop. Not too elegant, you've many other ways to do the same.
Yes, it is quite easy, see below.
var cells = [];
for (var i = 0; i <= 100; i++) {
cells[i] = document.getElementById("cell"+i);
// do stuff....
if( cells[55] ) {
cells[55].innerHTML = 'I am cell 55';
}
}
Consider you have a table with an ID as myTable.
Get the table with,,
var theTable = document.getElementById('myTable');
To get all <td>s you could do,
var cells = theTable.querySelectorAll('td');
Then do the looping part,
for(var i = 0; i < cells.length; i++){
if(cells[i].id && cells[i].id.indexOf('cell') != -1){ //added to get only the significant cells
//do your stuff
cells[i].addEventListener(function(){});
cells[i].innerHTML = 'Something';
}
}
I'm lazy and didn't want to hand code any table, so I made Demo 2:
A form that'll accept a number of rows and columns
Can create <tr> and append to a table (0 to 100 rows)
Can create <td> and append to a <tr>(0 to 100 columns)
Assigns a unique id to every <tr> and <td>
The id pattern allows a human reader to locate <tr>s and <td>s
Each id for the <td> are displayed in each cell.
There's also two arrays, one for the <tr>(rowX) and one for the <td>(colY). There's many powerful methods for Array and having those 2 arrays you could even make a two-dimensional array.
Concerning the OP's request specifically about an id for cells on a table (complete or partial), I am aware that you have a pre-made table, so I'll take the key lines that make it possible in Demo 2 to assign ids:
row.setAttribute('id', 'r' + r);// Each row will have a numbered id (ex. r0 is row 1)
col.setAttribute('id', 'r' + r + 'c' + c);// Each cell will have a numbered id representing it's location (ex. r3c0 is located on row 4 column 1)
Demo 1
This snippet is an adaptation of the code previously mentioned:
function oddRows() {
var rows = document.querySelectorAll('tr');
// rows is a NodeList (an array-like object).
// We can covert this NodeList into an Array.
var rowArray = Array.prototype.slice.call(rows);
//Either way, NodeList or Array should be iterated through a for loop (most common way to reiterate)
for (var i = 0; i < rowArray.length; i++) {
if (i % 2 === 1) {
console.log(i);
var odd = rowArray[i];
odd.style.display = "none";
//This filters and removes all odd numbered rows
}
}
return false;
}
function evenCols() {
var cols = document.querySelectorAll('td');
var colArray = Array.prototype.slice.call(cols);
for (var j = 0; j < colArray.length; j++) {
if (j % 2 === 0) {
console.log(j);
var even = colArray[j];
even.style.backgroundColor = "red";
//This filters even numbered <td> and colors the background red.
}
}
return false;
}
td {
border: 2px inset #777;
}
button {
margin: 20px 5px 10px;
}
<button id="btn1" onclick="oddRows();">Remove Odd Rows</button>
<button id="btn2" onclick="evenCols();">Mark Even Cols</button>
<table id="t1">
<tr id="r0" class="row">
<td id="r0c0" class="col">r0c0</td>
<td id="r0c1" class="col">r0c1</td>
<td id="r0c2" class="col">r0c2</td>
<td id="r0c3" class="col">r0c3</td>
<td id="r0c4" class="col">r0c4</td>
<td id="r0c5" class="col">r0c5</td>
<td id="r0c6" class="col">r0c6</td>
<td id="r0c7" class="col">r0c7</td>
<td id="r0c8" class="col">r0c8</td>
<td id="r0c9" class="col">r0c9</td>
</tr>
<tr id="r1" class="row">
<td id="r1c0" class="col">r1c0</td>
<td id="r1c1" class="col">r1c1</td>
<td id="r1c2" class="col">r1c2</td>
<td id="r1c3" class="col">r1c3</td>
<td id="r1c4" class="col">r1c4</td>
<td id="r1c5" class="col">r1c5</td>
<td id="r1c6" class="col">r1c6</td>
<td id="r1c7" class="col">r1c7</td>
<td id="r1c8" class="col">r1c8</td>
<td id="r1c9" class="col">r1c9</td>
</tr>
<tr id="r2" class="row">
<td id="r2c0" class="col">r2c0</td>
<td id="r2c1" class="col">r2c1</td>
<td id="r2c2" class="col">r2c2</td>
<td id="r2c3" class="col">r2c3</td>
<td id="r2c4" class="col">r2c4</td>
<td id="r2c5" class="col">r2c5</td>
<td id="r2c6" class="col">r2c6</td>
<td id="r2c7" class="col">r2c7</td>
<td id="r2c8" class="col">r2c8</td>
<td id="r2c9" class="col">r2c9</td>
</tr>
<tr id="r3" class="row">
<td id="r3c0" class="col">r3c0</td>
<td id="r3c1" class="col">r3c1</td>
<td id="r3c2" class="col">r3c2</td>
<td id="r3c3" class="col">r3c3</td>
<td id="r3c4" class="col">r3c4</td>
<td id="r3c5" class="col">r3c5</td>
<td id="r3c6" class="col">r3c6</td>
<td id="r3c7" class="col">r3c7</td>
<td id="r3c8" class="col">r3c8</td>
<td id="r3c9" class="col">r3c9</td>
</tr>
<tr id="r4" class="row">
<td id="r4c0" class="col">r4c0</td>
<td id="r4c1" class="col">r4c1</td>
<td id="r4c2" class="col">r4c2</td>
<td id="r4c3" class="col">r4c3</td>
<td id="r4c4" class="col">r4c4</td>
<td id="r4c5" class="col">r4c5</td>
<td id="r4c6" class="col">r4c6</td>
<td id="r4c7" class="col">r4c7</td>
<td id="r4c8" class="col">r4c8</td>
<td id="r4c9" class="col">r4c9</td>
</tr>
<tr id="r5" class="row">
<td id="r5c0" class="col">r5c0</td>
<td id="r5c1" class="col">r5c1</td>
<td id="r5c2" class="col">r5c2</td>
<td id="r5c3" class="col">r5c3</td>
<td id="r5c4" class="col">r5c4</td>
<td id="r5c5" class="col">r5c5</td>
<td id="r5c6" class="col">r5c6</td>
<td id="r5c7" class="col">r5c7</td>
<td id="r5c8" class="col">r5c8</td>
<td id="r5c9" class="col">r5c9</td>
</tr>
<tr id="r6" class="row">
<td id="r6c0" class="col">r6c0</td>
<td id="r6c1" class="col">r6c1</td>
<td id="r6c2" class="col">r6c2</td>
<td id="r6c3" class="col">r6c3</td>
<td id="r6c4" class="col">r6c4</td>
<td id="r6c5" class="col">r6c5</td>
<td id="r6c6" class="col">r6c6</td>
<td id="r6c7" class="col">r6c7</td>
<td id="r6c8" class="col">r6c8</td>
<td id="r6c9" class="col">r6c9</td>
</tr>
<tr id="r7" class="row">
<td id="r7c0" class="col">r7c0</td>
<td id="r7c1" class="col">r7c1</td>
<td id="r7c2" class="col">r7c2</td>
<td id="r7c3" class="col">r7c3</td>
<td id="r7c4" class="col">r7c4</td>
<td id="r7c5" class="col">r7c5</td>
<td id="r7c6" class="col">r7c6</td>
<td id="r7c7" class="col">r7c7</td>
<td id="r7c8" class="col">r7c8</td>
<td id="r7c9" class="col">r7c9</td>
</tr>
<tr id="r8" class="row">
<td id="r8c0" class="col">r8c0</td>
<td id="r8c1" class="col">r8c1</td>
<td id="r8c2" class="col">r8c2</td>
<td id="r8c3" class="col">r8c3</td>
<td id="r8c4" class="col">r8c4</td>
<td id="r8c5" class="col">r8c5</td>
<td id="r8c6" class="col">r8c6</td>
<td id="r8c7" class="col">r8c7</td>
<td id="r8c8" class="col">r8c8</td>
<td id="r8c9" class="col">r8c9</td>
</tr>
<tr id="r9" class="row">
<td id="r9c0" class="col">r9c0</td>
<td id="r9c1" class="col">r9c1</td>
<td id="r9c2" class="col">r9c2</td>
<td id="r9c3" class="col">r9c3</td>
<td id="r9c4" class="col">r9c4</td>
<td id="r9c5" class="col">r9c5</td>
<td id="r9c6" class="col">r9c6</td>
<td id="r9c7" class="col">r9c7</td>
<td id="r9c8" class="col">r9c8</td>
<td id="r9c9" class="col">r9c9</td>
</tr>
</table>
If ids seem too heavy and cumbersome, you can select any cell on a table by using the pseudo-selectors nth-child and nth-of-type.
Example:
Target:* You want the 3rd <td> on the 5th row to have red text.
CSS:
table tbody tr:nth-of-type(5) td:nth-of-type(3) { color: red; }
jQuery:
$("table tbody tr:nth-of-type(5) td:nth-of-type(3)").css('color', 'red');
JavaScript:
var tgt = document.querySelector("table tbody tr:nth-of-type(5) td:nth-of-type(3)");
tgt.style.color = "red";
*Assuming that the target element has a table with a <tbody>
Demo 2
fieldset {
width: 50vw;
height: 55px;
margin: 10px auto;
padding: 3px;
}
input {
width: 40px;
height: 20px;
margin: 5px 10px;
}
table {
table-layout: fixed;
border-collapse: collapse;
border: 3px ridge #666;
width: 50vw;
height: 50vh;
margin: 20px auto;
}
td {
height: 20px;
width: 20px;
border: 1px inset grey;
font-size: 8px;
}
<fieldset>
<legend>Rows & Columns</legend>
<input id="rows" type="number" min="0" max="100" />
<input id="cols" type="number" min="0" max="100" />
<button id="btn1">Build</button>
</fieldset>
<table id="t1"></table>
<script>
var t1 = document.getElementById('t1');
var rows = document.getElementById('rows');
var cols = document.getElementById('cols');
var btn1 = document.getElementById('btn1');
btn1.addEventListener('click', function(e) {
var R = rows.value;
var C = cols.value;
var rowX = [];
var colY = [];
for (var r = 0; r < R; r++) {
var row = document.createElement('tr');
row.setAttribute('id', 'r' + r);// Each row will have a numbered id (ex. r0 is row 1)
row.classList.add('row');
rowX.push(row);
t1.appendChild(row)
for (var c = 0; c < C; c++) {
var col = document.createElement('td');
col.setAttribute('id', 'r' + r + 'c' + c);// Each cell will have a numbered id representing it's location (ex. r3c0 is located on row 4 column 1)
col.innerHTML = col.id;
col.classList.add('col');
colY.push(col);
row.appendChild(col);
}
}
}, false);
</script>
I am currently creating a basic javascript car racer whereby the car is a an HTML tr element placed in a td. I want to have it that when I push the key "e" player one will move and if the "d" key is pressed player 2 will move. I want to do this by using an eventListener to have it that when the key is pressed the car will move from its original td element to the next td element and remove the car from the previous. This will make it look like the car has moved. I do not know how to have this element moved using the key press but my code is below. Thanks for the help!
document.addEventListener('DOMContentLoaded', function() {
//run the code
function move = function(player){
/*
psuedo code:
if Keypressed = "E"
then move first car forward
else d move second car forward
if player1 has moved to the end
then end the game
else for player 2
set a var to add up the total moves, user can then easily adapted the length of the road and have it match
the var total.
*/
}
function keyPress = function(e){
if (e.charCode == "e"){
//move player one
}
else if (e.charCode == "d"){
//move player 2
}
else{
alert("Invalid key stroke");
}
}
})
.racer_table td {
background-color: white;
height: 50px;
width: 50px;
border: 5px;
border-color: black;
}
.racer_table td.active {
background-color: black;
}
<link rel="stylesheet" type = "text/css" href="style.css">
<script type="text/javascript" src="racer.js"> </script>
<body>
<table class="racer_table">
<tr id="player1_strip">
<td class="active"></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr id="player2_strip">
<td class="active"></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</body>
</html>
I would set a var with the object then use jquery's 'next' function for sibling object.
if you add this button <button id="x1"/> this will work as an example:
$("#x1").click(function() {
var active = $("#player1_strip").children(".active");
active.next().addClass("active");
active.removeClass("active");
});
No jQuery solution. There is probably some other solution without need for an id, but I think this one is cleaner. You add an id to each <td> like 'tile1e', 'tile2e' etc. Then, your keypress function would look like this:
function keyPress = function(e){
if (e.charCode == "e"){
var tile = document.querySelector("#player1_strip > .active"); // get player tile
var nextTile = 'tile' + (tile.id[4] + 1) + 'e'; // get id of the next tile
tile.className = "";
document.getElementById(nextTile).className = "active";
}
else if (e.charCode == "d"){
var tile = document.querySelector("#player2_strip > .active"); // get player tile
var nextTile = 'tile' + (tile.id[4] + 1) + 'd'; // get id of the next tile
tile.className = "";
document.getElementById(nextTile).className = "active";
}
else{
alert("Invalid key stroke");
}
}
and the table something like this
<table class="racer_table">
<tr id="player1_strip">
<td id='tile0e' class="active"></td>
<td id='tile1e'></td>
<td id='tile2e'></td> <!-- move active to the next empty td element -->
<td id='tile3e'></td>
<td id='tile4e'></td>
<td id='tile5e'></td>
<td id='tile6e'></td>
<td id='tile7e'></td>
<td id='tile8e'></td>
<td id='tile9e'></td>
</tr>
<tr id="player2_strip">
<td id='tile0d' class="active"></td>
<td id='tile1d'></td>
<td id='tile2d'></td>
<td id='tile3d'></td>
<td id='tile4d'></td>
<td id='tile5d'></td>
<td id='tile6d'></td>
<td id='tile7d'></td>
<td id='tile8d'></td>
<td id='tile9d'></td>
</tr>
</table>
I hope you get the idea behind this.
But feel free to use the jQuery solution if you are comfortable with that, it is so much simpler.
I have the table below which hides all the child rows by default.
I'd like to toggle all child rows right underneath the corresponding clicked root row. That is, the n .child rows next to the clicked .root. How can I do this in pure Javascript?
.hidden {
display:none;
}
<table>
<tr>
<td>Root</td>
</tr>
<tr class="hidden">
<td>Child 1</td>
</tr>
<tr class="hidden">
<td>Child 2</td>
</tr>
<tr class="hidden">
<td>Child 3</td>
</tr>
<tr class="hidden">
<td>Child 4</td>
</tr>
<tr>
<td>Root</td>
</tr>
<tr class="hidden">
<td>Child 1</td>
</tr>
<tr class="hidden">
<td>Child 2</td>
</tr>
</table>
If, what you want to do is to remove the hidden classname from all the rows after the clicked one until you get to a row that is not hidden, then you can do this:
function func(root) {
var row = root.parentNode.parentNode;
row = nextElement(row, "tr");
while (row && row.className === "hidden") {
row.className = "";
row = nextElement(row, "tr");
}
}
function nextElement(start, tag) {
tag = tag.toUpperCase();
start = start.nextSibling;
while (start) {
if (start.tagName === tag) {
return start;
} else {
start = start.nextSibling;
}
}
return start;
}
Working demo: http://jsfiddle.net/jfriend00/dvg6j9or/
Here's another version that works off the array of rows and uses a parent search to find the right level of the table:
function func(root) {
var table = findParentTag(root, "table");
var currentRow = findParentTag(root, "tr");
var rows = Array.prototype.slice.call(table.querySelectorAll("tr"));
var currentIndex = rows.indexOf(currentRow) + 1;
// now traverse rows until you find one that is different than the starting row
for (; currentIndex < rows.length; ++currentIndex) {
if (rows[currentIndex].className.indexOf("hidden") !== -1) {
rows[currentIndex].className = "";
} else {
break;
}
}
}
function findParentTag(start, tag) {
tag = tag.toUpperCase();
while (start && start.tagName !== tag) {
start = start.parentNode;
}
return start;
}
Working demo: http://jsfiddle.net/jfriend00/hut56fLg/
I have HTML table
When I click on it's cell (not header) this cell is highlighted in red. the rest cells in the same row are highlighted in pink color.
I want to control this red cell using arrow keys.
Here is my HTML code:
<html>
<head>
<title>Table Highlight</title>
</head>
<style>
.highlighted{
color: white;
background-color: red;
}
tr.normal td {
color: black;
background-color: white;
}
.highlighted1 {
color: white;
background-color: pink;
}
</style>
<body onLoad="onLoad()" >
<table id="tbl" border="1">
<tr>
<td style="width:70">Id
<td style="width:70">Name
<td style="width:70">Year
<td style="width:70">Task
</tr>
<tr>
<td style="height:20">
<td style="height:20">
<td style="height:20">
<td style="height:20">
</tr>
<tr>
<td style="height:20">
<td style="height:20">
<td style="height:20">
<td style="height:20">
</tr>
<tr>
<td style="height:20">
<td style="height:20">
<td style="height:20">
<td style="height:20">
</tr>
</table>
<script>
tbl = document.getElementById('tbl');
tbl2 = document.getElementById('tbl');
cnt = 0;
function onLoad() {
td = document.getElementsByTagName('td');
for(j=4;j<td.length;j++){
td[j].innerHTML = " ";
td[j].onclick = function(){highlight(this)}
td[j].onkeydown=function(){key_highlight(event)}
}
}
function key_highlight(oo) {
td = document.getElementsByTagName('td');
for(n=1;i<tbl2.rows;n++){
cnt=0;
/*
if(cnt > tbl2[i].cells.length) return;
highlight(tbl2[i]);
}*/
alert();
//if(oo.keyCode==39)
if(cnt>tbl2.rows[n].cells.length) return;
highlight(tbl2[n].cells);
cnt++;
}
}
function highlight(o) {
for (i=0; i<tbl.cells.length; i++){
tbl.cells[i].className="normal";
tbl.cells[i].parentNode.className="normal";
}
o.parentNode.className = (o.className == "highlighted1")?"normal":"highlighted1";;
o.className=(o.className == "highlighted")?"normal":"highlighted";
}
</script>
</body>
You need to check for keycode on keydown event for the document and apply "highlighted" class to respective td.
HTML :
<table id="tbl" border="1">
<tr>
<td style="width:70" class="highlighted">Id</td>
<td style="width:70">Name</td>
<td style="width:70">Year</td>
<td style="width:70">Task</td>
</tr>
<tr>
<td style="height:20"> 1</td>
<td style="height:20"> Bob</td>
<td style="height:20"> 1998</td>
<td style="height:20"> NA</td>
</tr>
<tr>
<td style="height:20">2</td>
<td style="height:20">Maz</td>
<td style="height:20">2000</td>
<td style="height:20">QA</td>
</tr>
<tr>
<td style="height:20">3</td>
<td style="height:20">Mary</td>
<td style="height:20">1999</td>
<td style="height:20">Code</td>
</tr>
</table>
Jquery code:
var active;
$(document).keydown(function(e){
active = $('td.highlighted').removeClass('highlighted');
var x = active.index();
var y = active.closest('tr').index();
if (e.keyCode == 37) {
x--;
}
if (e.keyCode == 38) {
y--;
}
if (e.keyCode == 39) {
x++
}
if (e.keyCode == 40) {
y++
}
active = $('tr').eq(y).find('td').eq(x).addClass('highlighted');
});
Refer to fiddle for live Demo
You have to keep track of cell position (cellX,cellY) both when you click and when you press a key. Add a global keypress handler (document.onkeydown = ) and increment or decrement cellX and cellY according to the keys pressed.
Chech the running fiddle:
http://jsfiddle.net/aehq9c6f/1/
tbl = document.getElementById('tbl');
tbl2 = document.getElementById('tbl');
var cellX=null;
var cellY=null;
document.onkeydown = keyPressed;
cnt = 0;
function onLoad() {
td = document.getElementsByTagName('td');
for(j=4;j<td.length;j++){
td[j].innerHTML = " ";
td[j].onclick = function(){highlight(this)}
td[j].onkeydown=function(){key_highlight(event)}
}
}
function keyPressed(e) {
var code;
if (!e) var e = window.event;
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
var KeyVal=getCharDesc(code);
var maxX=4;
var maxY=4;
if(KeyVal=="left") {
if(cellX===null) cellX=maxX;
if(cellY===null) cellY=maxY/2;
cellX--;
if(cellX<0) cellX=maxX-1;
highlight(tbl.rows[cellY].cells[cellX]);
} else if(KeyVal=="right") {
if(cellX===null) cellX=-1;
if(cellY===null) cellY=maxY/2;
cellX++;
if(cellX>maxX-1) cellX=0;
highlight(tbl.rows[cellY].cells[cellX]);
} else if(KeyVal=="up") {
if(cellX===null) cellX=maxX/2;
if(cellY===null) cellY=maxY;
cellY--;
if(cellY<1) cellY=maxY-1; // avoid top row
highlight(tbl.rows[cellY].cells[cellX]);
} else if(KeyVal=="down") {
if(cellX===null) cellX=maxX/2;
if(cellY===null) cellY=0; // avoid top row
cellY++;
if(cellY>maxY-1) cellY=1; // avoid top row
highlight(tbl.rows[cellY].cells[cellX]);
}
}
function getCharDesc(char_code) {
switch(char_code) {
case 37:return "left";
case 38:return "up";
case 39:return "right";
case 40:return "down";
}
}
function highlight(o) {
for (var i = 0, row; row = tbl.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
row.cells[j].className="normal";
row.cells[j].parentNode.className="normal";
if(row.cells[j]===o) {
cellX=j;
cellY=i;
// alert(cellX+", "+cellY);
}
}
}
o.parentNode.className = (o.className == "highlighted1")?"normal":"highlighted1";;
o.className=(o.className == "highlighted")?"normal":"highlighted";
}
The extra tests like
if(cellX===null) ...
are to allow first keypress if nothing is selected (cellX and cellY are null), if you hit left, cursor will start from right, etc.. (window must have focus so first click window to test).
I changed tbl.cells[i] to tbl.rows[i].cells[j] because on my setup (Firefox) table.cells[..] was not defined