I am trying to figure out how to make all 5 columns and rows searchable. At the moment it only searches via the first column (DATE). Could someone please assist me with possibly making it search all the columns and rows please? I have included the HTML, CSS and javascript to try to provide as much information as possible.
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
#myInput {
background-image: url('/css/searchicon.png'); /* Add a search icon to input */
background-position: 10px 12px; /* Position the search icon */
background-repeat: no-repeat; /* Do not repeat the icon image */
width: 100%; /* Full-width */
font-size: 16px; /* Increase font-size */
padding: 12px 20px 12px 40px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 12px; /* Add some space below the input */
}
#myTable {
border-collapse: collapse; /* Collapse borders */
width: 100%; /* Full-width */
border: 1px solid #ddd; /* Add a grey border */
font-size: 18px; /* Increase font-size */
}
#myTable th, #myTable td {
text-align: left; /* Left-align text */
padding: 12px; /* Add padding */
}
#myTable tr {
/* Add a bottom border to all table rows */
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
/* Add a grey background color to the table header and on hover */
background-color: #f1f1f1;
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">
<table id="myTable">
<tr class="header">
<th style="width:20%;">Date</th>
<th style="width:20%;">Home</th>
<th style="width:20%;">Time</th>
<th style="width:20%;">Away</th>
<th style="width:20%;">City</th>
</tr>
<tr>
<td>08/01/2018</td>
<td>SPAIN</td>
<td>16:30 ET</td>
<td>USA</td>
<td>BARCELONA</td>
</tr>
<tr>
<td>08/02/2018</td>
<td>BOLIVIA</td>
<td>18:30 ET</td>
<td>PORTUAL</td>
<td>MADRID</td>
</tr>
<tr>
<td>08/03/2018</td>
<td>PUERTO RICO</td>
<td>18:30 ET</td>
<td>CANADA</td>
<td>CHICAGO</td>
</tr>
<tr>
<td>08/04/2018</td>
<td>MEXICO</td>
<td>19:30 ET</td>
<td>ENGLAND</td>
<td>LONDON</td>
</tr>
</table>
Using your existing code, loop through the table cells just as you loop through the table rows.
Below, I hide each row. For each row, if text in a cell matches the search term, that row is shown and the loop continues to the next row.
I'm also ignoring the table header by using tBodies to limit the search to <tr> elements that are within the first <tbody>. Alternatively, you could check that <td> elements exist in the row before searching; something like: if (tds.length) > 0.
function performSearch() {
// Declare search string
var filter = searchBox.value.toUpperCase();
// Loop through first tbody's rows
for (var rowI = 0; rowI < trs.length; rowI++) {
// define the row's cells
var tds = trs[rowI].getElementsByTagName("td");
// hide the row
trs[rowI].style.display = "none";
// loop through row cells
for (var cellI = 0; cellI < tds.length; cellI++) {
// if there's a match
if (tds[cellI].innerHTML.toUpperCase().indexOf(filter) > -1) {
// show the row
trs[rowI].style.display = "";
// skip to the next row
continue;
}
}
}
}
// declare elements
const searchBox = document.getElementById('searchBox');
const table = document.getElementById("myTable");
const trs = table.tBodies[0].getElementsByTagName("tr");
// add event listener to search box
searchBox.addEventListener('keyup', performSearch);
#searchBox {
box-sizing: border-box;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#myTable {
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
font-size: 18px;
}
#myTable th,
#myTable td {
text-align: left;
padding: 12px;
}
#myTable th {
width: 20%;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header,
#myTable tr:hover {
background-color: #f1f1f1;
}
<input type="text" id="searchBox" placeholder="Search for names..">
<table id="myTable">
<thead>
<tr class="header">
<th>Date</th>
<th>Home</th>
<th>Time</th>
<th>Away</th>
<th>City</th>
</tr>
</thead>
<tbody>
<tr>
<td>08/01/2018</td>
<td>SPAIN</td>
<td>16:30 ET</td>
<td>USA</td>
<td>BARCELONA</td>
</tr>
<tr>
<td>08/02/2018</td>
<td>BOLIVIA</td>
<td>18:30 ET</td>
<td>PORTUAL</td>
<td>MADRID</td>
</tr>
<tr>
<td>08/03/2018</td>
<td>PUERTO RICO</td>
<td>18:30 ET</td>
<td>CANADA</td>
<td>CHICAGO</td>
</tr>
<tr>
<td>08/04/2018</td>
<td>MEXICO</td>
<td>19:30 ET</td>
<td>ENGLAND</td>
<td>LONDON</td>
</tr>
</tbody>
</table>
100% working for unlimited columns !
<input class="form-control" type="text" id="myInput" placeholder="Search ..." onkeyup="searchTableColumns()">
<table id="myTable">
.....
.....
.....
</table
function searchTableColumns() {
// Declare variables
var input, filter, table, tr, i, j, column_length, count_td;
column_length = document.getElementById('myTable').rows[0].cells.length;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) { // except first(heading) row
count_td = 0;
for(j = 1; j < column_length-1; j++){ // except first column
td = tr[i].getElementsByTagName("td")[j];
/* ADD columns here that you want you to filter to be used on */
if (td) {
if ( td.innerHTML.toUpperCase().indexOf(filter) > -1) {
count_td++;
}
}
}
if(count_td > 0){
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
When you do tr[i].getElementsByTagName("td")[0];, you only select the date column, wich is why it only search in that one. You are going to have to loop through all the coumn and set a boolean to true if you find it at least once.
Something like that:
var found = false;
var td = tr[i].getElementsByTagName("td");
for(j = 0; j < td.length; j++) {
if (td[j].innerHTML.toUpperCase().indexOf(filter) > -1) {
//if found at least once it is set to true
found = true;
}
}
//only hides or shows it after checking all columns
if(found){
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
a compact version of the above code, credit to #showdev
/**
* HTML Search for any table
*
* #param element searchBox
* #param string tableBody
*/
function performSearch(searchBox,tableBody) {
let trs = $('#'+tableBody).find('tr');
// Declare search string
let filter = searchBox.value.toUpperCase();
// Loop through first tbody's rows
for (let rowI = 0; rowI < trs.length; rowI++) {
// define the row's cells
let tds = trs[rowI].getElementsByTagName("td");
// hide the row
trs[rowI].style.display = "none";
// loop through row cells
for (let cellI = 0; cellI < tds.length; cellI++) {
// if there's a match
if (tds[cellI].innerHTML.toUpperCase().indexOf(filter) > -1) {
// show the row
trs[rowI].style.display = "";
// skip to the next row
continue;
}
}
}
}
Use it like onkeyup="performSearch(this,'smsTableBody')"
Related
I've got a table of records and I've got a text field above it which dynamically filters the records on a specific table column. I implemented it following this handy How-To https://www.w3schools.com/howto/howto_js_filter_table.asp
Now, this works as advertised, but I'm looking to modify it so that the filter looks at all columns, not just one of them. In the example from the How-To, I'd like to be able to type a name or a country and for it to return all matches. I tried to do this in the JavaScript:
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
for (j = 0; j < tr.width; j++) {
td = tr[i].getElementsByTagName("td")[j];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}}}}}
The j variable is where I had hoped to additionally loop through the columns for each i, but doing this seems to break the filtering functionality, ie. typing anything has no effect on the records displayed - all records show at all times. Can someone tell me what I'm doing wrong?
You have a couple of errors there:
1. invalid for loop:
for (j = 0; j < tr.width; j++)
There's no such thing as tr.width. Or rather it's a jQuery function, so you're getting a text of it when you type tr.width.
Thus the script breaks, since the for loop clause if invalid.
If you actually called like this tr.width() you would get the pixel width of the element so it wouldn't help you either.
What you need is the <td> count in it. Here's how you get it:
let rowTds = tr[i].getElementsByTagName("td")
for (j = 0; j < rowTds.length; j++){...}
now you can iterate through the all the <td>s in the row.
2. Hide row logic needs revision to multiple column check:
Now you also need to change the logic of the hiding because it will keep hiding a row if the the last <td> didn't match the filter string.
td = tr[i].getElementsByTagName("td")[j];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
break; // this will break the row looping on j after making the row visible.
} else {
tr[i].style.display = "none";
}
}
}
}
}
Conclusion: Full working code adjusted from the W3schools tutorial:
Link: https://www.w3schools.com/code/tryit.asp?filename=FVXZWZMELE1Q
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<style>
* {
box-sizing: border-box;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#myTable {
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
font-size: 18px;
}
#myTable th, #myTable td {
text-align: left;
padding: 12px;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color: #f1f1f1;
}
</style>
</head>
<body>
<h2>My Customers</h2>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Berglunds snabbkop</td>
<td>Sweden</td>
</tr>
<tr>
<td>Island Trading</td>
<td>UK</td>
</tr>
<tr>
<td>Koniglich Essen</td>
<td>Germany</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Italy</td>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
<script>
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
let rowTds = tr[i].getElementsByTagName("td")
for (j = 0; j < rowTds.length; j++){
td = tr[i].getElementsByTagName("td")[j];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
break;
} else {
tr[i].style.display = "none";
}
}
}
}
}
</script>
</body>
</html>
I have a table which I want the first column to not move when I am scrolling horizontally. This code below works great for the first column of td's but does not work for the tr's. I have stepped through the code and it all appears to set the values I am expected, but the tr cell does not move with the td cells.
window.onscroll = function()
{
var scrollPosX = window.scrollX;
var theTable = document.getElementById("tablename"),
thead = theTable.getElementsByTagName("thead")[0];
tbody = theTable.getElementsByTagName("tbody")[0];
hrCell = thead.getElementsByTagName("tr")[0];
hrCell.style.left = scrollPosX;
rCells = tbody.getElementsByTagName("td");
for(var i = 0; i < rCells.length; i++)
{
rCells[i].style.left = scrollPosX;
}
}
JQuery is not an option in this problem as the program I am working on does not support it.
<style>
table
{
border: solid black 1px;
}
td{
min-width: 300px;
border: solid black 1px;
}
#run_gen_table td:first-child, #run_gen_table th:first-child
{
background-color: white;
position: relative;
}
</style>
<table id="tablename">
<thead id="headname">
<tr><th>Run No.</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>10</th></tr>
</thead>
<tbody id="bodyname">
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
</tbody>
</table>
I have not tested it but your code would alter all the td elements, not just the first column. A better approach would be to use document.querySelector() to select the first td and th elements.
window.onscroll = function()
{
var scrollPosX = window.scrollX;
var rCells = document.querySelector("#tablename th:first-child, #tablename td:first-child");
for(var i = 0; i < rCells.length; i++)
{
rCells[i].style.left = scrollPosX;
}
}
I'm currently busy with a project that has an html table with games and years they are launched. I'm trying to create a button that when clicked will hide any row that wasn't launched in 2016.
So my thoughts behind this process are that I'll create a forloop to go through each row and column to find the year value and if it's 2016 leave it alone, if not, hide it.
However I'm having an issue on the looping part.
<script>
function GameSearchLoop() {
var table = document.getElementsByClassName(table);
if (table == null) {
console.log("Table Not Found");
}
else {
console.log("Table Found");
}
var rowLength = table.rows.length;
for (var z = 0; z < rowLength; z++) {
var cells = table.rows.item(z).cells;
var cellLength = cells.length;
console.log("Row Checked");
for (var x = 0; x < cellLength; x++) {
console.log("Column Checked");
}
}
//for (var r = 0, n = table.rows.length; r < n; r++) {
// console.log("Row Checked");
// for (var c = 0, m = table.rows[r].cells.length; c < m; c++) {
// alert(table.rows[r].cells[c].innerHTML);
// console.log("Column Checked");
// }
//}
}
</script>
I've got two different for loops here and neither of them seem to work.
The table is created slightly about this with the same script with the class table attached to it.
When running the code and hitting the button I do see "Table Found" in the console but after that I get a "Cannot read property 'length' of undefined at GameSearchLoop".
Thanks
getElementsByClassName returns a NodeList, a collection. You need the first of these elements:
var table = document.getElementsByClassName(table)[0];
assuming that table is in the first instance a variable containing a class-name, and that your table is the first, or only, one of these.
Or alternatively,
var rowLength = table[0].rows.length;
Better yet, give your table an ID and use getElementById.
I found it form W3schools i hope this will help
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
box-sizing: border-box;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#myTable {
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
font-size: 18px;
}
#myTable th, #myTable td {
text-align: left;
padding: 12px;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color: #f1f1f1;
}
</style>
</head>
<body>
<h2>I picked it from W3schools</h2>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Year</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>2016</td>
<td>Germany</td>
</tr>
<tr>
<td>2017</td>
<td>Sweden</td>
</tr>
<tr>
<td>2016</td>
<td>UK</td>
</tr>
<tr>
<td>2018</td>
<td>Germany</td>
</tr>
<tr>
<td>2019</td>
<td>Canada</td>
</tr>
<tr>
<td>2010</td>
<td>Italy</td>
</tr>
<tr>
<td>2016</td>
<td>UK</td>
</tr>
<tr>
<td>2013</td>
<td>France</td>
</tr>
</table>
<script>
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
</body>
</html>
insted of
var table = document.getElementsByClassName(table);
use
var table = document.getElementsByClassName('some class in string');
i want the entire content of the cell displayed in the cell.
But the content first and the third cell in the first row are overflowing. How do i display the entire content without increasing the width of the table columns?
Can someone suggest a fix:
function sortTable(f,n){
var rows = $('#mytable tbody tr').get();
rows.sort(function(a, b) {
var A = getVal(a);
var B = getVal(b);
if(A < B) {
return -1*f;
}
if(A > B) {
return 1*f;
}
return 0;
});
function getVal(elm){
var v = $(elm).children('td').eq(n).text().toUpperCase();
if($.isNumeric(v)){
v = parseInt(v,10);
}
return v;
}
$.each(rows, function(index, row) {
$('#mytable').children('tbody').append(row);
});
}
var f_errorStringOfCurrentDataSet = 1;
var f_errorStringOfMatchedDataSet = 1;
var f_testCaseNameOfCurrentDataSet = 1;
var f_regexMatched = 1;
$("#errorStringOfCurrentDataSet").click(function(){
f_errorStringOfCurrentDataSet *= -1;
var n = $(this).prevAll().length;
sortTable(f_errorStringOfCurrentDataSet,n);
});
$("#errorStringOfMatchedDataSet").click(function(){
f_errorStringOfMatchedDataSet *= -1;
var n = $(this).prevAll().length;
sortTable(f_errorStringOfMatchedDataSet,n);
});
$("#testCaseNameOfCurrentDataSet").click(function(){
f_testCaseNameOfCurrentDataSet *= -1;
var n = $(this).prevAll().length;
sortTable(f_testCaseNameOfCurrentDataSet,n);
});
$("#regexMatched").click(function(){
f_regexMatched *= -1;
var n = $(this).prevAll().length;
sortTable(f_regexMatched,n);
});
table {
padding: 0;
border-collapse: collapse;
border: 1px solid #ccc;
margin-top: 20px;
table-layout: fixed;
width: 90%;
}
td {
border: 1px solid #ccc;
padding: 5px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
th, td {
overflow: hidden;
padding: 5px;
text-align: left;
}
<!DOCTYPE html>
<html>
<body>
<style>
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<h2>Summary: </h2>
<br>
<br>
<table border="1" id="mytable">
<thead>
<tr>
<th width="25%" id="testCaseNameOfCurrentDataSet">TESTCASENAME</th>
<th width="5%" id="regexMatched">RegexMatched (Yes/No)</th>
<th width="25%" id="errorStringOfCurrentDataSet">ERROR_STRING_CURRENT_DATASET</th>
<th width="25%" id="errorStringOfMatchedDataSet">ERROR_STRING_REF_DATASET</th>
<th width="5%">PICTU Detail</th>
</tr>
</thead>
<tbody>
<tr style="color: red">
<td>moviee.movieemovieemoviee.movieemovieemoviee.movieemovieemoviee.moviee</td>
<td>NO</td>
<td>ABCDE:[bbb-aa-gg 999-99] (Excellent Check) Monkey String ABCDE:[moviee 990-505] moviee to commit 3 small moviee/moviee/moviee: in file /dogg/summariz/abc/mmmm/movieemoviee/moviee/movieemoviee/moviee/movieemoviee/Small/movieemoviee/movieemoviee.1_</td>
<td>ABCDE:[abc-vd-Common 17-69] moviee moviee: moviee moviee moviee moviee moviee moviee</td>
<td><a href=http://mnbvcz01:5601/app/banana#/template/abc-DELETEDD-PICTU?embed=true&reportType=abc&_a=(filters:!(),options:(darkTheme:!f),query:(query_string:(analyze_wildcard:!t,lowercase_DELETEDD_terms:!f,query:'_id:movieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemoviee.movieemovieemoviee%20OR%20_id:17.movieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemovieemoviee.movieemovieemovieemovieemovieemovieemovieemoviee')),title:'abc%20DELETEDD%20PICTU',uiState:())&_g=(refreshInterval:(display:Off,pause:!f,value:0),time:(from:now-1y,mode:quick,to:now))>link</a></td>
</tr>
</tbody>
</table>
<script>
</script>
</body>
</html>
One solution for this is to add word-break: break-word; to td tags.
Here is a fiddle with your code: fiddle link
You can use word-break css property to solve this problem. here is the code replace your table tag with mine
<table border="1" id="mytable" style ="word-break: break-word;">
Hope this was useful to you
I have four tables of soccer players, one for goalkeepers, one for defenders, one for midfielders and one for attackers. I want the user to be able to change the position of a player so that he'll disappear from his current table and appear in another one without a page refresh.
The only method that I can think of is to have each player listed in all four tables but have him hidden for three of them. Then if he changes, I hide him in the current table and show him in another one.
I know how to achieve this, but it seems a bit heavy and I'm wondering if there's a more elegant solution.
You can use appendChild() in pure JavaScript to move a node from one place to another. The node is automatically removed from its old position in the DOM.
To quote the Mozilla Developer Network documentation on appendChild:
If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position (there is no requirement to remove the node from its parent node before appending it to some other node).
This means that a node can't be in two points of the document simultaneously. So if the node already has a parent, it is first removed, then appended at the new position.
The following snippet demonstrates the use of appendChild() to move rows between tables. Click on the move buttons to move an item from one table to the other.
window.onload = function () {
var data = {
like: ['vanilla', 'pistachio', 'squirrels', 'squash', 'mountains'],
dislike: ['chocolate', 'trucks', 'football', 'hard candy', 'valleys']
};
var tables = {};
var moveMe = function () {
this.table = tables[this.table === tables.like ? 'dislike' : 'like'];
this.table.tbody.appendChild(this.tr);
};
Object.keys(data).forEach(function (key) {
var container = document.createElement('div'),
table = tables[key] = document.createElement('table'),
tbody = table.tbody = document.createElement('tbody');
data[key].forEach(function (item) {
var tr = document.createElement('tr'),
td = document.createElement('td');
td.innerHTML = item;
tr.appendChild(td);
tbody.appendChild(tr);
var button = document.createElement('button');
button.innerHTML = 'move';
button.onclick = moveMe;
button.table = table;
button.tr = tr;
td.appendChild(button);
});
table.appendChild(tbody);
var header = document.createElement('h2');
header.innerHTML = key;
container.appendChild(header);
container.appendChild(table);
container.className = 'container';
document.getElementById('wrapper').appendChild(container);
});
};
* {
box-model: border-box;
}
body {
font-family: sans-serif;
}
#wrapper {
width: 450px;
}
.container {
display: inline-block;
width: 200px;
padding: 10px;
}
h2 {
margin: 5px 0;
color: #666;
}
table {
width: 200px;
border-collapse: collapse;
}
td {
color: #333;
padding: 10px;
border: 1px solid #bbb;
position: relative;
}
td button {
position: absolute;
right: 5px;
top: 5px;
border: 2px solid #ccc;
border-radius: 5px;
background: #fff;
font-size: 12px;
}
td button:hover {
outline: none;
border-color: #888;
cursor: pointer;
}
<div id="wrapper"></div>
You could also use table api to manipulate your tables, here is a sample:
moving 1,1,1 element to 3,1,1
var tables = document.querySelectorAll("table")
var elementToMove = tables[0].rows[0].cells[0]
var destination = tables[2].rows[0].cells[0]
destination.innerHTML = elementToMove.innerHTML
elementToMove.innerHTML = ""
<table>
<tr>
<td>1,1,1</td>
<td>1,1,2</td>
<td>1,1,3</td>
</tr>
<tr>
<td>1,2,1</td>
<td>1,2,2</td>
<td>1,2,3</td>
</tr>
<tr>
<td>1,3,1</td>
<td>1,3,2</td>
<td>1,3,3</td>
</tr>
</table>
<br>
<table>
<tr>
<td>2,1,1</td>
<td>2,1,2</td>
<td>2,1,3</td>
</tr>
<tr>
<td>2,2,1</td>
<td>2,2,2</td>
<td>2,2,3</td>
</tr>
<tr>
<td>2,3,1</td>
<td>2,3,2</td>
<td>2,3,3</td>
</tr>
</table>
<br>
<table>
<tr>
<td>3,1,1</td>
<td>3,1,2</td>
<td>3,1,3</td>
</tr>
<tr>
<td>3,2,1</td>
<td>3,2,2</td>
<td>3,2,3</td>
</tr>
<tr>
<td>3,3,1</td>
<td>3,3,2</td>
<td>3,3,3</td>
</tr>
</table>
Note that i'm using innerHTML to access data, but you could identify whatever element you have in the cell and then use the appendChild method to move the element you need